diff --git a/game/client/src/main/java/net/minecraft/client/gui/MainMenuBackground.java b/game/client/src/main/java/net/minecraft/client/gui/MainMenuBackground.java
index 5b0894194..6a29489bc 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/MainMenuBackground.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/MainMenuBackground.java
@@ -22,7 +22,7 @@ import net.minecraft.client.render.tessellator.TessellatorGeneral;
 import net.minecraft.client.render.texturepack.TexturePack;
 import net.minecraft.client.render.texturepack.TexturePackException;
 import net.minecraft.client.util.helper.TexturePackJsonHelper;
-import net.minecraft.core.util.helper.Buffer;
+import net.minecraft.client.util.helper.Buffer;
 import org.lwjgl.opengl.GL41;
 import org.slf4j.Logger;
 
diff --git a/game/client/src/main/java/net/minecraft/client/gui/modelviewer/ScreenModelViewer.java b/game/client/src/main/java/net/minecraft/client/gui/modelviewer/ScreenModelViewer.java
index 8927e5511..169eb5803 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/modelviewer/ScreenModelViewer.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/modelviewer/ScreenModelViewer.java
@@ -24,7 +24,7 @@ import net.minecraft.client.util.helper.Textures;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.item.Item;
 import net.minecraft.core.lang.I18n;
-import net.minecraft.core.util.helper.Buffer;
+import net.minecraft.client.util.helper.Buffer;
 import net.minecraft.core.world.chunk.DisplayChunk;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
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 bcc030c1e..f838cf2f1 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
@@ -3,12 +3,9 @@ package net.minecraft.client.render;
 import net.minecraft.client.render.renderer.GLRenderer;
 import org.jetbrains.annotations.NotNull;
 import org.joml.Math;
-import org.joml.Matrix4f;
 import org.joml.Vector3f;
 import org.joml.Vector4f;
 
-import static net.minecraft.client.render.uniform.UniformBlock.N;
-
 public final class Lighting {
     private Lighting() {
     }
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 a7cf0ac3b..dc821788a 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,7 +10,7 @@ import net.minecraft.client.Minecraft;
 import net.minecraft.client.gui.ScreenPhotoMode;
 import net.minecraft.client.option.enums.LightmapStyle;
 import net.minecraft.client.util.helper.Textures;
-import net.minecraft.core.util.helper.Buffer;
+import net.minecraft.client.util.helper.Buffer;
 import net.minecraft.core.util.helper.Color;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.world.World;
diff --git a/game/client/src/main/java/net/minecraft/client/render/TextureManager.java b/game/client/src/main/java/net/minecraft/client/render/TextureManager.java
index 0bb6b5568..c95484f2f 100644
--- a/game/client/src/main/java/net/minecraft/client/render/TextureManager.java
+++ b/game/client/src/main/java/net/minecraft/client/render/TextureManager.java
@@ -1,7 +1,7 @@
 package net.minecraft.client.render;
 
 import static net.minecraft.client.util.helper.Textures.*;
-import static net.minecraft.core.util.helper.Buffer.*;
+import static net.minecraft.client.util.helper.Buffer.*;
 import static org.lwjgl.opengl.GL12.*;
 
 import java.awt.image.BufferedImage;
@@ -51,7 +51,7 @@ import net.minecraft.client.util.helper.Colors;
 import net.minecraft.client.util.helper.Textures;
 import net.minecraft.core.block.material.MaterialColor;
 import net.minecraft.core.util.collection.NamespaceID;
-import net.minecraft.core.util.helper.Buffer;
+import net.minecraft.client.util.helper.Buffer;
 import net.minecraft.core.util.helper.DyeColor;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -151,7 +151,7 @@ public class TextureManager {
 		}
 
 		for (final AtlasStitcher stitcher : TextureRegistry.atlases){
-			for (final IconCoordinate c : stitcher.textureMap.values()) {
+			for (final IconCoordinate c : stitcher.iconMap.values()) {
 				try {
 					if (c.hasMeta("animation")) {
 						LOGGER.debug("Icon '{}' has 'animation' meta!", c.namespaceId);
@@ -385,15 +385,12 @@ public class TextureManager {
 	 */
 	public void refreshTextures(List<Throwable> errors) {
 		CustomAtlasHandler.beforeRefreshTextures();
-		
-		// Animations may change the size of textures, so they need to be initialized before the atlas is generated
 
-		long start = System.nanoTime();
 		for (AtlasStitcher stitcher : TextureRegistry.atlases){
 			stitcher.preinit();
 		}
-        LOGGER.debug("Took '{}' seconds to load atlases.", (System.nanoTime() - start) / 1_000_000_000d);
 
+		// Animations may change the size of textures, so they need to be initialized before the atlas is generated
 		initDynamicTextures(errors);
 
 		for (AtlasStitcher stitcher : TextureRegistry.atlases){
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 7dbf69160..ff7fa1795 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
@@ -640,19 +640,24 @@ public class WorldRenderer {
 
         this.fogManager.setupFog(FogManager.FOG_MODE_NORMAL, this.farPlaneDistance, partialTicks, GLRenderer.getFogState());
         TextureRegistry.worldAtlas.bind();
-        Lighting.disable();
 
         Debug.change("terrain");
         GLRenderer.pushFrame();
-        GLRenderer.setShader(Shaders.WORLD);
-        GLRenderer.globalSetUniforms(Shaders.WORLD);
+        GL41.glActiveTexture(GL41.GL_TEXTURE2);
+        TextureRegistry.worldAtlas.layerTextureMap.get("emissive").bind();
+//        GL41.glActiveTexture(GL41.GL_TEXTURE3);
+//        TextureRegistry.worldAtlas.layerTextureMap.get("maskColor").bind();
+        GL41.glActiveTexture(GL41.GL_TEXTURE0);
+
+        GLRenderer.setShader(Shaders.TERRAIN);
+        GLRenderer.globalSetUniforms(Shaders.TERRAIN);
         this.lightmapHelper.enableLightmapRendering();
         this.mc.terrainRenderer.renderSolidTerrain(partialTicks);
         GLRenderer.popFrame();
 
+        Lighting.enableLight();
         Debug.change("entities");
         GLRenderer.setBlendFunc(BlendFactor.SRC_ALPHA, BlendFactor.ONE_MINUS_SRC_ALPHA);
-        Lighting.enableLight();
         renderGlobal.renderEntities(this.mc.activeCamera, partialTicks);
 
         Debug.change("particles");
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModel.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModel.java
index 8118e1a60..240654c51 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModel.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModel.java
@@ -1,7 +1,6 @@
 package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.tessellator.TessellatorGeneral;
 import net.minecraft.core.block.Block;
@@ -13,9 +12,7 @@ import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.useless.dragonfly.DisplayPos;
 
-public abstract class BlockModel<T extends BlockLogic>
-{
-    public static boolean ENABLE_DIRECTIONAL_LIGHTING = true;
+public abstract class BlockModel<T extends BlockLogic> {
     public static final float[] SIDE_LIGHT_MULTIPLIER = {0.5f, 1.0f, 0.8f, 0.8f, 0.6f, 0.6f};
     public static final float FULL_CUBE_THRESHOLD = 1.0f / 16.0f;
 
@@ -23,10 +20,9 @@ public abstract class BlockModel<T extends BlockLogic>
     public BlockModel(final Block<T> block){
         this.block = block;
     }
-    public abstract boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos);
-    public abstract boolean renderOverbright(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos);
+    public abstract boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos);
     public abstract boolean renderNoCulling(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos);
-    public abstract boolean renderWithOverrideTexture(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos, IconCoordinate textureIndex);
+    public abstract boolean renderWithOverrideTexture(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos, IconCoordinate textureIndex);
     public abstract void renderStandalone(@NotNull TessellatorGeneral tessellator, int metadata, int lightmapCoord);
 
     public abstract boolean shouldItemRender3d();
@@ -40,9 +36,6 @@ public abstract class BlockModel<T extends BlockLogic>
     public abstract @Nullable IconCoordinate getOverlayTexture(int meta);
     public abstract int particleColorIndex(@NotNull WorldSource worldSource, @NotNull TilePosc tilePos, @NotNull Side side, int meta);
 
-    public boolean hasOverbright(){
-        return false;
-    }
     public boolean isRetro() {
         return Minecraft.getMinecraft().currentWorld != null && Minecraft.getMinecraft().currentWorld.isRetro();
     }
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelActivator.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelActivator.java
index 4d773ef7f..425153ec1 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelActivator.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelActivator.java
@@ -21,16 +21,6 @@ public class BlockModelActivator<T extends BlockLogic> extends BlockModelVeryRot
 
     public BlockModelActivator(Block<T> block) {
         super(block);
-        this.overbrightTextures
-            .set("minecraft:block/activator/bottom_active_overlay", Side.BOTTOM)
-            .set("minecraft:block/activator/top_active_overlay", Side.TOP)
-            .set("minecraft:block/activator/front_active_overlay", Side.SOUTH)
-            .set("minecraft:block/activator/side_active_overlay", Side.WEST, Side.EAST, Side.NORTH);
-    }
-
-    @Override
-    public boolean hasOverbright() {
-        return true;
     }
 
     @Override
@@ -41,11 +31,4 @@ public class BlockModelActivator<T extends BlockLogic> extends BlockModelVeryRot
             return super.getBlockTextureFromSideAndMetadata(side, data);
         }
     }
-
-    @Override
-    public @Nullable IconCoordinate getBlockOverbrightTextureFromSideAndMeta(@NotNull Side side, int data) {
-        boolean isPowered = (data & BlockLogicActivator.MASK_POWERED) != 0;
-        if (!isPowered) return null;
-        return super.getBlockOverbrightTextureFromSideAndMeta(side, data);
-    }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelAlgae.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelAlgae.java
index 927065ffe..60628cccf 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelAlgae.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelAlgae.java
@@ -1,7 +1,7 @@
 package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.block.color.BlockColorDispatcher;
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
+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;
@@ -17,7 +17,7 @@ public class BlockModelAlgae<T extends BlockLogic> extends BlockModelStandard<T>
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         AABBdc bounds = this.block.getBoundsFromState(worldSource, tilePos);
         tessellator.setLightmapCoord1i(this.block.getLightmapCoord(worldSource, tilePos));
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelAxisAligned.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelAxisAligned.java
index 0bd3af191..e7e375603 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelAxisAligned.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelAxisAligned.java
@@ -1,6 +1,6 @@
 package net.minecraft.client.render.block.model;
 
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
+import net.minecraft.client.render.tessellator.TessellatorGeneral;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.core.block.Block;
@@ -20,7 +20,7 @@ public class BlockModelAxisAligned<T extends BlockLogic> extends BlockModelStand
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         int meta = worldSource.getBlockData(tilePos);
         Axis axis = BlockLogicAxisAligned.metaToAxis(meta);
         switch (axis) {
@@ -56,13 +56,6 @@ public class BlockModelAxisAligned<T extends BlockLogic> extends BlockModelStand
         return super.getBlockTextureFromSideAndMetadata(rotated, data);
     }
 
-    @Override
-    public @Nullable IconCoordinate getBlockOverbrightTextureFromSideAndMeta(@NotNull Side side, int data) {
-        Side rotated = getRotatedSide(side, data);
-        if (rotated == Side.NONE) return null;
-        return super.getBlockOverbrightTextureFromSideAndMeta(rotated, data);
-    }
-
     public Side getRotatedSide(Side side, int data) {
         int d = (6 * (data & 3) + side.getId());
         return d < Sides.orientationLookUpXYZAligned.length ? Side.getSideById(Sides.orientationLookUpXYZAligned[d]) : Side.NONE;
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelBasket.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelBasket.java
index 455c2be57..4be4cc289 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelBasket.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelBasket.java
@@ -1,6 +1,6 @@
 package net.minecraft.client.render.block.model;
 
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
+import net.minecraft.client.render.tessellator.TessellatorGeneral;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.core.block.Block;
@@ -19,7 +19,7 @@ public class BlockModelBasket<T extends BlockLogicBasket> extends BlockModelStan
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         AABBd bounds = new AABBd(this.block.getBounds());
         // Render basket
         final float onePix = 1.0f / 16;
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelBed.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelBed.java
index 2e37212dc..e2f3ba68c 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelBed.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelBed.java
@@ -1,6 +1,6 @@
 package net.minecraft.client.render.block.model;
 
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
+import net.minecraft.client.render.tessellator.TessellatorGeneral;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.core.block.Block;
@@ -29,7 +29,7 @@ public class BlockModelBed<T extends BlockLogic> extends BlockModelStandard<T> {
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         TilePos queryPos = new TilePos();
         AABBd bounds = new AABBd(this.block.getBoundsFromState(worldSource, tilePos));
         renderBlocks.enableAO = true;
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelBrazier.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelBrazier.java
index b6a23d24e..aa39973d3 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelBrazier.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelBrazier.java
@@ -1,6 +1,5 @@
 package net.minecraft.client.render.block.model;
 
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.client.render.tessellator.TessellatorGeneral;
@@ -26,7 +25,7 @@ public class BlockModelBrazier<T extends BlockLogicBrazier>
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         TilePos queryPos = new TilePos();
         tessellator.setColorOpaque1i(0xFFFFFF);
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCactus.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCactus.java
index cfeb4ec06..5b029acf9 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCactus.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCactus.java
@@ -1,7 +1,6 @@
 package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.tessellator.TessellatorGeneral;
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.util.helper.Side;
@@ -17,7 +16,7 @@ public class BlockModelCactus<T extends BlockLogic> extends BlockModelStandard<T
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         final float sidesOffset = 0.0625F;
 
         AABBd bounds = new AABBd(this.block.getBounds());
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCandle.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCandle.java
index 973e02383..809d8f7a1 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCandle.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCandle.java
@@ -1,6 +1,6 @@
 package net.minecraft.client.render.block.model;
 
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
+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;
@@ -15,7 +15,7 @@ public class BlockModelCandle<T extends BlockLogic> extends BlockModelStandard<T
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         boolean isLit = (worldSource.getBlockData(tilePos) & 0b00000001) == 0;
         float brightness = isLit ? 1.0f : renderBlocks.getBlockBrightness(worldSource, tilePos);
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelChest.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelChest.java
index d1f4a7069..f7226e3aa 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelChest.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelChest.java
@@ -1,6 +1,6 @@
 package net.minecraft.client.render.block.model;
 
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
+import net.minecraft.client.render.tessellator.TessellatorGeneral;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.core.block.*;
@@ -46,7 +46,7 @@ public class BlockModelChest<T extends BlockLogic> extends BlockModelStandard<T>
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         int meta = worldSource.getBlockData(tilePos);
         final Direction dir = BlockLogicChest.getDirectionFromMeta(meta);
         switch (dir) {
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCropsPumpkin.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCropsPumpkin.java
index 037ddb1c4..47f1ab21b 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCropsPumpkin.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCropsPumpkin.java
@@ -1,6 +1,6 @@
 package net.minecraft.client.render.block.model;
 
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
+import net.minecraft.client.render.tessellator.TessellatorGeneral;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.core.block.Block;
@@ -32,7 +32,7 @@ public class BlockModelCropsPumpkin<T extends BlockLogic> extends BlockModelStan
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         float brightness = 1.0f;
         tessellator.setLightmapCoord1i(this.block.getLightmapCoord(worldSource, tilePos));
         tessellator.setColorOpaque3f(brightness, brightness, brightness);
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCropsWheat.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCropsWheat.java
index 6d74c9318..2086855af 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCropsWheat.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCropsWheat.java
@@ -1,6 +1,6 @@
 package net.minecraft.client.render.block.model;
 
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
+import net.minecraft.client.render.tessellator.TessellatorGeneral;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.core.block.Block;
@@ -31,7 +31,7 @@ public class BlockModelCropsWheat<T extends BlockLogic> extends BlockModelStanda
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         float brightness = 1.0f;
         tessellator.setLightmapCoord1i(this.block.getLightmapCoord(worldSource, tilePos));
         tessellator.setColorOpaque3f(brightness, brightness, brightness);
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCrossedSquares.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCrossedSquares.java
index 7b185aa07..bf2d2ab94 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCrossedSquares.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCrossedSquares.java
@@ -1,7 +1,6 @@
 package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.block.color.BlockColorDispatcher;
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.tessellator.TessellatorGeneral;
 import net.minecraft.core.block.Block;
@@ -68,7 +67,7 @@ public class BlockModelCrossedSquares<T extends BlockLogic> extends BlockModelSt
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         tessellator.setLightmapCoord1i(this.block.getLightmapCoord(worldSource, tilePos));
 
         int color = BlockColorDispatcher.getInstance().getDispatch(this.block).getWorldColor(worldSource, tilePos, 0);
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCrystallineNetherrack.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCrystallineNetherrack.java
index e6d315aaa..3581b561e 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCrystallineNetherrack.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelCrystallineNetherrack.java
@@ -2,7 +2,6 @@ package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.block.color.BlockColorDispatcher;
 import net.minecraft.client.render.tessellator.TessellatorGeneral;
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.core.block.Block;
@@ -21,7 +20,7 @@ public class BlockModelCrystallineNetherrack<T extends BlockLogic> extends Block
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         AABBdc bounds = this.block.getBoundsFromState(worldSource, tilePos);
         renderBlocks.renderStandardBlock(tessellator, worldSource, this, bounds, tilePos, 1.0f, 1.0f, 1.0f);
         renderBlocks.overrideBlockTexture = this.overlay;
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 442561d01..0a51d39b8 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
@@ -13,7 +13,6 @@ import org.useless.dragonfly.data.block.mojang.BlockModelMojangData;
 import java.util.Objects;
 
 import static net.minecraft.client.render.block.model.BlockModelStandard.BLOCK_TEXTURES;
-import static net.minecraft.client.render.block.model.BlockModelStandard.OVERBRIGHT_TEXTURES;
 import static net.minecraft.client.render.block.model.BlockModelStandard.RETRO_BLOCK_TEXTURES;
 
 public final class BlockModelDispatcher
@@ -407,21 +406,16 @@ public final class BlockModelDispatcher
         addDispatch(new BlockModelStandard<>(Blocks.ORE_REDSTONE_PERMAFROST).setAllTextures(BLOCK_TEXTURES, "minecraft:block/ore/redstone/permafrost"));
 
         addDispatch(new BlockModelStandard<>(Blocks.ORE_REDSTONE_GLOWING_STONE)
-            .setAllTextures(BLOCK_TEXTURES, "minecraft:block/ore/redstone/stone")
-            .setAllTextures(RETRO_BLOCK_TEXTURES, "minecraft:block/ore/redstone/stone_retro")
-            .setAllTextures(OVERBRIGHT_TEXTURES, "minecraft:block/ore/redstone/overlay"));
+            .setAllTextures(BLOCK_TEXTURES, "minecraft:block/ore/redstone/stone_active")
+            .setAllTextures(RETRO_BLOCK_TEXTURES, "minecraft:block/ore/redstone/stone_retro_active"));
         addDispatch(new BlockModelStandard<>(Blocks.ORE_REDSTONE_GLOWING_BASALT)
-            .setAllTextures(BLOCK_TEXTURES, "minecraft:block/ore/redstone/basalt")
-            .setAllTextures(OVERBRIGHT_TEXTURES, "minecraft:block/ore/redstone/overlay"));
+            .setAllTextures(BLOCK_TEXTURES, "minecraft:block/ore/redstone/basalt_active"));
         addDispatch(new BlockModelStandard<>(Blocks.ORE_REDSTONE_GLOWING_LIMESTONE)
-            .setAllTextures(BLOCK_TEXTURES, "minecraft:block/ore/redstone/limestone")
-            .setAllTextures(OVERBRIGHT_TEXTURES, "minecraft:block/ore/redstone/overlay"));
+            .setAllTextures(BLOCK_TEXTURES, "minecraft:block/ore/redstone/limestone_active"));
         addDispatch(new BlockModelStandard<>(Blocks.ORE_REDSTONE_GLOWING_GRANITE)
-            .setAllTextures(BLOCK_TEXTURES, "minecraft:block/ore/redstone/granite")
-            .setAllTextures(OVERBRIGHT_TEXTURES, "minecraft:block/ore/redstone/overlay"));
+            .setAllTextures(BLOCK_TEXTURES, "minecraft:block/ore/redstone/granite_active"));
         addDispatch(new BlockModelStandard<>(Blocks.ORE_REDSTONE_GLOWING_PERMAFROST)
-            .setAllTextures(BLOCK_TEXTURES, "minecraft:block/ore/redstone/permafrost")
-            .setAllTextures(OVERBRIGHT_TEXTURES, "minecraft:block/ore/redstone/overlay"));
+            .setAllTextures(BLOCK_TEXTURES, "minecraft:block/ore/redstone/permafrost_active"));
 
         addDispatch(new BlockModelStandard<>(Blocks.ORE_DIAMOND_STONE)
             .setAllTextures(BLOCK_TEXTURES, "minecraft:block/ore/diamond/stone")
@@ -436,8 +430,7 @@ public final class BlockModelDispatcher
         addDispatch(new BlockModelCrystallineNetherrack<>(Blocks.NETHERRACK_CRYSTALLINE).setAllTextures(BLOCK_TEXTURES, "minecraft:block/nether_crystal/crystal_netherrack"));
 
         addDispatch(new BlockModelStandard<>(Blocks.ORE_NETHERCOAL_NETHERRACK)
-            .setAllTextures(BLOCK_TEXTURES, "minecraft:block/ore/nethercoal/netherrack")
-            .setAllTextures(OVERBRIGHT_TEXTURES, "minecraft:block/ore/nethercoal/netherrack_overlay"));
+            .setAllTextures(BLOCK_TEXTURES, "minecraft:block/ore/nethercoal/netherrack"));
 
         addDispatch(new BlockModelStandard<>(Blocks.BLOCK_COAL).setAllTextures(BLOCK_TEXTURES, "minecraft:block/block_coal"));
         addDispatch(new BlockModelStandard<>(Blocks.BLOCK_IRON)
@@ -464,8 +457,7 @@ public final class BlockModelDispatcher
             .setTex(RETRO_BLOCK_TEXTURES, "minecraft:block/block_diamond/bottom_retro", Side.BOTTOM)
             .setTex(RETRO_BLOCK_TEXTURES, "minecraft:block/block_diamond/side_retro", S_SIDES));
         addDispatch(new BlockModelStandard<>(Blocks.BLOCK_NETHER_COAL)
-            .setAllTextures(BLOCK_TEXTURES, "minecraft:block/block_nethercoal")
-            .setAllTextures(OVERBRIGHT_TEXTURES, "minecraft:block/block_nethercoal_overlay"));
+            .setAllTextures(BLOCK_TEXTURES, "minecraft:block/block_nethercoal"));
         addDispatch(new BlockModelStandard<>(Blocks.BLOCK_STEEL)
             .setTex(BLOCK_TEXTURES, "minecraft:block/block_steel/top", Side.TOP)
             .setTex(BLOCK_TEXTURES, "minecraft:block/block_steel/bottom", Side.BOTTOM)
@@ -501,16 +493,14 @@ public final class BlockModelDispatcher
             .setTex(BLOCK_TEXTURES, "minecraft:block/motion_sensor/idle_front", Side.SOUTH));
         addDispatch(new BlockModelVeryRotatable<>(Blocks.MOTION_SENSOR_ACTIVE)
             .setAllTextures(BLOCK_TEXTURES, "minecraft:block/motion_sensor/side")
-            .setTex(BLOCK_TEXTURES, "minecraft:block/motion_sensor/active_front", Side.SOUTH)
-            .setTex(OVERBRIGHT_TEXTURES, "minecraft:block/motion_sensor/active_front_overlay", Side.SOUTH));
+            .setTex(BLOCK_TEXTURES, "minecraft:block/motion_sensor/active_front", Side.SOUTH));
 
         addDispatch(new BlockModelRepeater(Blocks.REPEATER_IDLE)
             .setTex(BLOCK_TEXTURES, "minecraft:block/repeater/idle_top", S_TB)
             .setTex(BLOCK_TEXTURES, "minecraft:block/polished_stone_top", S_SIDES));
         addDispatch(new BlockModelRepeater(Blocks.REPEATER_ACTIVE)
             .setTex(BLOCK_TEXTURES, "minecraft:block/repeater/active_top", S_TB)
-            .setTex(BLOCK_TEXTURES, "minecraft:block/polished_stone_top", S_SIDES)
-            .setAllTextures(OVERBRIGHT_TEXTURES, "minecraft:block/repeater/active_overlay"));
+            .setTex(BLOCK_TEXTURES, "minecraft:block/polished_stone_top", S_SIDES));
 
         addDispatch(new BlockModelPiston<>(Blocks.PISTON_BASE,
             TextureRegistry.getTexture("minecraft:block/piston/face"))
@@ -739,14 +729,12 @@ public final class BlockModelDispatcher
             .setTex(BLOCK_TEXTURES, "minecraft:block/pumpkin_redstone/top", Side.TOP)
             .setTex(BLOCK_TEXTURES, "minecraft:block/pumpkin_redstone/bottom", Side.BOTTOM)
             .setTex(BLOCK_TEXTURES, "minecraft:block/pumpkin_redstone/front", Side.SOUTH)
-            .setTex(BLOCK_TEXTURES, "minecraft:block/pumpkin_redstone/side", Side.WEST, Side.EAST, Side.NORTH)
-            .setTex(OVERBRIGHT_TEXTURES, "minecraft:block/pumpkin_redstone/front_overlay", Side.SOUTH));
+            .setTex(BLOCK_TEXTURES, "minecraft:block/pumpkin_redstone/side", Side.WEST, Side.EAST, Side.NORTH));
 
 
         addDispatch(new BlockModelStandard<>(Blocks.COBBLE_NETHERRACK).setAllTextures(BLOCK_TEXTURES, "minecraft:block/cobbled_netherrack/normal"));
         addDispatch(new BlockModelStandard<>(Blocks.COBBLE_NETHERRACK_IGNEOUS)
-            .setAllTextures(BLOCK_TEXTURES, "minecraft:block/cobbled_netherrack/igneous")
-            .setAllTextures(OVERBRIGHT_TEXTURES, "minecraft:block/cobbled_netherrack/igneous_overlay"));
+            .setAllTextures(BLOCK_TEXTURES, "minecraft:block/cobbled_netherrack/igneous"));
         addDispatch(new BlockModelStandard<>(Blocks.COBBLE_NETHERRACK_MOSSY).setAllTextures(BLOCK_TEXTURES, "minecraft:block/cobbled_netherrack/mossy"));
         addDispatch(new BlockModelStandard<>(Blocks.NETHERRACK).setAllTextures(BLOCK_TEXTURES, "minecraft:block/netherrack"));
         addDispatch(new BlockModelStandard<>(Blocks.BRICK_NETHERRACK).setAllTextures(BLOCK_TEXTURES, "minecraft:block/brick_netherrack"));
@@ -816,14 +804,11 @@ public final class BlockModelDispatcher
 
         addDispatch(new BlockModelMatcher<>(Blocks.MATCHER, false)
             .setTex(BLOCK_TEXTURES, "minecraft:block/matcher/side", S_SIDES)
-            .setTex(BLOCK_TEXTURES, "minecraft:block/matcher/front0", S_TB)
-            .setTex(OVERBRIGHT_TEXTURES, "minecraft:block/matcher/front_overlay0", S_TB));
+            .setTex(BLOCK_TEXTURES, "minecraft:block/matcher/front0", S_TB));
 
         addDispatch(new BlockModelMatcher<>(Blocks.MATCHER_ACTIVE, true)
             .setTex(BLOCK_TEXTURES, "minecraft:block/matcher/side_active", S_SIDES)
-            .setTex(BLOCK_TEXTURES, "minecraft:block/matcher/front0", S_TB)
-            .setTex(OVERBRIGHT_TEXTURES, "minecraft:block/matcher/front_active_overlay0", S_TB)
-            .setTex(OVERBRIGHT_TEXTURES, "minecraft:block/matcher/side_active_overlay", S_SIDES));
+            .setTex(BLOCK_TEXTURES, "minecraft:block/matcher/front0", S_TB));
     }
 }
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelDoor.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelDoor.java
index 0405aa8ff..0e2e77a25 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelDoor.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelDoor.java
@@ -1,7 +1,7 @@
 package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.LightmapHelper;
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
+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.BlockLogicDoor;
@@ -17,30 +17,14 @@ public class BlockModelDoor<T extends BlockLogicDoor> extends BlockModelStandard
         super(block);
     }
 
-    public void setBrightness(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos, float sideBrightness) {
-        tessellator.setLightmapCoord1i(this.block.getLightmapCoord(worldSource, tilePos));
-        tessellator.setColorOpaque3f(sideBrightness, sideBrightness, sideBrightness);
-    }
-
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         tessellator.setLightmapCoord1i(LightmapHelper.getLightmapCoord(15, 15));
         tessellator.setColorOpaque3f(1.0f, 1.0f, 1.0f);
 
         AABBdc bounds = this.block.getBoundsFromState(worldSource, tilePos);
         TilePos queryPos = new TilePos();
 
-        float sideBottom = 1.0f;
-        float sideTop = 1.0f;
-        float sideNorthSouth = 1.0f;
-        float sideEastWest = 1.0f;
-        if (ENABLE_DIRECTIONAL_LIGHTING) {
-            sideBottom = 0.5f;
-            sideTop = 1.0f;
-            sideNorthSouth = 0.8f;
-            sideEastWest = 0.6f;
-        }
-
         boolean aboveIsDoor = Block.hasLogicClass(worldSource.getBlock(tilePos.up(queryPos)), BlockLogicDoor.class);
         boolean belowIsDoor = Block.hasLogicClass(worldSource.getBlock(tilePos.down(queryPos)), BlockLogicDoor.class);
 
@@ -48,55 +32,33 @@ public class BlockModelDoor<T extends BlockLogicDoor> extends BlockModelStandard
 
         // Bottom
         if (!belowIsDoor) {
-            setBrightness(tessellator, worldSource, tilePos.down(queryPos), sideBottom);
             renderBlocks.renderBottomFace(tessellator, bounds, tilePos, getBlockTexture(worldSource, tilePos, Side.BOTTOM));
         }
 
         // Top
         if (!aboveIsDoor) {
-            setBrightness(tessellator, worldSource, tilePos.up(queryPos), sideTop);
             renderBlocks.renderTopFace(tessellator, bounds, tilePos, getBlockTexture(worldSource, tilePos, Side.TOP));
         }
 
         // North
-        if (bounds.minZ() > FULL_CUBE_THRESHOLD) {
-            setBrightness(tessellator, worldSource, tilePos, sideNorthSouth);
-        } else {
-            setBrightness(tessellator, worldSource, tilePos.north(queryPos), sideNorthSouth);
-        }
         renderBlocks.flipTexture = shouldFlipTexture(Side.NORTH, meta);
         IconCoordinate texture = getBlockTexture(worldSource, tilePos, Side.NORTH);
         renderBlocks.renderNorthFace(tessellator, bounds, tilePos, texture);
         renderBlocks.flipTexture = false;
 
         // South
-        if (bounds.maxZ() < 1.0f - FULL_CUBE_THRESHOLD) {
-            setBrightness(tessellator, worldSource, tilePos, sideNorthSouth);
-        } else {
-            setBrightness(tessellator, worldSource, tilePos.south(queryPos), sideNorthSouth);
-        }
         renderBlocks.flipTexture = shouldFlipTexture(Side.SOUTH, meta);
         texture = getBlockTexture(worldSource, tilePos, Side.SOUTH);
         renderBlocks.renderSouthFace(tessellator, bounds, tilePos, texture);
         renderBlocks.flipTexture = false;
 
         // West
-        if (bounds.minX() > FULL_CUBE_THRESHOLD) {
-            setBrightness(tessellator, worldSource, tilePos, sideEastWest);
-        } else {
-            setBrightness(tessellator, worldSource, tilePos.west(queryPos), sideEastWest);
-        }
         renderBlocks.flipTexture = shouldFlipTexture(Side.WEST, meta);
         texture = getBlockTexture(worldSource, tilePos, Side.WEST);
         renderBlocks.renderWestFace(tessellator, bounds, tilePos, texture);
         renderBlocks.flipTexture = false;
 
         // East
-        if (bounds.maxX() < 1.0f - FULL_CUBE_THRESHOLD) {
-            setBrightness(tessellator, worldSource, tilePos, sideEastWest);
-        } else {
-            setBrightness(tessellator, worldSource, tilePos.east(queryPos), sideEastWest);
-        }
         renderBlocks.flipTexture = shouldFlipTexture(Side.EAST, meta);
         texture = getBlockTexture(worldSource, tilePos, Side.EAST);
         renderBlocks.renderEastFace(tessellator, bounds, tilePos, texture);
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelEmpty.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelEmpty.java
index a8264f99d..c15c7c70e 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelEmpty.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelEmpty.java
@@ -1,7 +1,6 @@
 package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.tessellator.TessellatorGeneral;
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.BlockLogic;
@@ -17,7 +16,7 @@ public class BlockModelEmpty<T extends BlockLogic> extends BlockModelStandard<T>
     }
 
     @Override
-    public boolean render(final @NotNull TessellatorTerrain tessellator, @NotNull final WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(final @NotNull TessellatorGeneral tessellator, @NotNull final WorldSource worldSource, @NotNull TilePosc tilePos) {
         return false;
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFence.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFence.java
index 27005cdf9..4393cbb2e 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFence.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFence.java
@@ -1,7 +1,6 @@
 package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.tessellator.TessellatorGeneral;
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.BlockLogicFence;
 import net.minecraft.core.util.helper.Side;
@@ -24,7 +23,7 @@ public class BlockModelFence<T extends BlockLogicFence> extends BlockModelStanda
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         final float f = 0.375F;
         final float f1 = 0.625F;
         AABBd bounds = new AABBd(f, 0.0F, f, f1, 1.0F, f1);
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFenceGate.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFenceGate.java
index 0db20ff71..32255f8bc 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFenceGate.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFenceGate.java
@@ -1,7 +1,6 @@
 package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.tessellator.TessellatorGeneral;
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.BlockLogicFenceGate;
 import net.minecraft.core.util.helper.Side;
@@ -23,7 +22,7 @@ public class BlockModelFenceGate<T extends BlockLogicFenceGate> extends BlockMod
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         AABBd bounds = new AABBd(this.block.getBounds());
         boolean flag = true;
         int meta = worldSource.getBlockData(tilePos);
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFenceThin.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFenceThin.java
index 2f1010beb..be38e6e85 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFenceThin.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFenceThin.java
@@ -2,7 +2,6 @@ package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.renderer.GLRenderer;
 import net.minecraft.client.render.renderer.State;
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.tessellator.TessellatorGeneral;
 import net.minecraft.core.block.Block;
@@ -35,23 +34,13 @@ public class BlockModelFenceThin<T extends BlockLogicFenceThin> extends BlockMod
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain t, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral t, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         float brightness = 1.0f;
         t.setLightmapCoord1i(this.block.getLightmapCoord(worldSource, tilePos));
         t.setColorOpaque3f(brightness, brightness, brightness);
 
         TilePos queryPos = new TilePos();
 
-        float cBottom = 1.0f;
-        float cTop = 1.0f;
-        float cNorthSouth = 1.0f;
-        float cEastWest = 1.0f;
-        if (ENABLE_DIRECTIONAL_LIGHTING) {
-            cBottom = 0.5f;
-            cTop = 1.0f;
-            cNorthSouth = 0.8f;
-            cEastWest = 0.6f;
-        }
         BlockLogicFenceThin thin = this.block.getLogic();
         boolean connectNorth = thin.canConnectTo(worldSource, tilePos, Side.NORTH);
         boolean connectSouth = thin.canConnectTo(worldSource, tilePos, Side.SOUTH);
@@ -118,23 +107,25 @@ public class BlockModelFenceThin<T extends BlockLogicFenceThin> extends BlockMod
             float maxZ = tilePos.z() + ((16 / 2f) + (2 / 2f)) / 16f;
 
             // Render sides
-            t.setColorOpaque3f(cNorthSouth * brightness, cNorthSouth * brightness, cNorthSouth * brightness);
+            t.setNormal(0, 0, -1);
             t.addVertexWithUV(maxX, minY, minZ, sidesMinU, sidesMaxV);
             t.addVertexWithUV(minX, minY, minZ, sidesMaxU, sidesMaxV);
             t.addVertexWithUV(minX, maxY, minZ, sidesMaxU, sidesMinV);
             t.addVertexWithUV(maxX, maxY, minZ, sidesMinU, sidesMinV);
 
+            t.setNormal(0, 0, 1);
             t.addVertexWithUV(minX, minY, maxZ, sidesMinU, sidesMaxV);
             t.addVertexWithUV(maxX, minY, maxZ, sidesMaxU, sidesMaxV);
             t.addVertexWithUV(maxX, maxY, maxZ, sidesMaxU, sidesMinV);
             t.addVertexWithUV(minX, maxY, maxZ, sidesMinU, sidesMinV);
 
-            t.setColorOpaque3f(cEastWest * brightness, cEastWest * brightness, cEastWest * brightness);
+            t.setNormal(1, 0, 0);
             t.addVertexWithUV(maxX, minY, maxZ, sidesMinU, sidesMaxV);
             t.addVertexWithUV(maxX, minY, minZ, sidesMaxU, sidesMaxV);
             t.addVertexWithUV(maxX, maxY, minZ, sidesMaxU, sidesMinV);
             t.addVertexWithUV(maxX, maxY, maxZ, sidesMinU, sidesMinV);
 
+            t.setNormal(-1, 0, 0);
             t.addVertexWithUV(minX, minY, minZ, sidesMinU, sidesMaxV);
             t.addVertexWithUV(minX, minY, maxZ, sidesMaxU, sidesMaxV);
             t.addVertexWithUV(minX, maxY, maxZ, sidesMaxU, sidesMinV);
@@ -146,14 +137,14 @@ public class BlockModelFenceThin<T extends BlockLogicFenceThin> extends BlockMod
             double topBottomMaxV = this.columnTexIndex.getSubIconV(onePix * 2);
 
             // Render top
-            t.setColorOpaque3f(cTop * brightness, cTop * brightness, cTop * brightness);
+            t.setNormal(0, 1, 0);
             t.addVertexWithUV(minX, maxY, maxZ, topBottomMinU, topBottomMaxV);
             t.addVertexWithUV(maxX, maxY, maxZ, topBottomMaxU, topBottomMaxV);
             t.addVertexWithUV(maxX, maxY, minZ, topBottomMaxU, topBottomMinV);
             t.addVertexWithUV(minX, maxY, minZ, topBottomMinU, topBottomMinV);
 
             // Render bottom
-            t.setColorOpaque3f(cBottom * brightness, cBottom * brightness, cBottom * brightness);
+            t.setNormal(0, -1, 0);
             t.addVertexWithUV(minX, minY, minZ, topBottomMinU, topBottomMinV);
             t.addVertexWithUV(maxX, minY, minZ, topBottomMaxU, topBottomMinV);
             t.addVertexWithUV(maxX, minY, maxZ, topBottomMaxU, topBottomMaxV);
@@ -190,12 +181,13 @@ public class BlockModelFenceThin<T extends BlockLogicFenceThin> extends BlockMod
             float maxY = tilePos.y() + 1.0f;
             float maxZ = tilePos.z() + (8f / 16f);
 
-            t.setColorOpaque3f(cEastWest * brightness, cEastWest * brightness, cEastWest * brightness);
+            t.setNormal(1, 0, 0);
             t.addVertexWithUV(maxX, minY, maxZ, sidesMinU, sidesMaxV);
             t.addVertexWithUV(maxX, minY, minZ, sidesMaxU, sidesMaxV);
             t.addVertexWithUV(maxX, maxY, minZ, sidesMaxU, sidesMinV);
             t.addVertexWithUV(maxX, maxY, maxZ, sidesMinU, sidesMinV);
 
+            t.setNormal(-1, 0, 0);
             t.addVertexWithUV(minX, minY, minZ, sidesMaxU, sidesMaxV);
             t.addVertexWithUV(minX, minY, maxZ, sidesMinU, sidesMaxV);
             t.addVertexWithUV(minX, maxY, maxZ, sidesMinU, sidesMinV);
@@ -232,12 +224,13 @@ public class BlockModelFenceThin<T extends BlockLogicFenceThin> extends BlockMod
             float maxY = tilePos.y() + 1.0f;
             float maxZ = tilePos.z() + 1.0f;
 
-            t.setColorOpaque3f(cEastWest * brightness, cEastWest * brightness, cEastWest * brightness);
+            t.setNormal(1, 0, 0);
             t.addVertexWithUV(maxX, minY, maxZ, sidesMinU, sidesMaxV);
             t.addVertexWithUV(maxX, minY, minZ, sidesMaxU, sidesMaxV);
             t.addVertexWithUV(maxX, maxY, minZ, sidesMaxU, sidesMinV);
             t.addVertexWithUV(maxX, maxY, maxZ, sidesMinU, sidesMinV);
 
+            t.setNormal(-1, 0, 0);
             t.addVertexWithUV(minX, minY, minZ, sidesMaxU, sidesMaxV);
             t.addVertexWithUV(minX, minY, maxZ, sidesMinU, sidesMaxV);
             t.addVertexWithUV(minX, maxY, maxZ, sidesMinU, sidesMinV);
@@ -274,12 +267,13 @@ public class BlockModelFenceThin<T extends BlockLogicFenceThin> extends BlockMod
             float maxY = tilePos.y() + 1.0f;
             float maxZ = tilePos.z() + (8f / 16f);
 
-            t.setColorOpaque3f(cNorthSouth * brightness, cNorthSouth * brightness, cNorthSouth * brightness);
+            t.setNormal(0, 0, -1);
             t.addVertexWithUV(maxX, minY, minZ, sidesMinU, sidesMaxV);
             t.addVertexWithUV(minX, minY, minZ, sidesMaxU, sidesMaxV);
             t.addVertexWithUV(minX, maxY, minZ, sidesMaxU, sidesMinV);
             t.addVertexWithUV(maxX, maxY, minZ, sidesMinU, sidesMinV);
 
+            t.setNormal(0, 0, 1);
             t.addVertexWithUV(minX, minY, maxZ, sidesMaxU, sidesMaxV);
             t.addVertexWithUV(maxX, minY, maxZ, sidesMinU, sidesMaxV);
             t.addVertexWithUV(maxX, maxY, maxZ, sidesMinU, sidesMinV);
@@ -316,12 +310,13 @@ public class BlockModelFenceThin<T extends BlockLogicFenceThin> extends BlockMod
             float maxY = tilePos.y() + 1.0f;
             float maxZ = tilePos.z() + (8f / 16f);
 
-            t.setColorOpaque3f(cNorthSouth * brightness, cNorthSouth * brightness, cNorthSouth * brightness);
+            t.setNormal(0, 0, -1);
             t.addVertexWithUV(maxX, minY, minZ, sidesMinU, sidesMaxV);
             t.addVertexWithUV(minX, minY, minZ, sidesMaxU, sidesMaxV);
             t.addVertexWithUV(minX, maxY, minZ, sidesMaxU, sidesMinV);
             t.addVertexWithUV(maxX, maxY, minZ, sidesMinU, sidesMinV);
 
+            t.setNormal(0, 0, 1);
             t.addVertexWithUV(minX, minY, maxZ, sidesMaxU, sidesMaxV);
             t.addVertexWithUV(maxX, minY, maxZ, sidesMinU, sidesMaxV);
             t.addVertexWithUV(maxX, maxY, maxZ, sidesMinU, sidesMinV);
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFire.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFire.java
index 058d5f2b3..ebf152822 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFire.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFire.java
@@ -1,7 +1,7 @@
 package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.LightmapHelper;
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
+import net.minecraft.client.render.tessellator.TessellatorGeneral;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.world.WorldClient;
 import net.minecraft.core.block.Block;
@@ -27,7 +27,7 @@ public class BlockModelFire<T extends BlockLogic> extends BlockModelStandard<T>
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         IconCoordinate tex = getBlockTextureFromSideAndMetadata(Side.BOTTOM, worldSource.getBlockData(tilePos));
         if (renderBlocks.overrideBlockTexture != null) {
             tex = renderBlocks.overrideBlockTexture;
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFluid.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFluid.java
index ecd4a7058..4247cd617 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFluid.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFluid.java
@@ -2,7 +2,7 @@ package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.LightmapHelper;
 import net.minecraft.client.render.block.color.BlockColorDispatcher;
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
+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.BlockLogicFluid;
@@ -22,7 +22,7 @@ public class BlockModelFluid<T extends BlockLogicFluid> extends BlockModelStanda
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         int color = BlockColorDispatcher.getInstance().getDispatch(this.block).getWorldColor(worldSource, tilePos, 0);
         float r = (float) (color >> 16 & 0xff) / 255F;
         float g = (float) (color >> 8 & 0xff) / 255F;
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFullyRotatable.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFullyRotatable.java
index 03e3e9ba9..878664f2f 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFullyRotatable.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelFullyRotatable.java
@@ -1,7 +1,6 @@
 package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.tessellator.TessellatorGeneral;
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.BlockLogic;
@@ -19,7 +18,7 @@ public class BlockModelFullyRotatable<T extends BlockLogic> extends BlockModelSt
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         final int meta = worldSource.getBlockData(tilePos);
         final Direction dir = BlockLogicFullyRotatable.metaToDirection(meta);
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelGeneric.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelGeneric.java
index ec63ebae1..01e18ae46 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelGeneric.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelGeneric.java
@@ -2,7 +2,6 @@ package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.block.color.BlockColorDispatcher;
 import net.minecraft.client.render.tessellator.TessellatorGeneral;
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.BlockLogic;
@@ -40,7 +39,7 @@ public class BlockModelGeneric<T extends BlockLogic> extends BlockModel<T> {
     }
 
     @Override
-    public boolean render(final @NotNull TessellatorTerrain tessellator, @NotNull final WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(final @NotNull TessellatorGeneral tessellator, @NotNull final WorldSource worldSource, @NotNull TilePosc tilePos) {
         return this.staticModel.renderAttached(this,
             tessellator,
             worldSource,
@@ -51,12 +50,7 @@ public class BlockModelGeneric<T extends BlockLogic> extends BlockModel<T> {
     }
 
     @Override
-    public boolean renderOverbright(final @NotNull TessellatorTerrain tessellator, @NotNull final WorldSource worldSource, @NotNull TilePosc tilePos) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public boolean renderWithOverrideTexture(final @NotNull TessellatorTerrain tessellator, @NotNull final WorldSource worldSource, @NotNull TilePosc tilePos, final IconCoordinate textureIndex) {
+    public boolean renderWithOverrideTexture(final @NotNull TessellatorGeneral tessellator, @NotNull final WorldSource worldSource, @NotNull TilePosc tilePos, final IconCoordinate textureIndex) {
         return this.staticModel.renderAttached(this,
             tessellator,
             worldSource,
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelGrass.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelGrass.java
index 17dc9bef5..9d6158674 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelGrass.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelGrass.java
@@ -1,7 +1,6 @@
 package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.renderer.GLRenderer;
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.client.render.tessellator.TessellatorGeneral;
@@ -35,7 +34,7 @@ public class BlockModelGrass<T extends BlockLogic> extends BlockModelStandard<T>
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         AABBdc bounds = this.block.getBounds();
         boolean didRender = isRetro() ? renderBlocks.renderStandardBlock(tessellator, worldSource, this, bounds, tilePos, 1, 1, 1) : renderBlocks.renderStandardBlock(tessellator, worldSource, this, bounds, tilePos);
         if (fancyGrass && !(this.retroBlockTextures.hasTexture() && isRetro())) {
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelHorizontalRotation.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelHorizontalRotation.java
index 71c67f963..abdc96b9b 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelHorizontalRotation.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelHorizontalRotation.java
@@ -23,13 +23,6 @@ public class BlockModelHorizontalRotation<T extends BlockLogic> extends BlockMod
         setDisplayPos(DisplayPos.FIRST_PERSON_RIGHT_HAND, ROTATABLE_FIRST_PERSON_RIGHT_HAND);
     }
 
-    @Override
-    public @Nullable IconCoordinate getBlockOverbrightTextureFromSideAndMeta(@NotNull Side side, int data) {
-        int index = Sides.orientationLookUpHorizontal[6 * Math.min(data & BlockLogicRotatable.MASK_DIRECTION, 5) + side.getId()];
-        if (index >= Sides.orientationLookUpHorizontal.length) return this.overbrightTextures.get(Side.BOTTOM);
-        return super.getBlockOverbrightTextureFromSideAndMeta(Side.getSideById(index), data);
-    }
-
     @Override
     public @Nullable IconCoordinate getBlockTextureFromSideAndMetadata(@NotNull Side side, int data)
     {
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelJar.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelJar.java
index f87cedec6..b3e8b7604 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelJar.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelJar.java
@@ -1,6 +1,6 @@
 package net.minecraft.client.render.block.model;
 
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
+import net.minecraft.client.render.tessellator.TessellatorGeneral;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.core.block.Block;
@@ -20,7 +20,7 @@ public class BlockModelJar<T extends BlockLogic> extends BlockModelStandard<T> {
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         // todo: yes, i know this is horrible.
         float brightness = 1.0f;
         tessellator.setLightmapCoord1i(this.block.getLightmapCoord(worldSource, tilePos));
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelJarButterfly.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelJarButterfly.java
index ce96b1683..fe006b2cb 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelJarButterfly.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelJarButterfly.java
@@ -1,6 +1,6 @@
 package net.minecraft.client.render.block.model;
 
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
+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;
@@ -17,7 +17,7 @@ public class BlockModelJarButterfly<T extends BlockLogic> extends BlockModelStan
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         int meta = worldSource.getBlockData(tilePos);
         boolean isHanging = (meta & BlockLogicJarButterfly.MASK_HANGING) == 0;
         boolean isAngled = (meta & BlockLogicJarButterfly.MASK_ANGLED) != 0;
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLadder.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLadder.java
index 92e56d6d3..18a78942e 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLadder.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLadder.java
@@ -1,6 +1,6 @@
 package net.minecraft.client.render.block.model;
 
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
+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.BlockLogicLadder;
@@ -15,7 +15,7 @@ public class BlockModelLadder<T extends BlockLogicLadder> extends BlockModelStan
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         int data = worldSource.getBlockData(tilePos);
         IconCoordinate tex = getBlockTextureFromSideAndMetadata(Side.BOTTOM, data);
         if (renderBlocks.overrideBlockTexture != null) {
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLantern.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLantern.java
index 1014e9247..3850901fb 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLantern.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLantern.java
@@ -1,6 +1,6 @@
 package net.minecraft.client.render.block.model;
 
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
+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;
@@ -16,7 +16,7 @@ public class BlockModelLantern<T extends BlockLogic> extends BlockModelStandard<
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         int meta = worldSource.getBlockData(tilePos);
         boolean isHanging = (meta & BlockLogicLanternFirefly.MASK_HANGING) == 0;
 //        boolean isAngled = (meta & BlockLogicLanternFirefly.MASK_ANGLED) != 0;
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLeaves.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLeaves.java
index e7a332456..e6eef4658 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLeaves.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLeaves.java
@@ -1,7 +1,6 @@
 package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.tessellator.TessellatorGeneral;
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.core.block.Block;
@@ -45,7 +44,7 @@ public class BlockModelLeaves<T extends BlockLogic> extends BlockModelStandard<T
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         if (this.canBeRetro && isRetro()) {
             return renderBlocks.renderStandardBlock(tessellator, worldSource, this, this.block.getBoundsFromState(worldSource, tilePos), tilePos, 1, 1, 1);
         }
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLeavesCacao.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLeavesCacao.java
index 1e57db3c8..34087f503 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLeavesCacao.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLeavesCacao.java
@@ -1,7 +1,6 @@
 package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.LightmapHelper;
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.client.render.tessellator.TessellatorGeneral;
@@ -26,7 +25,7 @@ public class BlockModelLeavesCacao<T extends BlockLogic> extends BlockModelLeave
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         super.render(tessellator, worldSource, tilePos);
 
         AABBdc bounds = this.block.getBounds();
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLeavesCherryFlowering.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLeavesCherryFlowering.java
index 7b4914e2e..4b35c283a 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLeavesCherryFlowering.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLeavesCherryFlowering.java
@@ -1,6 +1,5 @@
 package net.minecraft.client.render.block.model;
 
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.client.render.tessellator.TessellatorGeneral;
@@ -21,7 +20,7 @@ public class BlockModelLeavesCherryFlowering<T extends BlockLogic> extends Block
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         super.render(tessellator, worldSource, tilePos);
 
         int growthRate = BlockLogicLeavesCherryFlowering.getGrowthRate(worldSource.getBlockData(tilePos));
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLever.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLever.java
index 76ad9fb2b..35ec6d67f 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLever.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelLever.java
@@ -1,6 +1,6 @@
 package net.minecraft.client.render.block.model;
 
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
+import net.minecraft.client.render.tessellator.TessellatorGeneral;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.core.block.Block;
@@ -20,7 +20,7 @@ public class BlockModelLever<T extends BlockLogic> extends BlockModelStandard<T>
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         int data = worldSource.getBlockData(tilePos);
         int rotation = data & BlockLogicLever.MASK_ROTATION;
         boolean powered = (data & BlockLogicLever.MASK_POWERED) != 0;
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelMatcher.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelMatcher.java
index 2def7f40e..d26ffeb3c 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelMatcher.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelMatcher.java
@@ -46,16 +46,6 @@ public class BlockModelMatcher<T extends BlockLogic> extends BlockModelAxisAlign
         return super.getBlockTexture(source, tilePos, side);
     }
 
-    @Override
-    public @Nullable IconCoordinate getBlockOverbrightTexture(@NotNull WorldSource source, @NotNull TilePosc tilePos, @NotNull Side side) {
-        Side rotated = getRotatedSide(side, source.getBlockData(tilePos));
-        if (rotated.getAxis() == Axis.Y) {
-            this.random.setSeed(getPositionalSeed(tilePos));
-            return this.frontOverlayVariants[this.random.nextInt(this.frontVariants.length)];
-        }
-        return super.getBlockOverbrightTexture(source, tilePos, side);
-    }
-
     public long getPositionalSeed(@NotNull TilePosc tilePos) {
         return tilePos.x() * 374761393L + tilePos.y() * 668265263L + tilePos.z() * 968290493L;
     }
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelOverlayLeaves.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelOverlayLeaves.java
index 22a18b83c..a33143806 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelOverlayLeaves.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelOverlayLeaves.java
@@ -1,6 +1,5 @@
 package net.minecraft.client.render.block.model;
 
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.client.render.tessellator.TessellatorGeneral;
@@ -20,7 +19,7 @@ public class BlockModelOverlayLeaves<T extends BlockLogic> extends BlockModelLea
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         super.render(tessellator, worldSource, tilePos);
 
         renderBlocks.overrideBlockTexture = this.overlayTexture;
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPebbles.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPebbles.java
index 82ce50ce1..ca87b5434 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPebbles.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPebbles.java
@@ -1,7 +1,7 @@
 package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.LightmapHelper;
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
+import net.minecraft.client.render.tessellator.TessellatorGeneral;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.core.block.Block;
@@ -26,7 +26,7 @@ public class BlockModelPebbles<T extends BlockLogic> extends BlockModelStandard<
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         tessellator.setLightmapCoord1i(LightmapHelper.max(this.block.getLightmapCoord(worldSource, tilePos), this.block.getLightmapCoord(worldSource, tilePos.down(new TilePos()))));
         renderBlocks.renderTopFace(tessellator,
             this.block.getBoundsFromState(worldSource, tilePos),
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPiePumpkin.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPiePumpkin.java
index 0da7f040e..7a36c1035 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPiePumpkin.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPiePumpkin.java
@@ -1,9 +1,8 @@
 package net.minecraft.client.render.block.model;
 
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
+import net.minecraft.client.render.tessellator.TessellatorGeneral;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
-import net.minecraft.client.render.tessellator.TessellatorGeneral;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.BlockLogicEdible;
 import net.minecraft.core.util.helper.Side;
@@ -25,7 +24,7 @@ public class BlockModelPiePumpkin<T extends BlockLogicEdible> extends BlockModel
         withCustomItemBounds(f, 0.0F, f, 1.0F - f, f1, 1.0F - f);
     }
 
-    public void renderSliceSide(final @NotNull TessellatorTerrain tessellator, final @NotNull WorldSource worldSource, final @NotNull AABBdc bounds, @NotNull TilePosc tilePos, final @NotNull Side side, final boolean overrideTex) {
+    public void renderSliceSide(final @NotNull TessellatorGeneral tessellator, final @NotNull WorldSource worldSource, final @NotNull AABBdc bounds, @NotNull TilePosc tilePos, final @NotNull Side side, final boolean overrideTex) {
         if (overrideTex)
             renderBlocks.overrideBlockTexture = this.insideTexture;
         renderBlocks.renderSide(tessellator, worldSource, this, bounds, tilePos, 1, 1, 1, side, 0);
@@ -33,7 +32,7 @@ public class BlockModelPiePumpkin<T extends BlockLogicEdible> extends BlockModel
             renderBlocks.overrideBlockTexture = null;
     }
 
-    private void renderSlice(final @NotNull TessellatorTerrain tessellator, final @NotNull WorldSource worldSource, final @NotNull AABBdc bounds, @NotNull TilePosc tilePos, final int sliceX, final int sliceZ) {
+    private void renderSlice(final @NotNull TessellatorGeneral tessellator, final @NotNull WorldSource worldSource, final @NotNull AABBdc bounds, @NotNull TilePosc tilePos, final int sliceX, final int sliceZ) {
 
         final double onePix = 0.0625;
         final double sliceWidth = onePix * 8;
@@ -65,7 +64,7 @@ public class BlockModelPiePumpkin<T extends BlockLogicEdible> extends BlockModel
     }
 
     @Override
-    public boolean render(final @NotNull TessellatorTerrain tessellator, @NotNull final WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(final @NotNull TessellatorGeneral tessellator, @NotNull final WorldSource worldSource, @NotNull TilePosc tilePos) {
         final AABBdc bounds = this.block.getBoundsFromState(worldSource, tilePos);
 
         final int meta = worldSource.getBlockData(tilePos);
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPiston.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPiston.java
index a1ba8bb45..dcdcbf928 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPiston.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPiston.java
@@ -1,6 +1,5 @@
 package net.minecraft.client.render.block.model;
 
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.client.render.tessellator.TessellatorGeneral;
@@ -46,13 +45,13 @@ public class BlockModelPiston<T extends BlockLogicPistonBase> extends BlockModel
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         return renderPistonBase(tessellator, worldSource, tilePos, false);
     }
 
     private boolean headless = false;
 
-    public boolean renderHeadless(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePos tilePos) {
+    public boolean renderHeadless(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePos tilePos) {
         renderBlocks.renderAllFaces = true;
         this.headless = true;
         boolean result = renderPistonBase(tessellator, worldSource, tilePos, true);
@@ -61,7 +60,7 @@ public class BlockModelPiston<T extends BlockLogicPistonBase> extends BlockModel
         return result;
     }
 
-    protected boolean renderPistonBase(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos, boolean noCulling) {
+    protected boolean renderPistonBase(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos, boolean noCulling) {
         int meta = worldSource.getBlockData(tilePos);
         boolean extended = noCulling || (meta & 8) != 0;
         Direction direction = BlockLogicPistonBase.getDirection(meta);
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPistonHead.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPistonHead.java
index be358a7d8..06848fd3b 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPistonHead.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPistonHead.java
@@ -1,6 +1,6 @@
 package net.minecraft.client.render.block.model;
 
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
+import net.minecraft.client.render.tessellator.TessellatorGeneral;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.core.block.Block;
@@ -40,11 +40,11 @@ public class BlockModelPistonHead extends BlockModelStandard<BlockLogicPistonHea
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         return renderPistonHead(tessellator, worldSource, this.block, tilePos, true);
     }
 
-    public void renderPistonHeadNoCulling(TessellatorTerrain tessellator, WorldSource worldSource, Block<BlockLogicPistonHead> block, @NotNull TilePos tilePos, boolean flag) {
+    public void renderPistonHeadNoCulling(@NotNull TessellatorGeneral tessellator, WorldSource worldSource, Block<BlockLogicPistonHead> block, @NotNull TilePos tilePos, boolean flag) {
         renderBlocks.renderAllFaces = true;
         renderPistonHead(tessellator, worldSource, block, tilePos, flag);
         renderBlocks.renderAllFaces = false;
@@ -54,7 +54,7 @@ public class BlockModelPistonHead extends BlockModelStandard<BlockLogicPistonHea
         this.faceTextureOverride = faceTexture;
     }
 
-    protected boolean renderPistonHead(TessellatorTerrain tessellator, WorldSource worldSource, Block<BlockLogicPistonHead> block, @NotNull TilePosc tilePos, boolean flag) {
+    protected boolean renderPistonHead(@NotNull TessellatorGeneral tessellator, WorldSource worldSource, Block<BlockLogicPistonHead> block, @NotNull TilePosc tilePos, boolean flag) {
         int metadata = worldSource.getBlockData(tilePos);
         Direction direction = BlockLogicPistonHead.getDirectionFromMeta(metadata);
         float brightness = 1.0f;
@@ -137,7 +137,7 @@ public class BlockModelPistonHead extends BlockModelStandard<BlockLogicPistonHea
         return true;
     }
 
-    private void renderHeadTopBottom(final TessellatorTerrain tessellator, final double xMin, final double xMax, final double yMin, final double yMax, final double zMin, final double zMax, final float brightness, final double width) {
+    private void renderHeadTopBottom(final @NotNull TessellatorGeneral tessellator, final double xMin, final double xMax, final double yMin, final double yMax, final double zMin, final double zMax, final float brightness, final double width) {
         final IconCoordinate i = renderBlocks.overrideBlockTexture != null ? renderBlocks.overrideBlockTexture : this.pistonShaft;
         final double uMin = i.getSubIconU(0.5 - this.shaftThickness / 2);
         final double vMin = i.getIconVMin();
@@ -150,7 +150,7 @@ public class BlockModelPistonHead extends BlockModelStandard<BlockLogicPistonHea
         tessellator.addVertexWithUV(xMax, yMax, zMax, uMin, vMax);
     }
 
-    private void renderHeadNorthSouth(final TessellatorTerrain tessellator, final double xMin, final double xMax, final double yMin, final double yMax, final double zMin, final double zMax, final float brightness, final double width) {
+    private void renderHeadNorthSouth(final @NotNull TessellatorGeneral tessellator, final double xMin, final double xMax, final double yMin, final double yMax, final double zMin, final double zMax, final float brightness, final double width) {
         final IconCoordinate i = renderBlocks.overrideBlockTexture != null ? renderBlocks.overrideBlockTexture : this.pistonShaft;
         final double uMin = i.getSubIconU(0.5 - this.shaftThickness / 2);
         final double vMin = i.getIconVMin();
@@ -163,7 +163,7 @@ public class BlockModelPistonHead extends BlockModelStandard<BlockLogicPistonHea
         tessellator.addVertexWithUV(xMax, yMax, zMax, uMin, vMax);
     }
 
-    private void renderHeadEastWest(final TessellatorTerrain tessellator, final double xMin, final double xMax, final double yMin, final double yMax, final double zMin, final double zMax, final float brightness, final double width) {
+    private void renderHeadEastWest(final @NotNull TessellatorGeneral tessellator, final double xMin, final double xMax, final double yMin, final double yMax, final double zMin, final double zMax, final float brightness, final double width) {
         final IconCoordinate i = renderBlocks.overrideBlockTexture != null ? renderBlocks.overrideBlockTexture : this.pistonShaft;
         final double uMin = i.getSubIconU(0.5 - this.shaftThickness / 2);
         final double vMin = i.getIconVMin();
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPumice.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPumice.java
index 02c3dae91..0bb7319b8 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPumice.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelPumice.java
@@ -2,7 +2,6 @@ package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.LightmapHelper;
 import net.minecraft.client.render.tessellator.TessellatorGeneral;
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.core.block.Block;
@@ -22,16 +21,11 @@ public class BlockModelPumice<T extends BlockLogic> extends BlockModelStandard<T
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         this.lavaFlag = true;
-        boolean ob = renderBlocks.overbright;
-        renderBlocks.overbright = true;
-//        block.setBlockBounds(0.005, 0.005, 0.005, 0.995, 0.995, 0.995);
         boolean rendered = super.render(tessellator, worldSource, tilePos);
 
-        renderBlocks.overbright = ob;
         this.lavaFlag = false;
-//        block.setBlockBounds(0, 0, 0, 1, 1, 1);
         rendered |= super.render(tessellator, worldSource, tilePos);
         return rendered;
     }
@@ -42,13 +36,10 @@ public class BlockModelPumice<T extends BlockLogic> extends BlockModelStandard<T
 
         int color = getStandaloneTintColor(metadata);
         this.lavaFlag = true;
-        boolean ob = renderBlocks.overbright;
-        renderBlocks.overbright = true;
         final double depthFixOffset = 0.001d;
         AABBd bounds = new AABBd(depthFixOffset, depthFixOffset, depthFixOffset, 1 - depthFixOffset, 1 - depthFixOffset, 1 - depthFixOffset);
         renderBlockWithBounds(tessellator, bounds, metadata, LightmapHelper.getLightmapCoord(15, 15), color);
 
-        renderBlocks.overbright = ob;
         this.lavaFlag = false;
         bounds.setMin(0, 0, 0).setMax(1, 1, 1);
         renderBlockWithBounds(tessellator, bounds, metadata, lightmapCoord, color);
@@ -61,10 +52,4 @@ public class BlockModelPumice<T extends BlockLogic> extends BlockModelStandard<T
         if (this.lavaFlag) return TextureRegistry.getTexture("minecraft:block/lava_still");
         return super.getBlockTextureFromSideAndMetadata(side, data);
     }
-
-    @Override
-    public @Nullable IconCoordinate getBlockOverbrightTextureFromSideAndMeta(@NotNull Side side, int data) {
-        if (this.lavaFlag) return TextureRegistry.getTexture("minecraft:block/lava_still");
-        return super.getBlockOverbrightTextureFromSideAndMeta(side, data);
-    }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelRail.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelRail.java
index faf32094f..f1625b7fa 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelRail.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelRail.java
@@ -1,14 +1,12 @@
 package net.minecraft.client.render.block.model;
 
-import net.minecraft.client.render.LightmapHelper;
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
+import net.minecraft.client.render.tessellator.TessellatorGeneral;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.BlockLogicRail;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.logic.RailDirection;
-import net.minecraft.core.enums.LightLayer;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.WorldSource;
 import net.minecraft.core.world.pos.TilePosc;
@@ -18,20 +16,14 @@ import org.jetbrains.annotations.Nullable;
 public class BlockModelRail<T extends BlockLogicRail> extends BlockModelStandard<T> {
     protected IconCoordinate railCurve = TextureRegistry.getTexture("minecraft:block/rail/turn");
     protected IconCoordinate powerActive = TextureRegistry.getTexture("minecraft:block/rail_powered/active");
-    protected IconCoordinate powerActiveOverlay = TextureRegistry.getTexture("minecraft:block/rail_powered/active_overlay");
-    protected IconCoordinate detectorActiveOverlay = TextureRegistry.getTexture("minecraft:block/rail_detector/active_overlay");
+    protected IconCoordinate detectorActive = TextureRegistry.getTexture("minecraft:block/rail_detector/active");
 
     public BlockModelRail(Block<T> block) {
         super(block);
     }
 
     @Override
-    public boolean hasOverbright() {
-        return true;
-    }
-
-    @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         int meta = worldSource.getBlockData(tilePos);
         IconCoordinate icon = getBlockTextureFromSideAndMetadata(Side.BOTTOM, meta);
         if (renderBlocks.overrideBlockTexture != null) {
@@ -39,14 +31,7 @@ public class BlockModelRail<T extends BlockLogicRail> extends BlockModelStandard
         }
         RailDirection railDirection = this.block.getLogic().getRailDirection(worldSource, tilePos);
         float brightness = 1.0f;
-        if (renderBlocks.overbright) {
-            tessellator.setLightmapCoord1i(LightmapHelper.getOverbrightLightmapCoord(worldSource.getSavedLightValue(LightLayer.Sky, tilePos)));
-        } else {
-            tessellator.setLightmapCoord1i(this.block.getLightmapCoord(worldSource, tilePos));
-        }
-        if (renderBlocks.overbright) {
-            icon = getBlockOverbrightTexture(worldSource, tilePos, Side.BOTTOM);
-        }
+        tessellator.setLightmapCoord1i(this.block.getLightmapCoord(worldSource, tilePos));
         if (icon == null) {
             return false;
         }
@@ -121,18 +106,12 @@ public class BlockModelRail<T extends BlockLogicRail> extends BlockModelStandard
         return false;
     }
 
-    @Override
-    public @Nullable IconCoordinate getBlockOverbrightTexture(@NotNull WorldSource blockAccess, @NotNull TilePosc tilePos, @NotNull Side side) {
-        if (!this.block.getLogic().isPowered || (blockAccess.getBlockData(tilePos) & BlockLogicRail.MASK_POWERED) == 0)
-            return null;
-
-        return this.block == Blocks.RAIL_POWERED ? this.powerActiveOverlay : this.detectorActiveOverlay;
-    }
-
     @Override
     public @Nullable IconCoordinate getBlockTextureFromSideAndMetadata(@NotNull Side side, int data) {
         if (this.block == Blocks.RAIL_POWERED && (data & BlockLogicRail.MASK_POWERED) != 0) {
             return this.powerActive;
+        } else if (this.block == Blocks.RAIL_DETECTOR && (data & BlockLogicRail.MASK_POWERED) != 0) {
+            return this.detectorActive;
         } else if (!this.block.getLogic().isPowered && data >= 6) {
             return this.railCurve;
         }
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelRepeater.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelRepeater.java
index 8091cc88b..abb449b02 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelRepeater.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelRepeater.java
@@ -1,7 +1,7 @@
 package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.LightmapHelper;
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
+import net.minecraft.client.render.tessellator.TessellatorGeneral;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.BlockLogicRepeater;
 import net.minecraft.core.block.Blocks;
@@ -19,7 +19,7 @@ public class BlockModelRepeater extends BlockModelStandard<BlockLogicRepeater> {
         super(block);
     }
 
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         int meta = worldSource.getBlockData(tilePos);
         int direction = meta & BlockLogicRepeater.MASK_DIRECTION;
 
@@ -78,13 +78,8 @@ public class BlockModelRepeater extends BlockModelStandard<BlockLogicRepeater> {
                 break;
         }
         BlockModelTorch<?> modelTorch = this.block.getLogic().isRepeaterPowered ? modelTorchActive : modelTorchIdle;
-        if (renderBlocks.overbright && this.block.getLogic().isRepeaterPowered) {
-            modelTorch.renderTorchAtAngle(tessellator, (double) tilePos.x() + d1, (double) tilePos.y() + d, (double) tilePos.z() + d2, 0.0D, 0.0D);
-            modelTorch.renderTorchAtAngle(tessellator, (double) tilePos.x() + d3, (double) tilePos.y() + d, (double) tilePos.z() + d4, 0.0D, 0.0D);
-        } else if (!renderBlocks.overbright) {
-            modelTorch.renderTorchAtAngle(tessellator, (double) tilePos.x() + d1, (double) tilePos.y() + d, (double) tilePos.z() + d2, 0.0D, 0.0D);
-            modelTorch.renderTorchAtAngle(tessellator, (double) tilePos.x() + d3, (double) tilePos.y() + d, (double) tilePos.z() + d4, 0.0D, 0.0D);
-        }
+        modelTorch.renderTorchAtAngle(tessellator, (double) tilePos.x() + d1, (double) tilePos.y() + d, (double) tilePos.z() + d2, 0.0D, 0.0D);
+        modelTorch.renderTorchAtAngle(tessellator, (double) tilePos.x() + d3, (double) tilePos.y() + d, (double) tilePos.z() + d4, 0.0D, 0.0D);
         return true;
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelRope.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelRope.java
index b81a888ad..12010d5cf 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelRope.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelRope.java
@@ -1,6 +1,6 @@
 package net.minecraft.client.render.block.model;
 
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
+import net.minecraft.client.render.tessellator.TessellatorGeneral;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.BlockLogicJarButterfly;
 import net.minecraft.core.block.BlockLogicLanternFirefly;
@@ -20,7 +20,7 @@ public class BlockModelRope<T extends BlockLogicRope>
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         Block<?> below = worldSource.getBlock(tilePos.down(new TilePos()));
         boolean hasFloor = below != null && below.canPlaceOnSurface();
         boolean hasBlockNegX = canConnect(worldSource, tilePos, Direction.WEST);
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelSeat.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelSeat.java
index 2b25f39d9..3e12d0fe1 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelSeat.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelSeat.java
@@ -1,6 +1,6 @@
 package net.minecraft.client.render.block.model;
 
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
+import net.minecraft.client.render.tessellator.TessellatorGeneral;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.util.helper.Side;
@@ -15,7 +15,7 @@ public class BlockModelSeat<T extends BlockLogic> extends BlockModelStandard<T>
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         AABBd bounds = new AABBd(this.block.getBoundsFromState(worldSource, tilePos));
 
         renderBlocks.setRenderSide(Side.BOTTOM, false); // Set bottom face to not render
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelSlab.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelSlab.java
index 78a09a529..e78c9b378 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelSlab.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelSlab.java
@@ -16,9 +16,7 @@ public class BlockModelSlab<T extends BlockLogicSlab> extends BlockModelStandard
         super(block);
         this.parentModel = (BlockModelStandard<T>) BlockModelDispatcher.getInstance().getDispatch(this.block.getLogic().modelBlock);
         this.blockTextures.copy(this.parentModel.blockTextures);
-        this.overbrightTextures.copy(this.parentModel.overbrightTextures);
         this.retroBlockTextures.copy(this.parentModel.retroBlockTextures);
-        this.retroOverbrightTextures.copy(this.parentModel.retroOverbrightTextures);
         withCustomItemBounds(0, 0, 0, 1, 0.5d, 1);
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelSpikes.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelSpikes.java
index d6dc143ed..6071b8925 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelSpikes.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelSpikes.java
@@ -1,6 +1,6 @@
 package net.minecraft.client.render.block.model;
 
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
+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;
@@ -17,7 +17,7 @@ public class BlockModelSpikes<T extends BlockLogic> extends BlockModelStandard<T
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         int metaData = worldSource.getBlockData(tilePos);
         IconCoordinate texture = getBlockTextureFromSideAndMetadata(Side.EAST, metaData);
         if (renderBlocks.overrideBlockTexture != null) {
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelStairs.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelStairs.java
index 3716fbe19..4ac11a6d5 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelStairs.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelStairs.java
@@ -1,6 +1,5 @@
 package net.minecraft.client.render.block.model;
 
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.tessellator.TessellatorGeneral;
 import net.minecraft.core.block.Block;
@@ -24,9 +23,7 @@ public class BlockModelStairs<T extends BlockLogicStairs> extends BlockModelStan
         super(block);
         this.parentModel = (BlockModelStandard<T>) BlockModelDispatcher.getInstance().getDispatch(this.block.getLogic().modelBlock);
         this.blockTextures.copy(this.parentModel.blockTextures);
-        this.overbrightTextures.copy(this.parentModel.overbrightTextures);
         this.retroBlockTextures.copy(this.parentModel.retroBlockTextures);
-        this.retroOverbrightTextures.copy(this.parentModel.retroOverbrightTextures);
 
         setDisplayPos(DisplayPos.GUI, STAIRS_GUI);
         setDisplayPos(DisplayPos.HEAD, STAIRS_HEAD);
@@ -34,7 +31,7 @@ public class BlockModelStairs<T extends BlockLogicStairs> extends BlockModelStan
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         int meta = worldSource.getBlockData(tilePos);
         int hRotation = meta & 0b0011;
         int vRotation = meta & 0b1000;
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelStandard.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelStandard.java
index c53be41f5..6bccc7236 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelStandard.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelStandard.java
@@ -1,6 +1,5 @@
 package net.minecraft.client.render.block.model;
 
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.client.render.tessellator.TessellatorGeneral;
@@ -38,14 +37,10 @@ public class BlockModelStandard<T extends BlockLogic> extends BlockModel<T> {
     public int renderLayer = 0;
 
     public static final int BLOCK_TEXTURES = 0;
-    public static final int OVERBRIGHT_TEXTURES = 1;
     public static final int RETRO_BLOCK_TEXTURES = 2;
-    public static final int RETRO_OVERBRIGHT_TEXTURES = 3;
 
     protected final TextureLayer blockTextures = new TextureLayer().setAll(BLOCK_TEXTURE_UNASSIGNED);
-    protected final TextureLayer overbrightTextures = new TextureLayer();
     protected final TextureLayer retroBlockTextures = new TextureLayer();
-    protected final TextureLayer retroOverbrightTextures = new TextureLayer();
 
     protected @NotNull Map<@NotNull String, @NotNull DisplayPos> displayPosMap = new HashMap<>();
 
@@ -69,7 +64,7 @@ public class BlockModelStandard<T extends BlockLogic> extends BlockModel<T> {
     }
 
     @Override
-    public boolean renderWithOverrideTexture(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos, IconCoordinate textureIndex) {
+    public boolean renderWithOverrideTexture(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos, IconCoordinate textureIndex) {
         renderBlocks.overrideBlockTexture = textureIndex;
         boolean result = render(tessellator, worldSource, tilePos);
         renderBlocks.overrideBlockTexture = null;
@@ -77,18 +72,10 @@ public class BlockModelStandard<T extends BlockLogic> extends BlockModel<T> {
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         return renderBlocks.renderStandardBlock(tessellator, worldSource, this, this.block.getBoundsFromState(worldSource, tilePos), tilePos);
     }
 
-    @Override
-    public boolean renderOverbright(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
-        renderBlocks.overbright = true;
-        boolean result = render(tessellator, worldSource, tilePos);
-        renderBlocks.overbright = false;
-        return result;
-    }
-
     @Override
     public void renderStandalone(@NotNull TessellatorGeneral tessellator, int metadata, int lightmapCoord) {
         AABBdc bounds = getBlockBoundsForItemRender();
@@ -120,28 +107,6 @@ public class BlockModelStandard<T extends BlockLogic> extends BlockModel<T> {
         tessellator.setNormal(1.0f, 0.0f, 0.0f);
         renderBlocks.renderEastFace(tessellator, bounds, 0.0, 0.0, 0.0, getBlockTextureFromSideAndMetadata(Side.EAST, metadata));
 
-        if (hasOverbright()) {
-            tessellator.setLightmapCoord2i(15, 15);
-
-            tessellator.setNormal(0.0f, -1.0f, 0.0f);
-            renderBlocks.renderBottomFace(tessellator, bounds, 0.0, 0.0, 0.0, getBlockOverbrightTextureFromSideAndMeta(Side.BOTTOM, metadata));
-
-            tessellator.setNormal(0.0f, 1.0f, 0.0f);
-            renderBlocks.renderTopFace(tessellator, bounds, 0.0, 0.0, 0.0, getBlockOverbrightTextureFromSideAndMeta(Side.TOP, metadata));
-
-            tessellator.setNormal(0.0f, 0.0f, -1.0f);
-            renderBlocks.renderNorthFace(tessellator, bounds, 0.0, 0.0, 0.0, getBlockOverbrightTextureFromSideAndMeta(Side.NORTH, metadata));
-
-            tessellator.setNormal(0.0f, 0.0f, 1.0f);
-            renderBlocks.renderSouthFace(tessellator, bounds, 0.0, 0.0, 0.0, getBlockOverbrightTextureFromSideAndMeta(Side.SOUTH, metadata));
-
-            tessellator.setNormal(-1.0f, 0.0f, 0.0f);
-            renderBlocks.renderWestFace(tessellator, bounds, 0.0, 0.0, 0.0, getBlockOverbrightTextureFromSideAndMeta(Side.WEST, metadata));
-
-            tessellator.setNormal(1.0f, 0.0f, 0.0f);
-            renderBlocks.renderEastFace(tessellator, bounds, 0.0, 0.0, 0.0, getBlockOverbrightTextureFromSideAndMeta(Side.EAST, metadata));
-
-        }
         tessellator.draw();
     }
 
@@ -169,15 +134,6 @@ public class BlockModelStandard<T extends BlockLogic> extends BlockModel<T> {
         return getBlockTextureFromSideAndMetadata(side, source.getBlockData(tilePos));
     }
 
-    @Deprecated
-    public final @Nullable IconCoordinate getBlockOverbrightTexture(@NotNull WorldSource source, int x, int y, int z, @NotNull Side side) {
-        return getBlockOverbrightTexture(source, new TilePos(x, y, z), side);
-    }
-
-    public @Nullable IconCoordinate getBlockOverbrightTexture(@NotNull WorldSource source, @NotNull TilePosc tilePos, @NotNull Side side) {
-        return getBlockOverbrightTextureFromSideAndMeta(side, source.getBlockData(tilePos));
-    }
-
     public int getStandaloneTintColor(int metadata) {
         if (renderBlocks.useInventoryTint) {
             return (BlockColorDispatcher.getInstance().getDispatch(this.block).getFallbackColor(metadata, 0) & 0xFFFFFF) | 0xFF000000;
@@ -185,18 +141,6 @@ public class BlockModelStandard<T extends BlockLogic> extends BlockModel<T> {
         return 0xFFFFFFFF;
     }
 
-    @Override
-    public boolean hasOverbright() {
-        return this.overbrightTextures.hasTexture();
-    }
-
-    public @Nullable IconCoordinate getBlockOverbrightTextureFromSideAndMeta(@NotNull Side side, int data) {
-        if (this.retroOverbrightTextures.hasTexture && isRetro()) {
-            return this.retroOverbrightTextures.get(side);
-        }
-        return this.overbrightTextures.get(side);
-    }
-
     public @Nullable IconCoordinate getBlockTextureFromSideAndMetadata(@NotNull Side side, int data) {
         if (this.retroBlockTextures.hasTexture && isRetro()) {
             return this.retroBlockTextures.get(side);
@@ -282,15 +226,9 @@ public class BlockModelStandard<T extends BlockLogic> extends BlockModel<T> {
             case BLOCK_TEXTURES:
                 this.blockTextures.set(coordinate, sides);
                 break;
-            case OVERBRIGHT_TEXTURES:
-                this.overbrightTextures.set(coordinate, sides);
-                break;
             case RETRO_BLOCK_TEXTURES:
                 this.retroBlockTextures.set(coordinate, sides);
                 break;
-            case RETRO_OVERBRIGHT_TEXTURES:
-                this.retroOverbrightTextures.set(coordinate, sides);
-                break;
         }
         return this;
     }
@@ -300,15 +238,9 @@ public class BlockModelStandard<T extends BlockLogic> extends BlockModel<T> {
             case BLOCK_TEXTURES:
                 this.blockTextures.set(texture, sides);
                 break;
-            case OVERBRIGHT_TEXTURES:
-                this.overbrightTextures.set(texture, sides);
-                break;
             case RETRO_BLOCK_TEXTURES:
                 this.retroBlockTextures.set(texture, sides);
                 break;
-            case RETRO_OVERBRIGHT_TEXTURES:
-                this.retroOverbrightTextures.set(texture, sides);
-                break;
         }
         return this;
     }
@@ -318,15 +250,9 @@ public class BlockModelStandard<T extends BlockLogic> extends BlockModel<T> {
             case BLOCK_TEXTURES:
                 this.blockTextures.setAll(coordinate);
                 break;
-            case OVERBRIGHT_TEXTURES:
-                this.overbrightTextures.setAll(coordinate);
-                break;
             case RETRO_BLOCK_TEXTURES:
                 this.retroBlockTextures.setAll(coordinate);
                 break;
-            case RETRO_OVERBRIGHT_TEXTURES:
-                this.retroOverbrightTextures.setAll(coordinate);
-                break;
         }
         return this;
     }
@@ -336,26 +262,13 @@ public class BlockModelStandard<T extends BlockLogic> extends BlockModel<T> {
             case BLOCK_TEXTURES:
                 this.blockTextures.setAll(texture);
                 break;
-            case OVERBRIGHT_TEXTURES:
-                this.overbrightTextures.setAll(texture);
-                break;
             case RETRO_BLOCK_TEXTURES:
                 this.retroBlockTextures.setAll(texture);
                 break;
-            case RETRO_OVERBRIGHT_TEXTURES:
-                this.retroOverbrightTextures.setAll(texture);
-                break;
         }
         return this;
     }
 
-
-    @Deprecated
-    public BlockModelStandard<T> withOverbrightTexture(String texture) {
-        this.overbrightTextures.setAll(texture);
-        return this;
-    }
-
     @Deprecated
     public BlockModelStandard<T> withTextures(String texture) {
         this.blockTextures.setAll(texture);
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelStoneMossy.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelStoneMossy.java
index 2d9079661..593d0c117 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelStoneMossy.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelStoneMossy.java
@@ -1,6 +1,5 @@
 package net.minecraft.client.render.block.model;
 
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.client.render.tessellator.TessellatorGeneral;
@@ -21,7 +20,7 @@ public class BlockModelStoneMossy<T extends BlockLogic> extends BlockModelStanda
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         AABBdc bounds = this.block.getBoundsFromState(worldSource, tilePos);
         renderBlocks.renderStandardBlock(tessellator, worldSource, this, bounds, tilePos, 1.0f, 1.0f, 1.0f);
         renderBlocks.overrideBlockTexture = this.mossOverlay;
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelTorch.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelTorch.java
index 5f8ee000f..c4d0d5302 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelTorch.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelTorch.java
@@ -1,8 +1,7 @@
 package net.minecraft.client.render.block.model;
 
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
-import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 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.BlockLogicTorch;
@@ -17,7 +16,7 @@ public class BlockModelTorch<T extends BlockLogic> extends BlockModelStandard<T>
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         float brightness = 1.0f;
         tessellator.setLightmapCoord1i(this.block.getLightmapCoord(worldSource, tilePos));
         tessellator.setColorOpaque3f(brightness, brightness, brightness);
@@ -45,7 +44,7 @@ public class BlockModelTorch<T extends BlockLogic> extends BlockModelStandard<T>
         return true;
     }
 
-    public void renderTorchAtAngle(TessellatorTerrain tessellator, double x, double y, double z, double topOffsetX, double topOffsetZ) {
+    public void renderTorchAtAngle(@NotNull TessellatorGeneral tessellator, double x, double y, double z, double topOffsetX, double topOffsetZ) {
         IconCoordinate texture = getBlockTextureFromSideAndMetadata(Side.BOTTOM, 0);
         if (renderBlocks.overrideBlockTexture != null) {
             texture = renderBlocks.overrideBlockTexture;
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelTrapDoor.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelTrapDoor.java
index 04d44863e..13dbccce2 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelTrapDoor.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelTrapDoor.java
@@ -1,6 +1,5 @@
 package net.minecraft.client.render.block.model;
 
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.tessellator.TessellatorGeneral;
 import net.minecraft.core.block.Block;
@@ -22,7 +21,7 @@ public class BlockModelTrapDoor<T extends BlockLogic> extends BlockModelStandard
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         int metadata = worldSource.getBlockData(tilePos);
         boolean isUp = BlockLogicTrapDoor.isTrapdoorOpen(metadata);
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelVeryRotatable.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelVeryRotatable.java
index f8c54a8d2..0310391f4 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelVeryRotatable.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelVeryRotatable.java
@@ -1,7 +1,6 @@
 package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.tessellator.TessellatorGeneral;
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.BlockLogic;
@@ -28,7 +27,7 @@ public class BlockModelVeryRotatable<T extends BlockLogic> extends BlockModelSta
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         final int meta = worldSource.getBlockData(tilePos);
         final Direction dir = BlockLogicVeryRotatable.metaToDirection(meta);
 
@@ -56,11 +55,6 @@ public class BlockModelVeryRotatable<T extends BlockLogic> extends BlockModelSta
         renderBlocks.resetRenderBlocks();
     }
 
-    @Override
-    public @Nullable IconCoordinate getBlockOverbrightTextureFromSideAndMeta(@NotNull Side side, int data) {
-        return super.getBlockOverbrightTextureFromSideAndMeta(getRotatedSide(side, data), data);
-    }
-
     @Override
     public @Nullable IconCoordinate getBlockTextureFromSideAndMetadata(@NotNull Side side, int data) {
         return super.getBlockTextureFromSideAndMetadata(getRotatedSide(side, data), data);
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelWireRedstone.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelWireRedstone.java
index 44168af52..3f1d2099f 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelWireRedstone.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelWireRedstone.java
@@ -1,7 +1,7 @@
 package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.LightmapHelper;
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
+import net.minecraft.client.render.tessellator.TessellatorGeneral;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.client.util.helper.Colors;
@@ -26,7 +26,7 @@ public class BlockModelWireRedstone<T extends BlockLogic> extends BlockModelStan
     }
 
     @Override
-    public boolean render(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
+    public boolean render(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull TilePosc tilePos) {
         int meta = worldSource.getBlockData(tilePos);
         IconCoordinate straight = this.wireStraight;
         IconCoordinate cross = this.wireCross;
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/RenderBlocks.java b/game/client/src/main/java/net/minecraft/client/render/block/model/RenderBlocks.java
index 77a5162ef..eaeb793e3 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/RenderBlocks.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/RenderBlocks.java
@@ -2,7 +2,7 @@ package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.LightingCache;
 import net.minecraft.client.render.LightmapHelper;
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
+import net.minecraft.client.render.tessellator.TessellatorGeneral;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.world.pos.TilePos;
 import net.minecraft.core.world.pos.TilePosc;
@@ -14,12 +14,10 @@ import net.minecraft.client.Minecraft;
 import net.minecraft.client.render.block.color.BlockColorDispatcher;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.enums.LightLayer;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.WorldSource;
 
 import static net.minecraft.client.render.block.model.BlockModel.FULL_CUBE_THRESHOLD;
-import static net.minecraft.client.render.block.model.BlockModel.SIDE_LIGHT_MULTIPLIER;
 
 public final class RenderBlocks {
     public final Minecraft mc;
@@ -51,7 +49,6 @@ public final class RenderBlocks {
     public int lightmapCoordBottomLeft;
     public int lightmapCoordBottomRight;
     public int lightmapCoordTopRight;
-    public boolean overbright;
     public LightingCache cache = new LightingCache();
 
     public RenderBlocks() {
@@ -111,11 +108,11 @@ public final class RenderBlocks {
     }
 
     @Deprecated
-    public boolean renderStandardBlock(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull BlockModelStandard<?> blockModel, @NotNull AABBdc bounds, int x, int y, int z) {
+    public boolean renderStandardBlock(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull BlockModelStandard<?> blockModel, @NotNull AABBdc bounds, int x, int y, int z) {
         return renderStandardBlock(tessellator, worldSource, blockModel, bounds, new TilePos(x, y, z));
     }
 
-    public boolean renderStandardBlock(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull BlockModelStandard<?> blockModel, @NotNull AABBdc bounds, @NotNull TilePosc tilePos) {
+    public boolean renderStandardBlock(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull BlockModelStandard<?> blockModel, @NotNull AABBdc bounds, @NotNull TilePosc tilePos) {
         int color = BlockColorDispatcher.getInstance().getDispatch(blockModel.block).getWorldColor(worldSource, tilePos, 0);
         float r = (float) (color >> 16 & 0xff) / 255F;
         float g = (float) (color >> 8 & 0xff) / 255F;
@@ -128,11 +125,11 @@ public final class RenderBlocks {
      * Thanks! :D
      */
     @Deprecated
-    public boolean renderStandardBlock(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull BlockModelStandard<?> blockModel, @NotNull AABBdc bounds, int x, int y, int z, float r, float g, float b) {
+    public boolean renderStandardBlock(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull BlockModelStandard<?> blockModel, @NotNull AABBdc bounds, int x, int y, int z, float r, float g, float b) {
         return renderStandardBlock(tessellator, worldSource, blockModel, bounds, new TilePos(x, y, z), r, g, b);
     }
 
-    public boolean renderStandardBlock(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull BlockModelStandard<?> blockModel, @NotNull AABBdc bounds, @NotNull TilePosc tilePos, float r, float g, float b) {
+    public boolean renderStandardBlock(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull BlockModelStandard<?> blockModel, @NotNull AABBdc bounds, @NotNull TilePosc tilePos, float r, float g, float b) {
         this.enableAO = true;
         int meta = worldSource.getBlockData(tilePos);
         this.cache.setupCache(blockModel.block, worldSource, tilePos);
@@ -145,11 +142,11 @@ public final class RenderBlocks {
     }
 
     @Deprecated
-    public boolean renderSide(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull BlockModelStandard<?> blockModel, @NotNull AABBdc bounds, int x, int y, int z, float r, float g, float b, @NotNull Side side, int meta) {
+    public boolean renderSide(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull BlockModelStandard<?> blockModel, @NotNull AABBdc bounds, int x, int y, int z, float r, float g, float b, @NotNull Side side, int meta) {
         return renderSide(tessellator, worldSource, blockModel, bounds, new TilePos(x, y, z), r, g, b, side, meta);
     }
 
-    public boolean renderSide(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull BlockModelStandard<?> blockModel, @NotNull AABBdc bounds, @NotNull TilePosc tilePos, float r, float g, float b, @NotNull Side side, int meta) {
+    public boolean renderSide(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull BlockModelStandard<?> blockModel, @NotNull AABBdc bounds, @NotNull TilePosc tilePos, float r, float g, float b, @NotNull Side side, int meta) {
         boolean useColor;
         return switch (side) {
             case BOTTOM -> {
@@ -208,18 +205,13 @@ public final class RenderBlocks {
      * @author CyborgCabbage
      * Thanks! :D
      */
-    public boolean renderSide(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull BlockModelStandard<?> blockModel, @NotNull AABBdc bounds,
+    public boolean renderSide(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull BlockModelStandard<?> blockModel, @NotNull AABBdc bounds,
                               @NotNull TilePosc tilePos, float r, float g, float b, @NotNull Side side, int meta,
                               int dirX, int dirY, int dirZ, float depth,
                               int topX, int topY, int topZ, float topP, float botP,
                               int lefX, int lefY, int lefZ, float lefP, float rigP
     ) {
-        IconCoordinate tex;
-        if (this.overbright) {
-            tex = blockModel.getBlockOverbrightTexture(worldSource, tilePos, side);
-        } else {
-            tex = blockModel.getBlockTexture(worldSource, tilePos, side);
-        }
+        IconCoordinate tex = blockModel.getBlockTexture(worldSource, tilePos, side);
         if (tex == null || ((this.renderBitMask >> side.getId()) & 1) != 0) return false;
 
         boolean rendered = false;
@@ -262,7 +254,7 @@ public final class RenderBlocks {
         boolean ao = this.mc.isAmbientOcclusionEnabled() && block.emission == 0;
         boolean isFullCube = depth <= FULL_CUBE_THRESHOLD;
 
-        if (this.overbright) {
+        if (ao) {
             int dirX2 = dirX;
             int dirY2 = dirY;
             int dirZ2 = dirZ;
@@ -273,56 +265,40 @@ public final class RenderBlocks {
                 dirZ2 = 0;
             }
 
-            int lmc = LightmapHelper.getOverbrightLightmapCoord(worldSource.getSavedLightValue(LightLayer.Sky, dirX2, dirY2, dirZ2));
+            boolean topT = this.cache.getOpacity(dirX2 + topX, dirY2 + topY, dirZ2 + topZ);
+            boolean botT = this.cache.getOpacity(dirX2 - topX, dirY2 - topY, dirZ2 - topZ);
+            boolean lefT = this.cache.getOpacity(dirX2 + lefX, dirY2 + lefY, dirZ2 + lefZ);
+            boolean rigT = this.cache.getOpacity(dirX2 - lefX, dirY2 - lefY, dirZ2 - lefZ);
 
-            this.lightmapCoordTopLeft = this.lightmapCoordBottomLeft = this.lightmapCoordBottomRight = this.lightmapCoordTopRight = lmc;
+            boolean topLefT = this.cache.getOpacity(dirX2 + topX + lefX, dirY2 + topY + lefY, dirZ2 + topZ + lefZ);
+            boolean topRigT = this.cache.getOpacity(dirX2 + topX - lefX, dirY2 + topY - lefY, dirZ2 + topZ - lefZ);
+            boolean botLefT = this.cache.getOpacity(dirX2 - topX + lefX, dirY2 - topY + lefY, dirZ2 - topZ + lefZ);
+            boolean botRigT = this.cache.getOpacity(dirX2 - topX - lefX, dirY2 - topY - lefY, dirZ2 - topZ - lefZ);
+
+            int lmcCen = this.cache.getLightmapCoord(dirX2, dirY2, dirZ2);
+
+            int lmcTop = topT ? lmcCen : this.cache.getLightmapCoord(dirX2 + topX, dirY2 + topY, dirZ2 + topZ);
+            int lmcBot = botT ? lmcCen : this.cache.getLightmapCoord(dirX2 - topX, dirY2 - topY, dirZ2 - topZ);
+            int lmcLef = lefT ? lmcCen : this.cache.getLightmapCoord(dirX2 + lefX, dirY2 + lefY, dirZ2 + lefZ);
+            int lmcRig = rigT ? lmcCen : this.cache.getLightmapCoord(dirX2 - lefX, dirY2 - lefY, dirZ2 - lefZ);
+
+            int lmcTopLef = topT && lefT ? lmcLef : (topLefT ? lmcCen : this.cache.getLightmapCoord(dirX2 + topX + lefX, dirY2 + topY + lefY, dirZ2 + topZ + lefZ));
+            int lmcBotLef = botT && lefT ? lmcLef : (botLefT ? lmcCen : this.cache.getLightmapCoord(dirX2 - topX + lefX, dirY2 - topY + lefY, dirZ2 - topZ + lefZ));
+            int lmcTopRig = topT && rigT ? lmcRig : (topRigT ? lmcCen : this.cache.getLightmapCoord(dirX2 + topX - lefX, dirY2 + topY - lefY, dirZ2 + topZ - lefZ));
+            int lmcBotRig = botT && rigT ? lmcRig : (botRigT ? lmcCen : this.cache.getLightmapCoord(dirX2 - topX - lefX, dirY2 - topY - lefY, dirZ2 - topZ - lefZ));
+
+            this.lightmapCoordTopLeft = LightmapHelper.avg(lmcCen, lmcLef, lmcTop, lmcTopLef);
+            this.lightmapCoordTopRight = LightmapHelper.avg(lmcCen, lmcRig, lmcTop, lmcTopRig);
+            this.lightmapCoordBottomLeft = LightmapHelper.avg(lmcCen, lmcLef, lmcBot, lmcBotLef);
+            this.lightmapCoordBottomRight = LightmapHelper.avg(lmcCen, lmcRig, lmcBot, lmcBotRig);
         } else {
-            if (ao) {
-                int dirX2 = dirX;
-                int dirY2 = dirY;
-                int dirZ2 = dirZ;
-
-                if (!isFullCube) {
-                    dirX2 = 0;
-                    dirY2 = 0;
-                    dirZ2 = 0;
-                }
-
-                boolean topT = this.cache.getOpacity(dirX2 + topX, dirY2 + topY, dirZ2 + topZ);
-                boolean botT = this.cache.getOpacity(dirX2 - topX, dirY2 - topY, dirZ2 - topZ);
-                boolean lefT = this.cache.getOpacity(dirX2 + lefX, dirY2 + lefY, dirZ2 + lefZ);
-                boolean rigT = this.cache.getOpacity(dirX2 - lefX, dirY2 - lefY, dirZ2 - lefZ);
-
-                boolean topLefT = this.cache.getOpacity(dirX2 + topX + lefX, dirY2 + topY + lefY, dirZ2 + topZ + lefZ);
-                boolean topRigT = this.cache.getOpacity(dirX2 + topX - lefX, dirY2 + topY - lefY, dirZ2 + topZ - lefZ);
-                boolean botLefT = this.cache.getOpacity(dirX2 - topX + lefX, dirY2 - topY + lefY, dirZ2 - topZ + lefZ);
-                boolean botRigT = this.cache.getOpacity(dirX2 - topX - lefX, dirY2 - topY - lefY, dirZ2 - topZ - lefZ);
-
-                int lmcCen = this.cache.getLightmapCoord(dirX2, dirY2, dirZ2);
-
-                int lmcTop = topT ? lmcCen : this.cache.getLightmapCoord(dirX2 + topX, dirY2 + topY, dirZ2 + topZ);
-                int lmcBot = botT ? lmcCen : this.cache.getLightmapCoord(dirX2 - topX, dirY2 - topY, dirZ2 - topZ);
-                int lmcLef = lefT ? lmcCen : this.cache.getLightmapCoord(dirX2 + lefX, dirY2 + lefY, dirZ2 + lefZ);
-                int lmcRig = rigT ? lmcCen : this.cache.getLightmapCoord(dirX2 - lefX, dirY2 - lefY, dirZ2 - lefZ);
-
-                int lmcTopLef = topT && lefT ? lmcLef : (topLefT ? lmcCen : this.cache.getLightmapCoord(dirX2 + topX + lefX, dirY2 + topY + lefY, dirZ2 + topZ + lefZ));
-                int lmcBotLef = botT && lefT ? lmcLef : (botLefT ? lmcCen : this.cache.getLightmapCoord(dirX2 - topX + lefX, dirY2 - topY + lefY, dirZ2 - topZ + lefZ));
-                int lmcTopRig = topT && rigT ? lmcRig : (topRigT ? lmcCen : this.cache.getLightmapCoord(dirX2 + topX - lefX, dirY2 + topY - lefY, dirZ2 + topZ - lefZ));
-                int lmcBotRig = botT && rigT ? lmcRig : (botRigT ? lmcCen : this.cache.getLightmapCoord(dirX2 - topX - lefX, dirY2 - topY - lefY, dirZ2 - topZ - lefZ));
-
-                this.lightmapCoordTopLeft = LightmapHelper.avg(lmcCen, lmcLef, lmcTop, lmcTopLef);
-                this.lightmapCoordTopRight = LightmapHelper.avg(lmcCen, lmcRig, lmcTop, lmcTopRig);
-                this.lightmapCoordBottomLeft = LightmapHelper.avg(lmcCen, lmcLef, lmcBot, lmcBotLef);
-                this.lightmapCoordBottomRight = LightmapHelper.avg(lmcCen, lmcRig, lmcBot, lmcBotRig);
+            int lmc;
+            if (!isFullCube) {
+                lmc = block.getLightmapCoord(worldSource, tilePos);
             } else {
-                int lmc;
-                if (!isFullCube) {
-                    lmc = block.getLightmapCoord(worldSource, tilePos);
-                } else {
-                    lmc = block.getLightmapCoord(worldSource, tilePos.add(dirX, dirY, dirZ, new TilePos()));
-                }
-                this.lightmapCoordTopLeft = this.lightmapCoordBottomLeft = this.lightmapCoordBottomRight = this.lightmapCoordTopRight = lmc;
+                lmc = block.getLightmapCoord(worldSource, tilePos.add(dirX, dirY, dirZ, new TilePos()));
             }
+            this.lightmapCoordTopLeft = this.lightmapCoordBottomLeft = this.lightmapCoordBottomRight = this.lightmapCoordTopRight = lmc;
         }
 
         float lightTR;
@@ -330,76 +306,63 @@ public final class RenderBlocks {
         float lightBL;
         float lightTL;
 
-        if (this.overbright) {
-            lightTR = 1.0F;
-            lightBR = 1.0F;
-            lightBL = 1.0F;
-            lightTL = 1.0F;
+        if (ao) {
+            {
+                float dirB = this.cache.getBrightness(dirX, dirY, dirZ);
+                boolean lefT = this.cache.getOpacity(dirX + lefX, dirY + lefY, dirZ + lefZ);
+                boolean botT = this.cache.getOpacity(dirX - topX, dirY - topY, dirZ - topZ);
+                boolean topT = this.cache.getOpacity(dirX + topX, dirY + topY, dirZ + topZ);
+                boolean rigT = this.cache.getOpacity(dirX - lefX, dirY - lefY, dirZ - lefZ);
+                float lB = this.cache.getBrightness(dirX + lefX, dirY + lefY, dirZ + lefZ);
+                float bB = this.cache.getBrightness(dirX - topX, dirY - topY, dirZ - topZ);
+                float tB = this.cache.getBrightness(dirX + topX, dirY + topY, dirZ + topZ);
+                float rB = this.cache.getBrightness(dirX - lefX, dirY - lefY, dirZ - lefZ);
+                float blB = botT && lefT ? lB : this.cache.getBrightness(dirX + lefX - topX, dirY + lefY - topY, dirZ + lefZ - topZ);
+                float tlB = topT && lefT ? lB : this.cache.getBrightness(dirX + lefX + topX, dirY + lefY + topY, dirZ + lefZ + topZ);
+                float brB = botT && rigT ? rB : this.cache.getBrightness(dirX - lefX - topX, dirY - lefY - topY, dirZ - lefZ - topZ);
+                float trB = topT && rigT ? rB : this.cache.getBrightness(dirX - lefX + topX, dirY - lefY + topY, dirZ - lefZ + topZ);
+                lightTL = (tlB + lB + tB + dirB) / 4.0F;
+                lightTR = (tB + dirB + trB + rB) / 4.0F;
+                lightBR = (dirB + bB + rB + brB) / 4.0F;
+                lightBL = (lB + blB + dirB + bB) / 4.0F;
+            }
+            if (!isFullCube) {
+                float dirB = this.cache.getBrightness(0, 0, 0);
+                boolean lefT = this.cache.getOpacity(lefX, lefY, lefZ);
+                boolean botT = this.cache.getOpacity(-topX, -topY, -topZ);
+                boolean topT = this.cache.getOpacity(topX, topY, topZ);
+                boolean rigT = this.cache.getOpacity(-lefX, -lefY, -lefZ);
+                float lB = this.cache.getBrightness(lefX, lefY, lefZ);
+                float bB = this.cache.getBrightness(-topX, -topY, -topZ);
+                float tB = this.cache.getBrightness(topX, topY, topZ);
+                float rB = this.cache.getBrightness(-lefX, -lefY, -lefZ);
+                float blB = botT && lefT ? lB : this.cache.getBrightness(lefX - topX, lefY - topY, lefZ - topZ);
+                float tlB = topT && lefT ? lB : this.cache.getBrightness(lefX + topX, lefY + topY, lefZ + topZ);
+                float brB = botT && rigT ? rB : this.cache.getBrightness(-lefX - topX, -lefY - topY, -lefZ - topZ);
+                float trB = topT && rigT ? rB : this.cache.getBrightness(-lefX + topX, -lefY + topY, -lefZ + topZ);
+                lightTL = (tlB + lB + tB + dirB) / 4.0F * depth + lightTL * (1 - depth);
+                lightTR = (tB + dirB + trB + rB) / 4.0F * depth + lightTR * (1 - depth);
+                lightBR = (dirB + bB + rB + brB) / 4.0F * depth + lightBR * (1 - depth);
+                lightBL = (lB + blB + dirB + bB) / 4.0F * depth + lightBL * (1 - depth);
+            }
         } else {
-            if (ao) {
-                {
-                    float dirB = this.cache.getBrightness(dirX, dirY, dirZ);
-                    boolean lefT = this.cache.getOpacity(dirX + lefX, dirY + lefY, dirZ + lefZ);
-                    boolean botT = this.cache.getOpacity(dirX - topX, dirY - topY, dirZ - topZ);
-                    boolean topT = this.cache.getOpacity(dirX + topX, dirY + topY, dirZ + topZ);
-                    boolean rigT = this.cache.getOpacity(dirX - lefX, dirY - lefY, dirZ - lefZ);
-                    float lB = this.cache.getBrightness(dirX + lefX, dirY + lefY, dirZ + lefZ);
-                    float bB = this.cache.getBrightness(dirX - topX, dirY - topY, dirZ - topZ);
-                    float tB = this.cache.getBrightness(dirX + topX, dirY + topY, dirZ + topZ);
-                    float rB = this.cache.getBrightness(dirX - lefX, dirY - lefY, dirZ - lefZ);
-                    float blB = botT && lefT ? lB : this.cache.getBrightness(dirX + lefX - topX, dirY + lefY - topY, dirZ + lefZ - topZ);
-                    float tlB = topT && lefT ? lB : this.cache.getBrightness(dirX + lefX + topX, dirY + lefY + topY, dirZ + lefZ + topZ);
-                    float brB = botT && rigT ? rB : this.cache.getBrightness(dirX - lefX - topX, dirY - lefY - topY, dirZ - lefZ - topZ);
-                    float trB = topT && rigT ? rB : this.cache.getBrightness(dirX - lefX + topX, dirY - lefY + topY, dirZ - lefZ + topZ);
-                    lightTL = (tlB + lB + tB + dirB) / 4.0F;
-                    lightTR = (tB + dirB + trB + rB) / 4.0F;
-                    lightBR = (dirB + bB + rB + brB) / 4.0F;
-                    lightBL = (lB + blB + dirB + bB) / 4.0F;
-                }
-                if (!isFullCube) {
-                    float dirB = this.cache.getBrightness(0, 0, 0);
-                    boolean lefT = this.cache.getOpacity(lefX, lefY, lefZ);
-                    boolean botT = this.cache.getOpacity(-topX, -topY, -topZ);
-                    boolean topT = this.cache.getOpacity(topX, topY, topZ);
-                    boolean rigT = this.cache.getOpacity(-lefX, -lefY, -lefZ);
-                    float lB = this.cache.getBrightness(lefX, lefY, lefZ);
-                    float bB = this.cache.getBrightness(-topX, -topY, -topZ);
-                    float tB = this.cache.getBrightness(topX, topY, topZ);
-                    float rB = this.cache.getBrightness(-lefX, -lefY, -lefZ);
-                    float blB = botT && lefT ? lB : this.cache.getBrightness(lefX - topX, lefY - topY, lefZ - topZ);
-                    float tlB = topT && lefT ? lB : this.cache.getBrightness(lefX + topX, lefY + topY, lefZ + topZ);
-                    float brB = botT && rigT ? rB : this.cache.getBrightness(-lefX - topX, -lefY - topY, -lefZ - topZ);
-                    float trB = topT && rigT ? rB : this.cache.getBrightness(-lefX + topX, -lefY + topY, -lefZ + topZ);
-                    lightTL = (tlB + lB + tB + dirB) / 4.0F * depth + lightTL * (1 - depth);
-                    lightTR = (tB + dirB + trB + rB) / 4.0F * depth + lightTR * (1 - depth);
-                    lightBR = (dirB + bB + rB + brB) / 4.0F * depth + lightBR * (1 - depth);
-                    lightBL = (lB + blB + dirB + bB) / 4.0F * depth + lightBL * (1 - depth);
-                }
-            } else {
-                int dirX2 = dirX;
-                int dirY2 = dirY;
-                int dirZ2 = dirZ;
-
-                if (!isFullCube) {
-                    dirX2 = 0;
-                    dirY2 = 0;
-                    dirZ2 = 0;
-                }
-
-                float brightness = this.cache.getBrightness(dirX2, dirY2, dirZ2);
-                lightTL = lightBL = lightBR = lightTR = brightness;
+            int dirX2 = dirX;
+            int dirY2 = dirY;
+            int dirZ2 = dirZ;
+
+            if (!isFullCube) {
+                dirX2 = 0;
+                dirY2 = 0;
+                dirZ2 = 0;
             }
-        }
 
-        if (this.overbright || !BlockModel.ENABLE_DIRECTIONAL_LIGHTING) {
-            this.colorRedTopLeft = this.colorRedBottomLeft = this.colorRedBottomRight = this.colorRedTopRight = r;
-            this.colorGreenTopLeft = this.colorGreenBottomLeft = this.colorGreenBottomRight = this.colorGreenTopRight = g;
-            this.colorBlueTopLeft = this.colorBlueBottomLeft = this.colorBlueBottomRight = this.colorBlueTopRight = b;
-        } else {
-            this.colorRedTopLeft = this.colorRedBottomLeft = this.colorRedBottomRight = this.colorRedTopRight = r * SIDE_LIGHT_MULTIPLIER[side.getId()];
-            this.colorGreenTopLeft = this.colorGreenBottomLeft = this.colorGreenBottomRight = this.colorGreenTopRight = g * SIDE_LIGHT_MULTIPLIER[side.getId()];
-            this.colorBlueTopLeft = this.colorBlueBottomLeft = this.colorBlueBottomRight = this.colorBlueTopRight = b * SIDE_LIGHT_MULTIPLIER[side.getId()];
+            float brightness = this.cache.getBrightness(dirX2, dirY2, dirZ2);
+            lightTL = lightBL = lightBR = lightTR = brightness;
         }
+
+        this.colorRedTopLeft = this.colorRedBottomLeft = this.colorRedBottomRight = this.colorRedTopRight = r;
+        this.colorGreenTopLeft = this.colorGreenBottomLeft = this.colorGreenBottomRight = this.colorGreenTopRight = g;
+        this.colorBlueTopLeft = this.colorBlueBottomLeft = this.colorBlueBottomRight = this.colorBlueTopRight = b;
         float tl = topP * lightTL + (1 - topP) * lightBL;
         float tr = topP * lightTR + (1 - topP) * lightBR;
         float bl = botP * lightTL + (1 - botP) * lightBL;
@@ -425,11 +388,11 @@ public final class RenderBlocks {
         this.colorBlueTopRight *= ltr;
     }
 
-    public void renderBottomFace(@NotNull TessellatorTerrain tessellator, @NotNull AABBdc bounds, @NotNull TilePosc tilePos, @Nullable IconCoordinate tex) {
+    public void renderBottomFace(@NotNull TessellatorGeneral tessellator, @NotNull AABBdc bounds, @NotNull TilePosc tilePos, @Nullable IconCoordinate tex) {
         renderBottomFace(tessellator, bounds, tilePos.x(), tilePos.y(), tilePos.z(), tex);
     }
 
-    public void renderBottomFace(@NotNull TessellatorTerrain tessellator, @NotNull AABBdc bounds, double x, double y, double z, @Nullable IconCoordinate tex) {
+    public void renderBottomFace(@NotNull TessellatorGeneral tessellator, @NotNull AABBdc bounds, double x, double y, double z, @Nullable IconCoordinate tex) {
         if (this.overrideBlockTexture != null) tex = this.overrideBlockTexture;
         if (tex == null) return;
         double d3 = tex.getSubIconU(bounds.minX());
@@ -485,6 +448,7 @@ public final class RenderBlocks {
         double d13 = y + bounds.minY();
         double d14 = z + bounds.minZ();
         double d15 = z + bounds.maxZ();
+        tessellator.setNormal(0, -1, 0);
         if (this.enableAO) {
             tessellator.setLightmapCoord1i(this.lightmapCoordTopLeft);
             tessellator.setColorOpaque3f(this.colorRedTopLeft, this.colorGreenTopLeft, this.colorBlueTopLeft);
@@ -504,13 +468,14 @@ public final class RenderBlocks {
             tessellator.addVertexWithUV(d12, d13, d14, d7, d9);
             tessellator.addVertexWithUV(d12, d13, d15, d4, d6);
         }
+        tessellator.setNormal(0, 1, 0);
     }
 
-    public void renderTopFace(@NotNull TessellatorTerrain tessellator, @NotNull AABBdc bounds, @NotNull TilePosc tilePos, @Nullable IconCoordinate tex) {
+    public void renderTopFace(@NotNull TessellatorGeneral tessellator, @NotNull AABBdc bounds, @NotNull TilePosc tilePos, @Nullable IconCoordinate tex) {
         renderTopFace(tessellator, bounds, tilePos.x(), tilePos.y(), tilePos.z(), tex);
     }
 
-    public void renderTopFace(@NotNull TessellatorTerrain tessellator, @NotNull AABBdc bounds, double x, double y, double z, @Nullable IconCoordinate tex) {
+    public void renderTopFace(@NotNull TessellatorGeneral tessellator, @NotNull AABBdc bounds, double x, double y, double z, @Nullable IconCoordinate tex) {
         if (this.overrideBlockTexture != null) tex = this.overrideBlockTexture;
         if (tex == null) return;
         double d3 = tex.getSubIconU(bounds.minX());
@@ -566,6 +531,7 @@ public final class RenderBlocks {
         double d13 = y + bounds.maxY();
         double d14 = z + bounds.minZ();
         double d15 = z + bounds.maxZ();
+        tessellator.setNormal(0, 1, 0);
         if (this.enableAO) {
             tessellator.setLightmapCoord1i(this.lightmapCoordTopLeft);
             tessellator.setColorOpaque3f(this.colorRedTopLeft, this.colorGreenTopLeft, this.colorBlueTopLeft);
@@ -585,13 +551,14 @@ public final class RenderBlocks {
             tessellator.addVertexWithUV(d11, d13, d14, d3, d5);
             tessellator.addVertexWithUV(d11, d13, d15, d8, d10);
         }
+        tessellator.setNormal(0, 1, 0);
     }
 
-    public void renderNorthFace(@NotNull TessellatorTerrain tessellator, @NotNull AABBdc bounds, @NotNull TilePosc tilePos, @Nullable IconCoordinate tex) {
+    public void renderNorthFace(@NotNull TessellatorGeneral tessellator, @NotNull AABBdc bounds, @NotNull TilePosc tilePos, @Nullable IconCoordinate tex) {
         renderNorthFace(tessellator, bounds, tilePos.x(), tilePos.y(), tilePos.z(), tex);
     }
 
-    public void renderNorthFace(@NotNull TessellatorTerrain tessellator, @NotNull AABBdc bounds, double x, double y, double z, @Nullable IconCoordinate tex) {
+    public void renderNorthFace(@NotNull TessellatorGeneral tessellator, @NotNull AABBdc bounds, double x, double y, double z, @Nullable IconCoordinate tex) {
         if (this.overrideBlockTexture != null) tex = this.overrideBlockTexture;
         if (tex == null) return;
         double d3 = tex.getSubIconU(bounds.minX());
@@ -652,6 +619,7 @@ public final class RenderBlocks {
         double d14 = y + bounds.minY();
         double d15 = y + bounds.maxY();
         double d16 = z + bounds.minZ();
+        tessellator.setNormal(0, 0, -1);
         if (this.enableAO) {
             tessellator.setLightmapCoord1i(this.lightmapCoordTopLeft);
             tessellator.setColorOpaque3f(this.colorRedTopLeft, this.colorGreenTopLeft, this.colorBlueTopLeft);
@@ -671,13 +639,14 @@ public final class RenderBlocks {
             tessellator.addVertexWithUV(d13, d14, d16, d9, d11);
             tessellator.addVertexWithUV(d12, d14, d16, d4, d6);
         }
+        tessellator.setNormal(0, 1, 0);
     }
 
-    public void renderSouthFace(@NotNull TessellatorTerrain tessellator, @NotNull AABBdc bounds, @NotNull TilePosc tilePos, @Nullable IconCoordinate tex) {
+    public void renderSouthFace(@NotNull TessellatorGeneral tessellator, @NotNull AABBdc bounds, @NotNull TilePosc tilePos, @Nullable IconCoordinate tex) {
         renderSouthFace(tessellator, bounds, tilePos.x(), tilePos.y(), tilePos.z(), tex);
     }
 
-    public void renderSouthFace(@NotNull TessellatorTerrain tessellator, @NotNull AABBdc bounds, double x, double y, double z, @Nullable IconCoordinate tex) {
+    public void renderSouthFace(@NotNull TessellatorGeneral tessellator, @NotNull AABBdc bounds, double x, double y, double z, @Nullable IconCoordinate tex) {
         if (this.overrideBlockTexture != null) tex = this.overrideBlockTexture;
         if (tex == null) return;
         double d3 = tex.getSubIconU(bounds.minX());
@@ -738,6 +707,7 @@ public final class RenderBlocks {
         double y0 = y + bounds.minY();
         double y1 = y + bounds.maxY();
         double z0 = z + bounds.maxZ();
+        tessellator.setNormal(0, 0, 1);
         if (this.enableAO) {
             tessellator.setLightmapCoord1i(this.lightmapCoordTopLeft);
             tessellator.setColorOpaque3f(this.colorRedTopLeft, this.colorGreenTopLeft, this.colorBlueTopLeft);
@@ -757,13 +727,14 @@ public final class RenderBlocks {
             tessellator.addVertexWithUV(x1, y0, z0, d4, d6);
             tessellator.addVertexWithUV(x1, y1, z0, d8, d10);
         }
+        tessellator.setNormal(0, 1, 0);
     }
 
-    public void renderWestFace(@NotNull TessellatorTerrain tessellator, @NotNull AABBdc bounds, @NotNull TilePosc tilePos, @Nullable IconCoordinate tex) {
+    public void renderWestFace(@NotNull TessellatorGeneral tessellator, @NotNull AABBdc bounds, @NotNull TilePosc tilePos, @Nullable IconCoordinate tex) {
         renderWestFace(tessellator, bounds, tilePos.x(), tilePos.y(), tilePos.z(), tex);
     }
 
-    public void renderWestFace(@NotNull TessellatorTerrain tessellator, @NotNull AABBdc bounds, double x, double y, double z, @Nullable IconCoordinate tex) {
+    public void renderWestFace(@NotNull TessellatorGeneral tessellator, @NotNull AABBdc bounds, double x, double y, double z, @Nullable IconCoordinate tex) {
         if (this.overrideBlockTexture != null) tex = this.overrideBlockTexture;
         if (tex == null) return;
         double d3 = tex.getSubIconU(bounds.minZ());
@@ -824,6 +795,7 @@ public final class RenderBlocks {
         double d14 = y + bounds.maxY();
         double d15 = z + bounds.minZ();
         double d16 = z + bounds.maxZ();
+        tessellator.setNormal(-1, 0, 0);
         if (this.enableAO) {
             tessellator.setLightmapCoord1i(this.lightmapCoordTopLeft);
             tessellator.setColorOpaque3f(this.colorRedTopLeft, this.colorGreenTopLeft, this.colorBlueTopLeft);
@@ -843,13 +815,14 @@ public final class RenderBlocks {
             tessellator.addVertexWithUV(d12, d13, d15, d9, d11);
             tessellator.addVertexWithUV(d12, d13, d16, d4, d6);
         }
+        tessellator.setNormal(0, 1, 0);
     }
 
-    public void renderEastFace(@NotNull TessellatorTerrain tessellator, @NotNull AABBdc bounds, @NotNull TilePosc tilePos, @Nullable IconCoordinate tex) {
+    public void renderEastFace(@NotNull TessellatorGeneral tessellator, @NotNull AABBdc bounds, @NotNull TilePosc tilePos, @Nullable IconCoordinate tex) {
         renderEastFace(tessellator, bounds, tilePos.x(), tilePos.y(), tilePos.z(), tex);
     }
 
-    public void renderEastFace(@NotNull TessellatorTerrain tessellator, @NotNull AABBdc bounds, double x, double y, double z, @Nullable IconCoordinate tex) {
+    public void renderEastFace(@NotNull TessellatorGeneral tessellator, @NotNull AABBdc bounds, double x, double y, double z, @Nullable IconCoordinate tex) {
         if (this.overrideBlockTexture != null) tex = this.overrideBlockTexture;
         if (tex == null) return;
         double uMin = tex.getSubIconU(bounds.minZ());
@@ -911,6 +884,7 @@ public final class RenderBlocks {
         double zMin = z + bounds.minZ();
         double zMax = z + bounds.maxZ();
 
+        tessellator.setNormal(1, 0, 0);
         if (this.enableAO) {
             tessellator.setLightmapCoord1i(this.lightmapCoordTopLeft);
             tessellator.setColorOpaque3f(this.colorRedTopLeft, this.colorGreenTopLeft, this.colorBlueTopLeft);
@@ -930,5 +904,6 @@ public final class RenderBlocks {
             tessellator.addVertexWithUV(xMax, yMax, zMin, uMax2, vMin2);
             tessellator.addVertexWithUV(xMax, yMax, zMax, uMin, vMin);
         }
+        tessellator.setNormal(0, 1, 0);
     }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureCompass.java b/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureCompass.java
index 0b67e399b..8342a41c7 100644
--- a/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureCompass.java
+++ b/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureCompass.java
@@ -12,7 +12,7 @@ import net.minecraft.core.world.pos.TilePos;
 
 public class DynamicTextureCompass extends DynamicTexture {
 	
-	private Minecraft mc;
+	private final Minecraft mc;
 	
 	private byte[] compassImageData;
 	
@@ -30,16 +30,16 @@ public class DynamicTextureCompass extends DynamicTexture {
 	public void postInit() {
 		initTexture();
 		
-		BufferedImage atlas = targetTexture.parentAtlas.atlas;
-		compassImageData = new byte[targetTexture.getArea() * 4];
+		BufferedImage atlas = this.targetTexture.parentAtlas.colorImage;
+        this.compassImageData = new byte[this.targetTexture.getArea() * 4];
 
-		for(int x = 0; x < targetTexture.width; x++) {
-			for(int y = 0; y < targetTexture.height; y++) {
-				putPixel(compassImageData, y * targetTexture.width + x, atlas.getRGB(targetTexture.iconX + x, targetTexture.iconY + y));
+		for(int x = 0; x < this.targetTexture.width; x++) {
+			for(int y = 0; y < this.targetTexture.height; y++) {
+				putPixel(this.compassImageData, y * this.targetTexture.width + x, atlas.getRGB(this.targetTexture.iconX + x, this.targetTexture.iconY + y));
 			}
 		}
-		
-		scaleFactor = targetTexture.width / 16.0;
+
+        this.scaleFactor = this.targetTexture.width / 16.0;
 	}
 	@Override
 	public boolean runUpdates(boolean isPaused) {
@@ -49,16 +49,16 @@ public class DynamicTextureCompass extends DynamicTexture {
 	@Override
 	public void update() {
 
-		for (int _x = 0; _x < targetTexture.width; _x++) {
-			for(int _y = 0; _y < targetTexture.height; _y++) {
-				int i = _y * targetTexture.width + _x;
+		for (int _x = 0; _x < this.targetTexture.width; _x++) {
+			for(int _y = 0; _y < this.targetTexture.height; _y++) {
+				int i = _y * this.targetTexture.width + _x;
 
 				int a = this.compassImageData[i * 4 + 3] & 0xFF;
-				int r = this.compassImageData[i * 4 + 0] & 0xFF;
+				int r = this.compassImageData[i * 4] & 0xFF;
 				int g = this.compassImageData[i * 4 + 1] & 0xFF;
 				int b = this.compassImageData[i * 4 + 2] & 0xFF;
 
-				this.imageData[i * 4 + 0] = (byte)r;
+				this.imageData[i * 4] = (byte)r;
 				this.imageData[i * 4 + 1] = (byte)g;
 				this.imageData[i * 4 + 2] = (byte)b;
 				this.imageData[i * 4 + 3] = (byte)a;
@@ -109,34 +109,34 @@ public class DynamicTextureCompass extends DynamicTexture {
 		int b;
 		int a;
 
-        double xs = (targetTexture.width / 2.0) + 0.5;
-		double ys = (targetTexture.height / 2.0) - 0.5;
+        double xs = (this.targetTexture.width / 2.0) + 0.5;
+		double ys = (this.targetTexture.height / 2.0) - 0.5;
 		
-		for(int i = (int)(-4 * scaleFactor); i <= (int)(4 * scaleFactor); ++i) {
+		for(int i = (int)(-4 * this.scaleFactor); i <= (int)(4 * this.scaleFactor); ++i) {
 			x2 = (int)(xs + y * (double)i * 0.3D);
 			y2 = (int)(ys - x * (double)i * 0.3D * 0.5D);
-			j = y2 * targetTexture.width + x2;
+			j = y2 * this.targetTexture.width + x2;
 			r = 100;
 			g = 100;
 			b = 100;
 			a = 255;
 
-			this.imageData[j * 4 + 0] = (byte)r;
+			this.imageData[j * 4] = (byte)r;
 			this.imageData[j * 4 + 1] = (byte)g;
 			this.imageData[j * 4 + 2] = (byte)b;
 			this.imageData[j * 4 + 3] = (byte)a;
 		}
 
-		for(int i = (int)(-8 * scaleFactor); i <= (int)(16 * scaleFactor); ++i) {
+		for(int i = (int)(-8 * this.scaleFactor); i <= (int)(16 * this.scaleFactor); ++i) {
 			x2 = (int)(xs + x * (double)i * 0.3D);
 			y2 = (int)(ys + y * (double)i * 0.3D * 0.5D);
-			j = y2 * targetTexture.width + x2;
+			j = y2 * this.targetTexture.width + x2;
 			r = i >= 0 ? 255 : 100;
 			g = i >= 0 ? 20 : 100;
 			b = i >= 0 ? 20 : 100;
 			a = 255;
 
-			this.imageData[j * 4 + 0] = (byte)r;
+			this.imageData[j * 4] = (byte)r;
 			this.imageData[j * 4 + 1] = (byte)g;
 			this.imageData[j * 4 + 2] = (byte)b;
 			this.imageData[j * 4 + 3] = (byte)a;
diff --git a/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureCustom.java b/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureCustom.java
index 89295e750..1d9739ffa 100644
--- a/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureCustom.java
+++ b/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureCustom.java
@@ -33,20 +33,16 @@ public class DynamicTextureCustom extends DynamicTexture {
 
 		this.properties = animationProperties;
 
-		BufferedImage image = texture.getImageStorage();
 		try {
-			if(image == null) {
-				throw new TexturePackException("Could not load image!");
-			}
-			if(image.getHeight() < image.getWidth()) {
+			if(texture.height < texture.width) {
 				throw new TexturePackException("Height is smaller than width!");
 			}
 		}catch (TexturePackException e) {
 			throw new TexturePackException("Error in animation " + texture.namespaceId, e);
 		}
 
-		int width = image.getWidth();
-		int height = image.getHeight();
+		int width = texture.width;
+		int height = texture.height;
 
 		int tileWidth = width;
 		int tileHeight = (animationProperties.height * width) / animationProperties.width ;
@@ -56,29 +52,31 @@ public class DynamicTextureCustom extends DynamicTexture {
 		this.frameCount = height / tileHeight;
 
 		if (animationProperties.frames != null) {
-			indices = animationProperties.frames.size();
+            this.indices = animationProperties.frames.size();
 			for (AnimationProperties.Frame f : animationProperties.frames) {
-				if (f.index >= frameCount) {
-					throw new TexturePackException("Animation in '" + texture.namespaceId + "' illegally attempts to reference index '" + f.index + "' when theres only '" + frameCount + "' possible frames!");
+				if (f.index >= this.frameCount) {
+					throw new TexturePackException("Animation in '" + texture.namespaceId + "' illegally attempts to reference index '" + f.index + "' when theres only '" + this.frameCount + "' possible frames!");
 				}
 			}
 		} else {
-			indices = frameCount;
+            this.indices = this.frameCount;
 		}
 
 
-		frameData = new byte[tileWidth * tileHeight * 4 * frameCount];
-		for(int frame=0; frame < frameCount; frame++) {
+		BufferedImage image = texture.parentAtlas.getImage("color", texture);
+
+        this.frameData = new byte[tileWidth * tileHeight * 4 * this.frameCount];
+		for(int frame = 0; frame < this.frameCount; frame++) {
 			for(int x=0; x < tileWidth; x++) {
 				for(int y=0; y < tileHeight; y++) {
 					int c = image.getRGB(x, frame * tileHeight + y);
 					int i = frame * tileWidth * tileHeight + y * tileWidth + x;
-					putPixel(frameData, i, c);
+					putPixel(this.frameData, i, c);
 				}
 			}
 		}
 
-		tickWhenPaused = texture.parentAtlas.tickWhenPaused();
+        this.tickWhenPaused = texture.parentAtlas.tickWhenPaused();
 	}
 
 	@Override
@@ -88,70 +86,70 @@ public class DynamicTextureCustom extends DynamicTexture {
 	
 	@Override
 	public void update() {
-		if(properties.interpolate) {
-			if(delayUntilNextFrame > 0) {
-				delayUntilNextFrame--;
+		if(this.properties.interpolate) {
+			if(this.delayUntilNextFrame > 0) {
+                this.delayUntilNextFrame--;
 			}
 			
-			if(delayUntilNextFrame <= 0) {
+			if(this.delayUntilNextFrame <= 0) {
 				progressFrame();
 			}
 
-			float blendFactor = 1.0f - delayUntilNextFrame / (float) frameLength;
+			float blendFactor = 1.0f - this.delayUntilNextFrame / (float) this.frameLength;
 			
-			if(previousFrame == -1) {
-				transferFrame(currentFrame);
+			if(this.previousFrame == -1) {
+				transferFrame(this.currentFrame);
 			}else {
-				transferBlendedFrame(previousFrame, currentFrame, blendFactor);
+				transferBlendedFrame(this.previousFrame, this.currentFrame, blendFactor);
 			}
 			
 			return;
 		}
 		
-		if(delayUntilNextFrame > 0) {
-			delayUntilNextFrame--;
-			if(delayUntilNextFrame > 0) {
+		if(this.delayUntilNextFrame > 0) {
+            this.delayUntilNextFrame--;
+			if(this.delayUntilNextFrame > 0) {
 				return;
 			}
 		}
 		
 		progressFrame();
 
-		if(currentFrame != previousFrame) {
-			transferFrame(currentFrame);
+		if(this.currentFrame != this.previousFrame) {
+			transferFrame(this.currentFrame);
 		}
 	}
 	private void progressFrame() {
-		frameLength = delayUntilNextFrame = getNextFrameDelay();
-		if (properties.random) {
-			currentIndex = rand.nextInt(indices);
+        this.frameLength = this.delayUntilNextFrame = getNextFrameDelay();
+		if (this.properties.random) {
+            this.currentIndex = rand.nextInt(this.indices);
 		} else {
-			currentIndex = (currentIndex + 1) % indices;
+            this.currentIndex = (this.currentIndex + 1) % this.indices;
 		}
-		previousFrame = currentFrame;
-		currentFrame = getNextFrame();
+        this.previousFrame = this.currentFrame;
+        this.currentFrame = getNextFrame();
 	}
 	
 	private int getNextFrame() {
-		return properties.frames == null ? currentIndex : properties.frames.get(currentIndex).index;
+		return this.properties.frames == null ? this.currentIndex : this.properties.frames.get(this.currentIndex).index;
 	}
 
 	private int getNextFrameDelay() {
-		if (properties.frames == null) return properties.frametime;
-		return properties.frames.get(currentIndex).time;
+		if (this.properties.frames == null) return this.properties.frametime;
+		return this.properties.frames.get(this.currentIndex).time;
 	}
 	
 	private void transferFrame(int frame) {
 		try {
-			for(int x0 = 0; x0 < targetTexture.width; x0++) {
-				for(int y0 = 0; y0 < targetTexture.height; y0++) {
-					int i = (frame * targetTexture.getArea() + y0 * targetTexture.width + x0) << 2;
-					int j = (y0 * targetTexture.width + x0) << 2;
-
-					imageData[j + 0] = frameData[i + 0];
-					imageData[j + 1] = frameData[i + 1];
-					imageData[j + 2] = frameData[i + 2];
-					imageData[j + 3] = frameData[i + 3];
+			for(int x0 = 0; x0 < this.targetTexture.width; x0++) {
+				for(int y0 = 0; y0 < this.targetTexture.height; y0++) {
+					int i = (frame * this.targetTexture.getArea() + y0 * this.targetTexture.width + x0) << 2;
+					int j = (y0 * this.targetTexture.width + x0) << 2;
+
+                    this.imageData[j] = this.frameData[i];
+                    this.imageData[j + 1] = this.frameData[i + 1];
+                    this.imageData[j + 2] = this.frameData[i + 2];
+                    this.imageData[j + 3] = this.frameData[i + 3];
 				}
 			}
 		} catch (Exception e) {
@@ -165,16 +163,16 @@ public class DynamicTextureCustom extends DynamicTexture {
 		}else if(blendFactor >= 1.0f) {
 			transferFrame(frame2);
 		}else {
-			for(int x0 = 0; x0 < targetTexture.width; x0++) {
-				for(int y0 = 0; y0 < targetTexture.height; y0++) {
-					int i = (frame1 * targetTexture.getArea() + y0 * targetTexture.width + x0) << 2;
-					int j = (frame2 * targetTexture.getArea() + y0 * targetTexture.width + x0) << 2;
-					int k = (y0 * targetTexture.width + x0) << 2;
-
-					imageData[k + 0] = blend(frameData[i + 0], frameData[j + 0], blendFactor);
-					imageData[k + 1] = blend(frameData[i + 1], frameData[j + 1], blendFactor);
-					imageData[k + 2] = blend(frameData[i + 2], frameData[j + 2], blendFactor);
-					imageData[k + 3] = blend(frameData[i + 3], frameData[j + 3], blendFactor);
+			for(int x0 = 0; x0 < this.targetTexture.width; x0++) {
+				for(int y0 = 0; y0 < this.targetTexture.height; y0++) {
+					int i = (frame1 * this.targetTexture.getArea() + y0 * this.targetTexture.width + x0) << 2;
+					int j = (frame2 * this.targetTexture.getArea() + y0 * this.targetTexture.width + x0) << 2;
+					int k = (y0 * this.targetTexture.width + x0) << 2;
+
+                    this.imageData[k] = blend(this.frameData[i], this.frameData[j], blendFactor);
+                    this.imageData[k + 1] = blend(this.frameData[i + 1], this.frameData[j + 1], blendFactor);
+                    this.imageData[k + 2] = blend(this.frameData[i + 2], this.frameData[j + 2], blendFactor);
+                    this.imageData[k + 3] = blend(this.frameData[i + 3], this.frameData[j + 3], blendFactor);
 				}
 			}
 		}
@@ -186,6 +184,6 @@ public class DynamicTextureCustom extends DynamicTexture {
 	}
 	@Override
 	public boolean runUpdates(boolean isPaused) {
-		return mc.gameSettings.animations.value != 0 && (!isPaused || tickWhenPaused);
+		return this.mc.gameSettings.animations.value != 0 && (!isPaused || this.tickWhenPaused);
 	}
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureFireflyJar.java b/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureFireflyJar.java
index a975e53cc..2e8a478b2 100644
--- a/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureFireflyJar.java
+++ b/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureFireflyJar.java
@@ -12,16 +12,13 @@ public class DynamicTextureFireflyJar extends DynamicTexture {
 
 	public DynamicTextureFireflyJar(IconCoordinate texture) {
         super(texture);
-		BufferedImage image = texture.getImageStorage();
-		if(image == null) {
-			throw new TexturePackException("Could not load image from texture'" + texture.namespaceId + "'!");
-		}
-        texture.setDimension(image.getWidth(), image.getHeight());
+
         this.originalData = new byte[texture.getArea() * 4];
+        int[] data = texture.parentAtlas.getIconData("color", texture, new int[texture.getArea()]);
 
 		for(int x = 0; x < texture.width; x++) {
 			for(int y = 0; y < texture.height; y++) {
-				putPixel(originalData, y * texture.width + x, image.getRGB(x, y));
+				putPixel(this.originalData, y * texture.width + x, data[y * texture.width + x]);
 			}
 		}
 	}
@@ -33,7 +30,7 @@ public class DynamicTextureFireflyJar extends DynamicTexture {
 
     private float getInternalBrightness()
     {
-        float b = ((float) Math.sin(ticks / 10f) + 1.0f) / 2f;
+        float b = ((float) Math.sin(this.ticks / 10f) + 1.0f) / 2f;
         return MathHelper.clamp(b, 0f, 1f);
     }
 
@@ -44,19 +41,19 @@ public class DynamicTextureFireflyJar extends DynamicTexture {
     @Override
     public void update()
     {
-        ticks++;
+        this.ticks++;
         float br = getInternalBrightness();
 
-        for (int x = 0; x < targetTexture.width; x++){
-            for (int y = 0; y < targetTexture.height; y++)
+        for (int x = 0; x < this.targetTexture.width; x++){
+            for (int y = 0; y < this.targetTexture.height; y++)
             {
-                int i = y * targetTexture.width + x;
+                int i = y * this.targetTexture.width + x;
                 int a = this.originalData[i * 4 + 3] & 0xFF;
-                int r = this.originalData[i * 4 + 0] & 0xFF;
+                int r = this.originalData[i * 4] & 0xFF;
                 int g = this.originalData[i * 4 + 1] & 0xFF;
                 int b = this.originalData[i * 4 + 2] & 0xFF;
 
-                if (x >= targetTexture.width * (6 / 16f) && x < targetTexture.width * (10 / 16f) && y >= targetTexture.height * (6 / 16f) && y < targetTexture.height)
+                if (x >= this.targetTexture.width * (6 / 16f) && x < this.targetTexture.width * (10 / 16f) && y >= this.targetTexture.height * (6 / 16f) && y < this.targetTexture.height)
                 {
 
                     float rf = r / 255f;
@@ -67,9 +64,9 @@ public class DynamicTextureFireflyJar extends DynamicTexture {
                     float maxG = MathHelper.clamp(gf + 0.1f, 0.0f, 1.0f);
                     float maxB = MathHelper.clamp(bf + 0.1f, 0.0f, 1.0f);
 
-                    float tMinR = MathHelper.lerp(minR, rf, 0.85f);
-                    float tMinG = MathHelper.lerp(minG, gf, 0.85f);
-                    float tMinB = MathHelper.lerp(minB, bf, 0.85f);
+                    float tMinR = MathHelper.lerp(this.minR, rf, 0.85f);
+                    float tMinG = MathHelper.lerp(this.minG, gf, 0.85f);
+                    float tMinB = MathHelper.lerp(this.minB, bf, 0.85f);
 
                     if (br < 0.5f)
                     {
@@ -90,7 +87,7 @@ public class DynamicTextureFireflyJar extends DynamicTexture {
 
                 }
 
-                this.imageData[i * 4 + 0] = (byte) r;
+                this.imageData[i * 4] = (byte) r;
                 this.imageData[i * 4 + 1] = (byte) g;
                 this.imageData[i * 4 + 2] = (byte) b;
                 this.imageData[i * 4 + 3] = (byte) a;
diff --git a/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureRotating.java b/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureRotating.java
index fff2e2380..5faef5228 100644
--- a/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureRotating.java
+++ b/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureRotating.java
@@ -10,103 +10,103 @@ import net.minecraft.core.util.helper.MathHelper;
 
 public abstract class DynamicTextureRotating extends DynamicTexture {
 
-	protected final Minecraft mc;
-
-	protected byte[] dialImageData;
-	protected int dialTexRes;
-
-	protected byte[] clockImageData;
-	
-	protected double angleFinal;
-	protected double delta;
-
-	public DynamicTextureRotating(Minecraft minecraft, IconCoordinate texture) {
-		super(texture);
-		this.mc = minecraft;
-	}
-	
-	@Override
-	public void postInit() {
-		initTexture();
-
-		BufferedImage atlas = targetTexture.parentAtlas.atlas;
-		clockImageData = new byte[targetTexture.getArea() * 4];
-		for (int x = 0; x < targetTexture.width; x++) {
-			for (int y = 0; y < targetTexture.height; y++) {
-				putPixel(clockImageData, y * targetTexture.width + x, atlas.getRGB(targetTexture.iconX + x, targetTexture.iconY + y));
-			}
-		}
-	}
-
-	public abstract double getAngle();
-	
-	public void updateAngle() {
-		double angle = getAngle();
-
-		double angleSmooth;
-		for (angleSmooth = angle - this.angleFinal; angleSmooth < -MathHelper.PI; ) {
-			angleSmooth += MathHelper.PI * 2;
-		}
-
-		while (angleSmooth >= MathHelper.PI) {
-			angleSmooth -= MathHelper.PI * 2;
-		}
-		
-		if (angleSmooth < -1.0D) angleSmooth = -1.0D;
-		if (angleSmooth > 1.0D) angleSmooth = 1.0D;
-		
-		this.delta += angleSmooth * 0.1D;
-		this.delta *= 0.8D;
-		this.angleFinal += this.delta;
-	}
-
-	@Override
-	public void update() {
-		updateAngle();
-		
-		double x = Math.sin(this.angleFinal);
-		double y = Math.cos(this.angleFinal);
-
-		for (int _x = 0; _x < targetTexture.width; _x++) {
-			for (int _y = 0; _y < targetTexture.height; _y++) {
-				int i = _y * targetTexture.width + _x;
-				int a = this.clockImageData[i * 4 + 3] & 0xFF;
-				int r = this.clockImageData[i * 4 + 0] & 0xFF;
-				int g = this.clockImageData[i * 4 + 1] & 0xFF;
-				int b = this.clockImageData[i * 4 + 2] & 0xFF;
+    protected final Minecraft mc;
+
+    protected byte[] dialImageData;
+    protected int dialTexRes;
+
+    protected byte[] clockImageData;
+
+    protected double angleFinal;
+    protected double delta;
+
+    public DynamicTextureRotating(Minecraft minecraft, IconCoordinate texture) {
+        super(texture);
+        this.mc = minecraft;
+    }
+
+    @Override
+    public void postInit() {
+        initTexture();
+
+        BufferedImage atlas = this.targetTexture.parentAtlas.colorImage;
+        this.clockImageData = new byte[this.targetTexture.getArea() * 4];
+        for (int x = 0; x < this.targetTexture.width; x++) {
+            for (int y = 0; y < this.targetTexture.height; y++) {
+                putPixel(this.clockImageData, y * this.targetTexture.width + x, atlas.getRGB(this.targetTexture.iconX + x, this.targetTexture.iconY + y));
+            }
+        }
+    }
+
+    public abstract double getAngle();
+
+    public void updateAngle() {
+        double angle = getAngle();
+
+        double angleSmooth;
+        for (angleSmooth = angle - this.angleFinal; angleSmooth < -MathHelper.PI; ) {
+            angleSmooth += MathHelper.PI * 2;
+        }
+
+        while (angleSmooth >= MathHelper.PI) {
+            angleSmooth -= MathHelper.PI * 2;
+        }
+
+        if (angleSmooth < -1.0D) angleSmooth = -1.0D;
+        if (angleSmooth > 1.0D) angleSmooth = 1.0D;
+
+        this.delta += angleSmooth * 0.1D;
+        this.delta *= 0.8D;
+        this.angleFinal += this.delta;
+    }
+
+    @Override
+    public void update() {
+        updateAngle();
+
+        double x = Math.sin(this.angleFinal);
+        double y = Math.cos(this.angleFinal);
+
+        for (int _x = 0; _x < this.targetTexture.width; _x++) {
+            for (int _y = 0; _y < this.targetTexture.height; _y++) {
+                int i = _y * this.targetTexture.width + _x;
+                int a = this.clockImageData[i * 4 + 3] & 0xFF;
+                int r = this.clockImageData[i * 4] & 0xFF;
+                int g = this.clockImageData[i * 4 + 1] & 0xFF;
+                int b = this.clockImageData[i * 4 + 2] & 0xFF;
 
 //			r = b = 255; g = 0;
 //			If the pixel in the clock icon is colored pink (Red and Blue are equal), it will be replaced a pixel from the dial texture
-				if (r == b && g == 0 && b > 0) {
-					double pixelBrightness = r / 256.0;
+                if (r == b && g == 0 && b > 0) {
+                    double pixelBrightness = r / 256.0;
 
-					double x2 = -((double) (_x) / (targetTexture.width-1) - 0.5D);
-					double y2 =   (double) (_y) / (targetTexture.height-1) - 0.5D;
+                    double x2 = -((double) (_x) / (this.targetTexture.width - 1) - 0.5D);
+                    double y2 = (double) (_y) / (this.targetTexture.height - 1) - 0.5D;
 
-					int x3 = (int) ((x2 * y + y2 * x + 0.5D) * dialTexRes);
-					int y3 = (int) ((y2 * y - x2 * x + 0.5D) * dialTexRes);
+                    int x3 = (int) ((x2 * y + y2 * x + 0.5D) * this.dialTexRes);
+                    int y3 = (int) ((y2 * y - x2 * x + 0.5D) * this.dialTexRes);
 
-					//Repeat texture
+                    //Repeat texture
 //				int j = pmod(x3, dialTexRes) + pmod(y3, dialTexRes) * dialTexRes;
-					//Clamp to edge
-					int j = clamp(x3, 0, dialTexRes-1) + clamp(y3, 0, dialTexRes-1) * dialTexRes;
-
-					a = this.dialImageData[j * 4 + 3] & 0xFF;
-					r = this.dialImageData[j * 4 + 0] & 0xFF;
-					g = this.dialImageData[j * 4 + 1] & 0xFF;
-					b = this.dialImageData[j * 4 + 2] & 0xFF;
-
-					r = (int) (r * pixelBrightness);
-					g = (int) (g * pixelBrightness);
-					b = (int) (b * pixelBrightness);
-				}
-
-
-				this.imageData[i * 4 + 0] = (byte) r;
-				this.imageData[i * 4 + 1] = (byte) g;
-				this.imageData[i * 4 + 2] = (byte) b;
-				this.imageData[i * 4 + 3] = (byte) a;
-			}
-		}
-	}
+                    //Clamp to edge
+                    int j = clamp(x3, 0, this.dialTexRes - 1) + clamp(y3, 0, this.dialTexRes - 1) * this.dialTexRes;
+
+                    a = this.dialImageData[j * 4 + 3] & 0xFF;
+                    r = this.dialImageData[j * 4] & 0xFF;
+                    g = this.dialImageData[j * 4 + 1] & 0xFF;
+                    b = this.dialImageData[j * 4 + 2] & 0xFF;
+
+                    r = (int) (r * pixelBrightness);
+                    g = (int) (g * pixelBrightness);
+                    b = (int) (b * pixelBrightness);
+                }
+
+
+                this.imageData[i * 4] = (byte) r;
+                this.imageData[i * 4 + 1] = (byte) g;
+                this.imageData[i * 4 + 2] = (byte) b;
+                this.imageData[i * 4 + 3] = (byte) a;
+            }
+        }
+    }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureTrommel.java b/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureTrommel.java
index 7b8433298..aaf3e6b8a 100644
--- a/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureTrommel.java
+++ b/game/client/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureTrommel.java
@@ -8,10 +8,10 @@ import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 
 public class DynamicTextureTrommel extends DynamicTextureRotating {
 	
-	private boolean counterClockwise;
+	private final boolean counterClockwise;
 	
 	private double rotation = 0.0;
-	private double speed = 0.12;
+	private final double speed = 0.12;
 	
 	public DynamicTextureTrommel(Minecraft minecraft, IconCoordinate textureIndex, boolean counterClockwise) {
 		super(minecraft, textureIndex);
@@ -23,22 +23,22 @@ public class DynamicTextureTrommel extends DynamicTextureRotating {
 	public void postInit() {
 		initTexture();
 		
-		BufferedImage atlasImage = targetTexture.parentAtlas.atlas;
+		BufferedImage atlasImage = this.targetTexture.parentAtlas.colorImage;
 		
 		IconCoordinate foreground = TextureRegistry.getTexture("minecraft:block/trommel/active_front_foreground");
-		dialImageData = new byte[foreground.getArea() * 4];
+        this.dialImageData = new byte[foreground.getArea() * 4];
 		for(int x=0; x < foreground.width; x++) {
 			for(int y=0; y < foreground.height; y++) {
-				putPixel(dialImageData, y * foreground.width + x, atlasImage.getRGB(foreground.iconX + x, foreground.iconY + y));
+				putPixel(this.dialImageData, y * foreground.width + x, atlasImage.getRGB(foreground.iconX + x, foreground.iconY + y));
 			}
 		}
-		dialTexRes = foreground.width;
+        this.dialTexRes = foreground.width;
 		
 		IconCoordinate background = TextureRegistry.getTexture("minecraft:block/trommel/active_front_background");
-		clockImageData = new byte[background.getArea() * 4];
+        this.clockImageData = new byte[background.getArea() * 4];
 		for(int x=0; x < background.width; x++) {
 			for(int y=0; y < background.height; y++) {
-				putPixel(clockImageData, y * background.width + x, atlasImage.getRGB(background.iconX+ x, background.iconY + y));
+				putPixel(this.clockImageData, y * background.width + x, atlasImage.getRGB(background.iconX+ x, background.iconY + y));
 			}
 		}
 	}
@@ -50,20 +50,20 @@ public class DynamicTextureTrommel extends DynamicTextureRotating {
 	
 	@Override
 	public void updateAngle() {
-		if(counterClockwise) {
-			rotation -= speed;
+		if(this.counterClockwise) {
+            this.rotation -= this.speed;
 			
-			if(rotation < 0) {
-				rotation += Math.PI * 2;
+			if(this.rotation < 0) {
+                this.rotation += Math.PI * 2;
 			}
 			
 		}else {
-			rotation += speed;
+            this.rotation += this.speed;
 			
-			if(rotation > Math.PI * 2) {
-				rotation -= Math.PI * 2;
+			if(this.rotation > Math.PI * 2) {
+                this.rotation -= Math.PI * 2;
 			}
 		}
-		angleFinal = rotation;
+        this.angleFinal = this.rotation;
 	}
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/renderer/Shaders.java b/game/client/src/main/java/net/minecraft/client/render/renderer/Shaders.java
index f75ee0b23..e8aaee8eb 100644
--- a/game/client/src/main/java/net/minecraft/client/render/renderer/Shaders.java
+++ b/game/client/src/main/java/net/minecraft/client/render/renderer/Shaders.java
@@ -23,6 +23,7 @@ public final class Shaders {
     public static final @NotNull ShaderProvider PROVIDER_INTERNAL = new ShaderProviderInternal("/shaders/");
 
     public static final @NotNull Shader WORLD = register("world", new Shader());
+    public static final @NotNull Shader TERRAIN = register("terrain", new Shader());
     public static final @NotNull Shader INTERFACE = register("interface", new Shader());
     public static final @NotNull Shader COLOR = register("color", new Shader());
     public static final @NotNull Shader COLOR_WORLD = register("color_world", new Shader());
@@ -45,8 +46,10 @@ public final class Shaders {
                     entry.getValue().uniformBlockBinding(block.name, block.index);
                 }
                 entry.getValue().bind();
-                GL41.glUniform1i(entry.getValue().getUniform("texture0"), 0);
-                GL41.glUniform1i(entry.getValue().getUniform("texture1"), 1);
+                entry.getValue().uniformInt("colortex", 0);
+                entry.getValue().uniformInt("lighttex", 1);
+                entry.getValue().uniformInt("emmisivetex", 2);
+//                entry.getValue().uniformInt("colormasktex", 3);
                 GL41.glUseProgram(0);
             } catch (Exception e) {
                 LOGGER.error("", e);
@@ -63,8 +66,12 @@ public final class Shaders {
                     entry.getValue().uniformBlockBinding(block.name, block.index);
                 }
                 entry.getValue().bind();
-                GL41.glUniform1i(entry.getValue().getUniform("texture0"), 0);
-                GL41.glUniform1i(entry.getValue().getUniform("texture1"), 1);
+                GL41.glUniform1i(entry.getValue().getUniform("colortex"), 0);
+                GL41.glUniform1i(entry.getValue().getUniform("lighttex"), 1);
+                entry.getValue().uniformInt("colortex", 0);
+                entry.getValue().uniformInt("lighttex", 1);
+                entry.getValue().uniformInt("emmisivetex", 2);
+//                entry.getValue().uniformInt("colormasktex", 3);
                 GL41.glUseProgram(0);
             } catch (Exception e) {
                 LOGGER.error("", e);
diff --git a/game/client/src/main/java/net/minecraft/client/render/terrain/ChunkRenderer.java b/game/client/src/main/java/net/minecraft/client/render/terrain/ChunkRenderer.java
index 492e99b17..3a1a5a151 100644
--- a/game/client/src/main/java/net/minecraft/client/render/terrain/ChunkRenderer.java
+++ b/game/client/src/main/java/net/minecraft/client/render/terrain/ChunkRenderer.java
@@ -4,7 +4,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 import net.minecraft.client.render.LightmapHelper;
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
+import net.minecraft.client.render.tessellator.TessellatorGeneral;
 import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.world.WorldSource;
 import net.minecraft.core.world.pos.TilePos;
@@ -86,16 +86,11 @@ public abstract class ChunkRenderer {
 
     public abstract boolean rebuild(boolean priority);
 
-    public boolean renderBlock(@NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, @NotNull BlockModel<?> model, @NotNull TilePos tilePos) {
-        boolean rendered = false;
+    public boolean renderBlock(@NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, @NotNull BlockModel<?> model, @NotNull TilePos tilePos) {
         tessellator.setLightmapCoord1i(LightmapHelper.getLightmapCoord(15, 15));
         tessellator.setColor4i(255, 255, 255, 255);
         tessellator.setTextureUV(0.0, 0.0);
-        rendered |= model.render(tessellator, worldSource, tilePos);
-        if (model.hasOverbright()) {
-            rendered |= model.renderOverbright(tessellator, worldSource, tilePos);
-        }
-        return rendered;
+        return model.render(tessellator, worldSource, tilePos);
     }
 
     public float distanceToEntitySquared(Entity entity) {
diff --git a/game/client/src/main/java/net/minecraft/client/render/terrain/RenderList.java b/game/client/src/main/java/net/minecraft/client/render/terrain/RenderList.java
index a76e31e04..622154ca5 100644
--- a/game/client/src/main/java/net/minecraft/client/render/terrain/RenderList.java
+++ b/game/client/src/main/java/net/minecraft/client/render/terrain/RenderList.java
@@ -11,7 +11,7 @@ import java.util.Set;
 import com.mojang.logging.CategorizedLogger;
 import com.mojang.logging.LogUtils;
 import net.minecraft.client.render.terrain.VertexBuffer.Entry;
-import net.minecraft.core.util.helper.Buffer;
+import org.lwjgl.BufferUtils;
 
 /**
  * 		Can render a lot of objects with a single call
@@ -36,8 +36,8 @@ public class RenderList {
 
     public RenderList(VertexBuffer vertexBuffer, int capacity) {
         this.vertexBuffer = vertexBuffer;
-        this.posBuffer = Buffer.createBuffer(capacity * 4).asIntBuffer();
-        this.sizeBuffer = Buffer.createBuffer(capacity * 4).asIntBuffer();
+        this.posBuffer = BufferUtils.createByteBuffer(capacity * 4).asIntBuffer();
+        this.sizeBuffer = BufferUtils.createByteBuffer(capacity * 4).asIntBuffer();
     }
 
     public void draw() {
@@ -155,7 +155,7 @@ public class RenderList {
 
             LOGGER.warn("Expanding RenderList IntBuffer from {} to {} ints...", buffer.capacity(), newCapacity);
 
-            return Buffer.createBuffer(newCapacity << 2).asIntBuffer();
+            return BufferUtils.createIntBuffer(newCapacity);
         }
         return buffer;
     }
diff --git a/game/client/src/main/java/net/minecraft/client/render/terrain/TerrainRendererMultiDraw.java b/game/client/src/main/java/net/minecraft/client/render/terrain/TerrainRendererMultiDraw.java
index e1df10235..caf724961 100644
--- a/game/client/src/main/java/net/minecraft/client/render/terrain/TerrainRendererMultiDraw.java
+++ b/game/client/src/main/java/net/minecraft/client/render/terrain/TerrainRendererMultiDraw.java
@@ -96,7 +96,7 @@ public class TerrainRendererMultiDraw extends TerrainRenderer {
             if (renderList != null && renderList.size() > 0) {
                 GLRenderer.pushFrame();
                 GLRenderer.modelM4f().translate((float) ((region.posX << this.REGION_SIZE) - this.renderPosX), (float) -this.renderPosY, (float) ((region.posZ << this.REGION_SIZE) - this.renderPosZ));
-                GLRenderer.globalSetUniforms(Shaders.WORLD);
+                GLRenderer.globalSetUniforms(Shaders.TERRAIN);
 
                 renderList.draw();
                 this.drawCalls[0]++;
@@ -116,7 +116,7 @@ public class TerrainRendererMultiDraw extends TerrainRenderer {
             if (renderList != null && renderList.size() > 0) {
                 GLRenderer.pushFrame();
                 GLRenderer.modelM4f().translate((float) ((region.posX << this.REGION_SIZE) - this.renderPosX), (float) -this.renderPosY, (float) ((region.posZ << this.REGION_SIZE) - this.renderPosZ));
-                GLRenderer.globalSetUniforms(Shaders.WORLD);
+                GLRenderer.globalSetUniforms(Shaders.TERRAIN);
 
                 renderList.draw();
                 this.drawCalls[renderPass]++;
diff --git a/game/client/src/main/java/net/minecraft/client/render/terrain/VertexData.java b/game/client/src/main/java/net/minecraft/client/render/terrain/VertexData.java
index 523b0f409..aa1c5408c 100644
--- a/game/client/src/main/java/net/minecraft/client/render/terrain/VertexData.java
+++ b/game/client/src/main/java/net/minecraft/client/render/terrain/VertexData.java
@@ -2,7 +2,8 @@ package net.minecraft.client.render.terrain;
 
 import java.nio.ByteBuffer;
 
-import net.minecraft.core.util.helper.Buffer;
+import net.minecraft.client.util.helper.Buffer;
+import org.lwjgl.BufferUtils;
 
 public class VertexData {
 
@@ -13,6 +14,6 @@ public class VertexData {
     public int vertexCount;
 
     public VertexData(int size) {
-        this.buffer = Buffer.createBuffer(size);
+        this.buffer = BufferUtils.createByteBuffer(size);
     }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/tessellator/Tessellator.java b/game/client/src/main/java/net/minecraft/client/render/tessellator/Tessellator.java
index da2d5ca78..fb1d12f89 100644
--- a/game/client/src/main/java/net/minecraft/client/render/tessellator/Tessellator.java
+++ b/game/client/src/main/java/net/minecraft/client/render/tessellator/Tessellator.java
@@ -1,8 +1,6 @@
 package net.minecraft.client.render.tessellator;
 
-import net.minecraft.client.Minecraft;
 import net.minecraft.client.render.renderer.DrawMode;
-import net.minecraft.core.enums.EnumOS;
 import org.jetbrains.annotations.NotNull;
 
 public interface Tessellator {
diff --git a/game/client/src/main/java/net/minecraft/client/render/tessellator/TessellatorGeneral.java b/game/client/src/main/java/net/minecraft/client/render/tessellator/TessellatorGeneral.java
index 1f51a346f..2820b27fc 100644
--- a/game/client/src/main/java/net/minecraft/client/render/tessellator/TessellatorGeneral.java
+++ b/game/client/src/main/java/net/minecraft/client/render/tessellator/TessellatorGeneral.java
@@ -1,6 +1,6 @@
 package net.minecraft.client.render.tessellator;
 
-public interface TessellatorGeneral extends TessellatorColor, TessellatorTextured, TessellatorLightmap, TessellatorNormal, TessellatorTerrain, Tessellator {
+public interface TessellatorGeneral extends TessellatorColor, TessellatorTextured, TessellatorLightmap, TessellatorNormal, Tessellator {
 
 
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/tessellator/TessellatorParticleShader.java b/game/client/src/main/java/net/minecraft/client/render/tessellator/TessellatorParticleShader.java
index 86b3f3c11..e75ac25cb 100644
--- a/game/client/src/main/java/net/minecraft/client/render/tessellator/TessellatorParticleShader.java
+++ b/game/client/src/main/java/net/minecraft/client/render/tessellator/TessellatorParticleShader.java
@@ -5,9 +5,9 @@ import net.minecraft.client.render.LightmapHelper;
 import net.minecraft.client.render.camera.ICamera;
 import net.minecraft.client.render.renderer.DrawMode;
 import net.minecraft.client.render.renderer.GLRenderer;
-import net.minecraft.core.util.helper.Buffer;
 import net.minecraft.core.util.helper.MathHelper;
 import org.jetbrains.annotations.NotNull;
+import org.lwjgl.BufferUtils;
 import org.lwjgl.opengl.GL41;
 import org.slf4j.Logger;
 
@@ -31,7 +31,7 @@ public class TessellatorParticleShader implements TessellatorParticle {
     private double offsetZ;
 
     public TessellatorParticleShader(int size) {
-        this.buffer = Buffer.createBuffer(size);
+        this.buffer = BufferUtils.createByteBuffer(size);
         this.vao = GL41.glGenVertexArrays();
         this.vbo = GL41.glGenBuffers();
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/tessellator/TessellatorTerrain.java b/game/client/src/main/java/net/minecraft/client/render/tessellator/TessellatorTerrain.java
deleted file mode 100644
index 0e5bc837b..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/tessellator/TessellatorTerrain.java
+++ /dev/null
@@ -1,4 +0,0 @@
-package net.minecraft.client.render.tessellator;
-
-public interface TessellatorTerrain extends TessellatorColor, TessellatorTextured, TessellatorLightmap {
-}
diff --git a/game/client/src/main/java/net/minecraft/client/render/tessellator/TessellatorTerrainImpl.java b/game/client/src/main/java/net/minecraft/client/render/tessellator/TessellatorTerrainImpl.java
index 70f190ca4..eb328e0e7 100644
--- a/game/client/src/main/java/net/minecraft/client/render/tessellator/TessellatorTerrainImpl.java
+++ b/game/client/src/main/java/net/minecraft/client/render/tessellator/TessellatorTerrainImpl.java
@@ -12,7 +12,7 @@ import org.lwjgl.BufferUtils;
 import org.lwjgl.opengl.GL41;
 import org.slf4j.Logger;
 
-public class TessellatorTerrainImpl implements TessellatorTerrain {
+public class TessellatorTerrainImpl implements TessellatorGeneral {
 	private static final Logger LOGGER = LogUtils.getLogger();
 	public TerrainVertexData data;
 	public boolean drawing;
@@ -27,6 +27,10 @@ public class TessellatorTerrainImpl implements TessellatorTerrain {
 	private double offsetY;
 	private double offsetZ;
 
+	private byte normalX;
+	private byte normalY;
+	private byte normalZ;
+
 	private boolean lockedColor = false;
 	private int quadVertCount = 0;
 	
@@ -48,6 +52,7 @@ public class TessellatorTerrainImpl implements TessellatorTerrain {
 		setLightmapCoord1i(LightmapHelper.getLightmapCoord(15, 15));
 		setColor4i(255, 255, 255, 255);
 		setTextureUV(0.0, 0.0);
+		setNormal(0, 1, 0);
 
 		this.lockedColor = false;
         this.data.buffer.clear();
@@ -79,9 +84,14 @@ public class TessellatorTerrainImpl implements TessellatorTerrain {
         buffer.putFloat((float) this.textureU);
         buffer.putFloat((float) this.textureV);
 
-        buffer
-            .put((byte) ((LightmapHelper.getBlockLightFromCoord(this.lightmapCoord) << 4) + 7))
-            .put((byte) ((LightmapHelper.getSkyLightFromCoord(this.lightmapCoord) << 4) + 7));
+		buffer
+			.put((byte) ((LightmapHelper.getBlockLightFromCoord(this.lightmapCoord) << 4) + 7))
+			.put((byte) ((LightmapHelper.getSkyLightFromCoord(this.lightmapCoord) << 4) + 7));
+
+		buffer.put(this.normalX);
+		buffer.put(this.normalY);
+		buffer.put(this.normalZ);
+
 
 
         this.data.vertexCount++;
@@ -103,7 +113,7 @@ public class TessellatorTerrainImpl implements TessellatorTerrain {
 		if(this.data.buffer.capacity() < this.data.buffer.position() + size) {
 			int newSize = this.data.buffer.capacity() * 2;
 
-			LOGGER.info("Expanding {} Buffer ({} -> {})", "Entity Tessellator", this.data.buffer.capacity(), newSize);
+			LOGGER.info("Expanding {} Buffer ({} -> {})", "Terrain Tessellator", this.data.buffer.capacity(), newSize);
 
 			ByteBuffer newBuffer = BufferUtils.createByteBuffer(newSize);
 			this.data.buffer.flip();
@@ -169,6 +179,15 @@ public class TessellatorTerrainImpl implements TessellatorTerrain {
 		}
 	}
 
+	@Override
+	public void setNormal(float x, float y, float z) {
+		checkIsDrawing();
+
+		this.normalX = (byte) (x * 127.0f);
+		this.normalY = (byte) (y * 127.0f);
+		this.normalZ = (byte) (z * 127.0f);
+	}
+
 	public static class TerrainVertexData extends VertexData {
 
 		public TerrainVertexData(int size) {
@@ -194,13 +213,13 @@ public class TessellatorTerrainImpl implements TessellatorTerrain {
             GL41.glVertexAttribPointer(1, 4, GL41.GL_UNSIGNED_BYTE, true, vertexSize, offset); offset += 4;    // Color
 			GL41.glVertexAttribPointer(2, 2, GL41.GL_FLOAT, false, vertexSize, offset); offset += 2 * Float.BYTES;    // UV
 			GL41.glVertexAttribPointer(3, 2, GL41.GL_UNSIGNED_BYTE, true, vertexSize, offset); offset += 2;    // Lightmap
+			GL41.glVertexAttribPointer(4, 3, GL41.GL_BYTE, true, vertexSize, offset); offset += 3;    // Normals
 
 			GL41.glEnableVertexAttribArray(0);
 			GL41.glEnableVertexAttribArray(1);
 			GL41.glEnableVertexAttribArray(2);
 			GL41.glEnableVertexAttribArray(3);
-
-			GL41.glVertexAttrib3f(4, 0, -1, 0);
+			GL41.glEnableVertexAttribArray(4);
 		}
 
 		public void disable() {
@@ -218,6 +237,7 @@ public class TessellatorTerrainImpl implements TessellatorTerrain {
             size += 4;
             size += Float.BYTES * 2;
             size += 2;
+            size += 3;
 			return size;
 		}
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/texture/Texture.java b/game/client/src/main/java/net/minecraft/client/render/texture/Texture.java
index 40c29ed80..d97e8f693 100644
--- a/game/client/src/main/java/net/minecraft/client/render/texture/Texture.java
+++ b/game/client/src/main/java/net/minecraft/client/render/texture/Texture.java
@@ -1,6 +1,6 @@
 package net.minecraft.client.render.texture;
 
-import static net.minecraft.core.util.helper.Buffer.buffer;
+import static net.minecraft.client.util.helper.Buffer.buffer;
 import static org.lwjgl.opengl.GL11.*;
 import static org.lwjgl.opengl.GL12.GL_CLAMP_TO_EDGE;
 import static org.lwjgl.opengl.GL12.GL_TEXTURE_MAX_LEVEL;
@@ -10,7 +10,7 @@ import net.minecraft.client.GLAllocation;
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.option.enums.MipmapType;
 import net.minecraft.client.render.texture.meta.TextureProperties;
-import net.minecraft.core.util.helper.Buffer;
+import net.minecraft.client.util.helper.Buffer;
 import org.jetbrains.annotations.Nullable;
 import org.slf4j.Logger;
 
@@ -44,8 +44,8 @@ public class Texture {
 		if(isGenerated()) {
 			return false;
 		}
-		
-		id = GLAllocation.generateTexture();
+
+        this.id = GLAllocation.generateTexture();
 		if(!isGenerated()) {
 			throw new RuntimeException("Texture not created!");
 		}
@@ -57,8 +57,8 @@ public class Texture {
 		if(!isGenerated()) {
 			return false;
 		}
-		GLAllocation.deleteTexture(id);
-		id = 0;
+		GLAllocation.deleteTexture(this.id);
+        this.id = 0;
 		return true;
 	}
 	
@@ -67,7 +67,7 @@ public class Texture {
 			return false;
 		}
 		
-		glBindTexture(GL_TEXTURE_2D, id);
+		glBindTexture(GL_TEXTURE_2D, this.id);
 		return true;
 	}
 
@@ -83,7 +83,7 @@ public class Texture {
 //	}
 
 	public boolean isGenerated() {
-		return id != 0;
+		return this.id != 0;
 	}
 	
 	public int getWidth() {
@@ -95,7 +95,7 @@ public class Texture {
 	}
 	
 	public int id() {
-		return id;
+		return this.id;
 	}
 
 
@@ -115,8 +115,6 @@ public class Texture {
 	public void setupTexture(BufferedImage img, boolean blurTexture, boolean clampTexture, boolean mipmap) {
 		bind();
 
-
-
 		if(blurTexture) {
 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -225,9 +223,9 @@ public class Texture {
 						int y1 = y << 1;
 
 						if(smooth) {
-							int color0 = data[previousWidth * (y1 + 0) + (x1 + 0)];
-							int color1 = data[previousWidth * (y1 + 0) + (x1 + 1)];
-							int color2 = data[previousWidth * (y1 + 1) + (x1 + 0)];
+							int color0 = data[previousWidth * (y1) + (x1)];
+							int color1 = data[previousWidth * (y1) + (x1 + 1)];
+							int color2 = data[previousWidth * (y1 + 1) + (x1)];
 							int color3 = data[previousWidth * (y1 + 1) + (x1 + 1)];
 
 							color = blendColor(blendColor(color0, color1), blendColor(color2, color3));
diff --git a/game/client/src/main/java/net/minecraft/client/render/texture/stitcher/AtlasStitcher.java b/game/client/src/main/java/net/minecraft/client/render/texture/stitcher/AtlasStitcher.java
index 1b7b5f9c7..5e2d5fff6 100644
--- a/game/client/src/main/java/net/minecraft/client/render/texture/stitcher/AtlasStitcher.java
+++ b/game/client/src/main/java/net/minecraft/client/render/texture/stitcher/AtlasStitcher.java
@@ -1,52 +1,58 @@
 package net.minecraft.client.render.texture.stitcher;
 
-import java.awt.AlphaComposite;
-import java.awt.Graphics2D;
+import java.awt.*;
 import java.awt.image.BufferedImage;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
 
 import com.mojang.logging.LogUtils;
+import it.unimi.dsi.fastutil.objects.Object2IntArrayMap;
+import it.unimi.dsi.fastutil.objects.Object2IntMap;
+import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
 import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
+import it.unimi.dsi.fastutil.objects.ObjectArrayList;
 import net.minecraft.client.Minecraft;
+import net.minecraft.client.render.customatlas.CustomAtlasHandler;
 import net.minecraft.client.render.texture.Texture;
 import net.minecraft.client.render.texturepack.TexturePack;
-import net.minecraft.client.render.texturepack.TexturePackList;
+import net.minecraft.client.util.helper.Textures;
 import net.minecraft.core.util.collection.NamespaceID;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
-import net.minecraft.client.render.customatlas.CustomAtlasHandler;
-import net.minecraft.client.util.helper.Textures;
+import org.jetbrains.annotations.Nullable;
+import org.joml.Math;
+import org.lwjgl.opengl.GL41;
 import org.slf4j.Logger;
 
-public class AtlasStitcher extends Texture {
+public class AtlasStitcher {
     private static final Logger LOGGER = LogUtils.getLogger();
     public static final String rootAssetPath = "/assets";
-    public @NotNull Map<NamespaceID, IconCoordinate> textureMap = new Object2ObjectOpenHashMap<>();
+    public @NotNull Map<NamespaceID, IconCoordinate> iconMap = new Object2ObjectOpenHashMap<>();
     public @NotNull Map<String, String> idDirMap = new Object2ObjectOpenHashMap<>();
-    public final @Nullable BufferedImage defaultTexture;
-    public BufferedImage atlas;
+
+    public @NotNull Map<String, String> layerPostfixMap = new Object2ObjectOpenHashMap<>();
+    public @NotNull Map<String, BufferedImage> layerImageMap = new Object2ObjectOpenHashMap<>();
+    public @NotNull Map<String, Texture> layerTextureMap = new Object2ObjectOpenHashMap<>();
+    public @NotNull Object2IntMap<String> layerDefaultColorMap = new Object2IntOpenHashMap<>();
+
+    public BufferedImage colorImage;
+    public final @NotNull Texture colorTexture;
     private int atlasWidth;
     private int atlasHeight;
     private double invWidth;
     private double invHeight;
     private final boolean mipmap;
     private final boolean tickPaused;
-    public AtlasStitcher(boolean tickWhenPaused, boolean mipmap, @Nullable BufferedImage defaultTexture){
+
+    public AtlasStitcher(boolean tickWhenPaused, boolean mipmap) {
         this.tickPaused = tickWhenPaused;
         this.mipmap = mipmap;
-        this.defaultTexture = defaultTexture;
+
+        addLayer("color", "", 0xFFFF00FF);
+        this.colorTexture = this.layerTextureMap.get("color");
     }
 
     public @NotNull AtlasStitcher addDirectory(@NotNull String id, @NotNull String path) {
@@ -54,21 +60,28 @@ public class AtlasStitcher extends Texture {
         return this;
     }
 
-    protected @NotNull IconCoordinate getTexture(@NotNull NamespaceID id){
-        IconCoordinate cached = this.textureMap.get(id); // Changed to read cached value this way as somehow this method previously managed to return null https://bugs.betterthanadventure.net/scp/tickets.php?id=246
+    public @NotNull AtlasStitcher addLayer(@NotNull String id, @NotNull String filePostfix, int defaultColor) {
+        this.layerPostfixMap.put(id, filePostfix);
+        this.layerTextureMap.put(id, new Texture());
+        this.layerDefaultColorMap.put(id, defaultColor);
+        return this;
+    }
+
+    protected @NotNull IconCoordinate getTexture(@NotNull NamespaceID id) {
+        IconCoordinate cached = this.iconMap.get(id); // Changed to read cached value this way as somehow this method previously managed to return null https://bugs.betterthanadventure.net/scp/tickets.php?id=246
         if (cached != null) return cached;
 
-        IconCoordinate iconCoordinate = new IconCoordinate(this, id, getSourceImagePath(id));
-        this.textureMap.put(id, iconCoordinate);
+        IconCoordinate iconCoordinate = new IconCoordinate(this, id);
+        this.iconMap.put(id, iconCoordinate);
         return iconCoordinate;
     }
 
-    public @NotNull String getSourceImagePath(@NotNull NamespaceID id){
+    public @NotNull String getSourceImageId(@NotNull NamespaceID id) {
         String value = id.value();
         int slashIndex = value.indexOf("/");
         if (slashIndex != -1) {
             String dir = this.idDirMap.get(value.substring(0, slashIndex));
-            return String.format("%s/%s/%s/%s.png", rootAssetPath, id.namespace(), dir, value.substring(slashIndex + 1));
+            return String.format("%s/%s/%s/%s", rootAssetPath, id.namespace(), dir, value.substring(slashIndex + 1));
         } else {
             throw new IllegalArgumentException("Id " + id + " does not specify an id!");
         }
@@ -81,146 +94,273 @@ public class AtlasStitcher extends Texture {
             String[] paths = TextureRegistry.getFilesAndSubFiles(folder, searchSubDirectories);
 
             for (String p : paths) {
-                getTexture(new NamespaceID(namespace, e.getKey() + "/" + p.replace(".png", "")));
+                if (p.contains(".") && p.lastIndexOf(".") == p.indexOf(".")) {
+                    getTexture(new NamespaceID(namespace, e.getKey() + "/" + p.replace(".png", "")));
+                }
             }
         }
     }
 
+    private final List<Box> boxes = new ObjectArrayList<>();
     public void preinit() {
-        generate();
-        long startTime = System.nanoTime();
-        Minecraft mc = Minecraft.getMinecraft();
-        List<IconCoordinate> coordinateList = new ArrayList<>(this.textureMap.values());
-        List<Future<?>> futures = new ArrayList<>();
-        ExecutorService service = Executors.newFixedThreadPool(32);
-        for (IconCoordinate coordinate : coordinateList){
-            futures.add(service.submit(new SetupTexture(mc.texturePackList, coordinate, this.defaultTexture)));
-        }
-
-        for (Future<?> f : futures) {
-            try {
-                f.get();
-            } catch (InterruptedException | ExecutionException e) {
-                LOGGER.error("", e);
-            }
+        this.boxes.clear();
+
+        for (IconCoordinate coordinate : this.iconMap.values()) {
+            Box box = new Box(Minecraft.getMinecraft(), this, coordinate, null);
+            this.boxes.add(box);
+            coordinate.setDimension(box.image.getWidth(), box.image.getHeight());
         }
-        service.shutdown();
-        LOGGER.debug("Took '{}' seconds to load images.", (System.nanoTime() - startTime) / 1_000_000_000d);
     }
 
-    @Override
-    public void init(){
-        // Load all individual textures and the store the widths
-        int area = 0;
+    public void init() {
         int maxWidth = 0;
-        List<IconCoordinate> coordinateList = new ArrayList<>(this.textureMap.values());
-        for (IconCoordinate coordinate : coordinateList){
-            if (coordinate.needsDimensions()) {
-                BufferedImage image = coordinate.getImageStorage();
-                coordinate.setDimension(image.getWidth(), image.getHeight());
+        int maxHeight = 0;
+        for (Box box : this.boxes) {
+            maxWidth = Math.max(maxWidth, box.coord.width + box.border * 2);
+            maxHeight = Math.max(maxHeight, box.coord.height + box.border * 2);
+        }
+
+        this.boxes.sort((o1, o2) -> {
+            int diff = o2.coord.height - o1.coord.height;
+            if (diff != 0) return diff;
+            return o1.coord.namespaceId.compareTo(o2.coord.namespaceId);
+        });
+
+        int atlasWidth = Math.max(Integer.highestOneBit(maxWidth) << 1, 256);
+        int atlasHeight = Math.max(Integer.highestOneBit(maxHeight) << 1, 256);
+
+        ObjectArrayList<Space> spaces = new ObjectArrayList<>(); spaces.add(new Space(0, 0, atlasWidth, atlasHeight));
+        List<Box> packed = new ObjectArrayList<>();
+
+        for (Box box : this.boxes) {
+            expand: while(true) {
+                for (int i = spaces.size() - 1; i >= 0; i--) {
+                    var space = spaces.get(i);
+
+                    if (box.coord.width + box.border * 2 > space.w || box.coord.height + box.border * 2 > space.h) continue;
+
+                    packed.add(box);
+                    box.x = space.x;
+                    box.y = space.y;
+
+                    if (box.coord.width + box.border * 2 == space.w && box.coord.height + box.border * 2 == space.h) {
+                        var last = spaces.remove(spaces.size() - 1);
+                        if (i < spaces.size()) spaces.set(i, last);
+                    } else if (box.coord.height == space.h) {
+                        space.x += box.coord.width + box.border * 2;
+                        space.w -= box.coord.width + box.border * 2;
+                    } else if (box.coord.width + box.border * 2 == space.w) {
+                        space.y += box.coord.height + box.border * 2;
+                        space.h -= box.coord.height + box.border * 2;
+                    } else{
+                        spaces.add(new Space(space.x + box.coord.width + box.border * 2, space.y, space.w - (box.coord.width + box.border * 2), box.coord.height + box.border * 2));
+                        space.y += box.coord.height + box.border * 2;
+                        space.h -= box.coord.height + box.border * 2;
+                    }
+                    break expand;
+                }
+                if (atlasWidth <= atlasHeight) {
+                    spaces.add(0, new Space(atlasWidth, 0, atlasWidth, atlasHeight));
+                    atlasWidth *= 2;
+                } else{
+                    spaces.add(0, new Space(0, atlasHeight, atlasWidth, atlasHeight));
+                    atlasHeight *= 2;
+                }
             }
-            area += coordinate.getArea();
-            if (coordinate.width > maxWidth) maxWidth = coordinate.width;
-        }
-        // Calculate an okay atlas width to keep the aspect ratio of the final atlas mostly 1:1
-        int targetWidth = Integer.highestOneBit((int) Math.max(Math.ceil(Math.sqrt(area)), maxWidth)) << 1;
-        Collections.sort(coordinateList);
-
-        // Find positions for each texture on the atlas
-        int nextX = 0;
-        int currentY = 0;
-        int nextY = coordinateList.get(0).height;
-        int maxRealWidth = 0;
-        for (IconCoordinate coordinate : coordinateList){
-            if (nextX + coordinate.width > targetWidth){
-                nextX = 0;
-                currentY = nextY;
-                nextY += coordinate.height;
+        }
+
+        for (Box box : packed) {
+            box.coord.setPosition(box.x, box.y);
+        }
+
+        for (Map.Entry<String, String> e : this.layerPostfixMap.entrySet()) {
+            BufferedImage atlas = new BufferedImage(atlasWidth, atlasHeight, BufferedImage.TYPE_INT_ARGB);
+            Graphics2D g = atlas.createGraphics();
+            this.layerImageMap.put(e.getKey(), atlas);
+
+            for (Box box : packed) {
+                BufferedImage image = getImage(e.getKey(), box.coord);
+
+                BufferedImage _subImage = new BufferedImage(box.coord.width, box.coord.height, BufferedImage.TYPE_INT_ARGB);
+                _subImage.setRGB(0, 0, _subImage.getWidth(), _subImage.getHeight(),
+                    image.getRGB(0, 0, _subImage.getWidth(), _subImage.getHeight(), new int[_subImage.getWidth() * _subImage.getHeight()], 0, _subImage.getWidth()),
+                    0, _subImage.getWidth());
+                g.drawImage(_subImage, box.x, box.y, null);
+            }
+            g.dispose();
+
+            Texture t = this.layerTextureMap.get(e.getKey());
+            if (!t.isGenerated()) {
+                t.generate();
             }
-            coordinate.setPosition(nextX, currentY);
-            nextX += coordinate.width;
-            if (nextX > maxRealWidth) maxRealWidth = nextX;
+            t.setupTexture(atlas, false, false, this.mipmap);
         }
 
-        // Generate and then copy the data to a new image with the dimensions needed
-        BufferedImage generatedAtlas = new BufferedImage(targetWidth, Integer.highestOneBit(nextY) << 1, BufferedImage.TYPE_INT_ARGB);
+        this.colorImage = this.layerImageMap.get("color");
 
-        this.atlasWidth = generatedAtlas.getWidth();
-        this.atlasHeight = generatedAtlas.getHeight();
-        this.invWidth = 1d/ this.atlasWidth;
-        this.invHeight = 1d/ this.atlasHeight;
+        this.atlasWidth = atlasWidth;
+        this.atlasHeight = atlasHeight;
+        this.invWidth = 1d / this.atlasWidth;
+        this.invHeight = 1d / this.atlasHeight;
 
-        Graphics2D atlas = generatedAtlas.createGraphics();
-        atlas.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f));
-        for (IconCoordinate coordinate : coordinateList){
-            coordinate.drawToAtlas(atlas);
-            coordinate.discardImage();
+        for (Box box : packed) {
+            box.coord.cacheUVs();
         }
-        atlas.dispose();
+    }
+
+    public BufferedImage getImage(@NotNull String layer, @NotNull IconCoordinate coordinate) {
+        String source = getSourceImageId(coordinate.namespaceId);
+        String postfix = this.layerPostfixMap.getOrDefault(layer, "");
+        String path;
+        if (postfix.isEmpty()) {
+            path = source + ".png";
+        } else {
+            path = source + "." + postfix + ".png";
+        }
+        BufferedImage image = CustomAtlasHandler.getTextureOverride(Minecraft.getMinecraft().texturePackList, source + "png");
+        if(image == null) {
+            TexturePack pack = Minecraft.getMinecraft().texturePackList.getHighestPriorityTexturePackWithFile(source + ".png");
+            if (pack != null) {
+                for (int attempt = 0; attempt < 3; attempt++) {
+                    try {
+                        image = Textures.readImageUnhandled(pack.getResourceAsStream(path));
+                        if (image != null) break;
+                    } catch (Exception e) {
+                        LOGGER.error("", e);
+                    }
+                }
+            }
+        }
+        if (image == null || image == Textures.missingTexture){
+            image = new BufferedImage(coordinate.width, coordinate.height, BufferedImage.TYPE_INT_ARGB);
+            int defaultColor = layerDefaultColorMap.getOrDefault(layer, 0xFFFF00FF);
+            for (int x = 0; x < image.getWidth(); x++) {
+                for (int y = 0; y < image.getHeight(); y++) {
+                    image.setRGB(x, y, defaultColor);
+                }
+            }
+            return image;
+        }
+        return image;
+    }
 
-        setupTexture(generatedAtlas, false, false, this.mipmap);
+    public int[] getIconData(@NotNull String layer, @NotNull IconCoordinate coordinate, int[] dest) {
+        BufferedImage img = this.layerImageMap.get(layer);
+        if (img != null) {
+            assert dest.length >= coordinate.getArea();
+            img.getRGB(coordinate.iconX, coordinate.iconY, coordinate.width, coordinate.height, dest, 0, coordinate.width);
+        }
+        return dest;
+    }
 
-        this.atlas = generatedAtlas;
+    public void bind() {
+        this.colorTexture.bind();
+    }
+
+    public void bind(@NotNull String layer) {
+        Texture t = this.layerTextureMap.get(layer);
+        if (t != null) {
+            t.bind();
+        } else {
+            GL41.glBindTexture(GL41.GL_TEXTURE_2D, 0);
+        }
     }
 
-    public int getAtlasWidth(){
+    public int getAtlasWidth() {
         return this.atlasWidth;
     }
-    public int getAtlasHeight(){
+
+    public int getAtlasHeight() {
         return this.atlasHeight;
     }
-    public double getInverseWidth(){
+
+    public double getInverseWidth() {
         return this.invWidth;
     }
-    public double getInverseHeight(){
+
+    public double getInverseHeight() {
         return this.invHeight;
     }
-    public boolean tickWhenPaused() {return this.tickPaused;}
-    public boolean hasMipmaps() {return this.mipmap;}
-
-    public static class SetupTexture implements Callable<IconCoordinate> {
-        private final @NotNull TexturePackList packList;
-        private final @NotNull IconCoordinate coordinate;
-        private final @Nullable BufferedImage defaultTexture;
-        public SetupTexture(@NotNull TexturePackList packList, @NotNull IconCoordinate coordinate, @Nullable BufferedImage defaultTexture) {
-            this.packList = packList;
-            this.coordinate = coordinate;
-            this.defaultTexture = defaultTexture;
-        }
-        @Override
-        public IconCoordinate call() {
-            this.coordinate.resetMetadata();
-            BufferedImage image = CustomAtlasHandler.getTextureOverride(this.packList, this.coordinate.sourceImagePath);
+
+    public boolean tickWhenPaused() {
+        return this.tickPaused;
+    }
+
+    public boolean hasMipmaps() {
+        return this.mipmap;
+    }
+
+    private static class Space {
+        private int x;
+        private int y;
+        private int w;
+        private int h;
+
+        public Space(int x, int y, int w, int h) {
+            this.x = x;
+            this.y = y;
+            this.w = w;
+            this.h = h;
+        }
+    }
+
+    private static class Box {
+
+        private int x;
+        private int y;
+        private int border;
+        @NotNull
+        private final IconCoordinate coord;
+        @NotNull
+        private final BufferedImage image;
+        @Nullable
+        private TexturePack pack;
+
+        public Box(@NotNull Minecraft mc, @NotNull AtlasStitcher atlasStitcher, @NotNull IconCoordinate coordinate, @Nullable BufferedImage defaultTexture) {
+            coordinate.resetMetadata();
+            String path = atlasStitcher.getSourceImageId(coordinate.namespaceId) + ".png";
+            BufferedImage image = CustomAtlasHandler.getTextureOverride(mc.texturePackList, path);
             if(image == null) {
-                TexturePack pack = this.packList.getHighestPriorityTexturePackWithFile(this.coordinate.sourceImagePath);
+                TexturePack pack = mc.texturePackList.getHighestPriorityTexturePackWithFile(path);
                 if (pack != null) {
+                    this.pack = pack;
                     for (int attempt = 0; attempt < 3; attempt++) {
                         try {
-                            image = Textures.readImageUnhandled(pack.getResourceAsStream(this.coordinate.sourceImagePath));
+                            image = Textures.readImageUnhandled(pack.getResourceAsStream(path));
                             if (image != null) break;
                         } catch (Exception e) {
                             LOGGER.error("", e);
                         }
                     }
-                    String metaPath = this.coordinate.sourceImagePath + ".mcmeta";
+                    String metaPath = path + ".mcmeta";
                     if (pack.hasFile(metaPath)) {
                         try (InputStream stream = pack.getResourceAsStream(metaPath)){
-                            this.coordinate.initMetadata(stream);
+                            coordinate.initMetadata(stream);
                         } catch (Exception e) {
-                            LOGGER.error("Failed to initiate metadata for '{}'!", this.coordinate.namespaceId, e);
+                            LOGGER.error("Failed to initiate metadata for '{}'!", coordinate.namespaceId, e);
                         }
                     }
                 }
             }
             if (image == null || image == Textures.missingTexture){
-                LOGGER.warn("{} could not be found!", this.coordinate.sourceImagePath);
-                if (this.defaultTexture != null){
-                    image = this.defaultTexture;
+                LOGGER.warn("{} could not be found!", path);
+                if (defaultTexture != null){
+                    image = defaultTexture;
                 }
                 if (image == null) image = Textures.missingTexture; // If this ever happens I'll be very sad
             }
-            this.coordinate.setImage(image);
-            return this.coordinate;
+            this.image = image;
+            this.coord = coordinate;
+        }
+
+        public Box(int x, int y, int border, @NotNull IconCoordinate coord, @NotNull BufferedImage image, @NotNull TexturePack pack) {
+            this.x = x;
+            this.y = y;
+            this.border = border;
+            this.coord = coord;
+            this.image = image;
+            this.pack = pack;
         }
     }
+
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/texture/stitcher/IconCoordinate.java b/game/client/src/main/java/net/minecraft/client/render/texture/stitcher/IconCoordinate.java
index ccf2bee8b..dfc1f8c63 100644
--- a/game/client/src/main/java/net/minecraft/client/render/texture/stitcher/IconCoordinate.java
+++ b/game/client/src/main/java/net/minecraft/client/render/texture/stitcher/IconCoordinate.java
@@ -7,11 +7,9 @@ import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.slf4j.Logger;
 
-import java.awt.*;
-import java.awt.image.BufferedImage;
 import java.io.InputStream;
 
-public class IconCoordinate implements Comparable<IconCoordinate> {
+public class IconCoordinate {
     private static final Logger LOGGER = LogUtils.getLogger();
     public int iconX;
     public int iconY;
@@ -23,71 +21,36 @@ public class IconCoordinate implements Comparable<IconCoordinate> {
     private double vMax;
     private double uSize;
     private double vSize;
-    private boolean pendingDimensions;
-    protected final @NotNull String sourceImagePath;
     protected final @NotNull TextureMetaHandler metaHandler = new TextureMetaHandler();
     public final @NotNull NamespaceID namespaceId;
     public final @NotNull AtlasStitcher parentAtlas;
-    private BufferedImage _imageStorage;
 
-    public IconCoordinate(@NotNull AtlasStitcher stitcher, @NotNull NamespaceID namespaceId, @NotNull String sourceImagePath) {
+    public IconCoordinate(@NotNull AtlasStitcher stitcher, @NotNull NamespaceID namespaceId) {
         this.parentAtlas = stitcher;
         this.namespaceId = namespaceId;
-        this.sourceImagePath = sourceImagePath;
-    }
-
-    protected void setImage(@NotNull BufferedImage image) {
-        assert image != null : "setImage cannot take null!";
-        this.pendingDimensions = true;
-        this._imageStorage = image;
-    }
-
-    // This will only ever return the actual image when used during a very narrow period of time
-    // Its very much for use with the atlas stitching process and dynamic textures
-    public BufferedImage getImageStorage() {
-        return this._imageStorage;
-    }
-
-    protected void discardImage() {
-        this.uMin = ((double) this.iconX) * this.parentAtlas.getInverseWidth();
-        this.uMax = ((double) this.iconX + width) * this.parentAtlas.getInverseWidth();
-        this.vMin = ((double) this.iconY) * this.parentAtlas.getInverseHeight();
-        this.vMax = ((double) this.iconY + height) * this.parentAtlas.getInverseHeight();
-        this.uSize = width * this.parentAtlas.getInverseWidth();
-        this.vSize = height * this.parentAtlas.getInverseHeight();
-
-        this._imageStorage = null;
-    }
-
-    public boolean needsDimensions() {
-        return this.pendingDimensions;
     }
 
     public void setDimension(int width, int height) {
         this.width = width;
         this.height = height;
-        this.pendingDimensions = false;
     }
 
-    public void setPosition(int x, int y) {
+    protected void setPosition(int x, int y) {
         this.iconX = x;
         this.iconY = y;
     }
 
-    public int getArea() {
-        return this.width * this.height;
+    protected void cacheUVs() {
+        this.uMin = ((double) this.iconX) * this.parentAtlas.getInverseWidth();
+        this.uMax = ((double) this.iconX + this.width) * this.parentAtlas.getInverseWidth();
+        this.vMin = ((double) this.iconY) * this.parentAtlas.getInverseHeight();
+        this.vMax = ((double) this.iconY + this.height) * this.parentAtlas.getInverseHeight();
+        this.uSize = this.width * this.parentAtlas.getInverseWidth();
+        this.vSize = this.height * this.parentAtlas.getInverseHeight();
     }
 
-    protected void drawToAtlas(Graphics2D atlas) {
-        assert this._imageStorage != null : "Image storage should not be null!! something went wrong with image '" + this.namespaceId + "' at '" + this.sourceImagePath + "'!";
-        if (this.width != this._imageStorage.getWidth() || this.height != this._imageStorage.getHeight()) {
-            int[] subImage = this._imageStorage.getRGB(0, 0, this.width, this.height, null, 0, this.width);
-            BufferedImage _img = new BufferedImage(this.width, this.height, BufferedImage.TYPE_INT_ARGB);
-            _img.setRGB(0, 0, this.width, this.height, subImage, 0, this.width);
-            atlas.drawImage(_img, this.iconX, this.iconY, null);
-            return;
-        }
-        atlas.drawImage(this._imageStorage, this.iconX, this.iconY, null);
+    public int getArea() {
+        return this.width * this.height;
     }
 
     public double getIconUMin() {
@@ -122,19 +85,8 @@ public class IconCoordinate implements Comparable<IconCoordinate> {
         return this.vSize;
     }
 
-    public String toString() {
-        return String.format("W:%d, H:%d, X:%d, Y:%d | ID:%s, Source:%s", this.width, this.height, this.iconX, this.iconY, this.namespaceId, this.sourceImagePath);
-    }
-
-    public String getImageSource() {
-        return this.sourceImagePath;
-    }
-
-    @Override
-    public int compareTo(@NotNull IconCoordinate o) {
-        int res = o.height - this.height;
-        if (res != 0) return res;
-        return this.namespaceId.compareTo(o.namespaceId);
+    public @NotNull String toString() {
+        return String.format("W:%d, H:%d, X:%d, Y:%d | ID:%s", this.width, this.height, this.iconX, this.iconY, this.namespaceId);
     }
 
     protected void resetMetadata() {
@@ -149,15 +101,15 @@ public class IconCoordinate implements Comparable<IconCoordinate> {
         }
     }
 
-    public boolean hasMeta(String key) {
+    public boolean hasMeta(@NotNull String key) {
         return this.metaHandler.has(key);
     }
 
-    public @Nullable <T> T getMeta(String key, Class<T> aClass) {
+    public @Nullable <T> T getMeta(@NotNull String key, @NotNull Class<T> aClass) {
         return this.metaHandler.get(key, aClass);
     }
 
-    public <T> T getOrDefaultMeta(String key, T metaDefault, Class<T> aClass) {
+    public <T> T getOrDefaultMeta(@NotNull String key, @NotNull T metaDefault, @NotNull Class<T> aClass) {
         return this.metaHandler.getOrDefault(key, metaDefault, aClass);
     }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/texture/stitcher/TextureRegistry.java b/game/client/src/main/java/net/minecraft/client/render/texture/stitcher/TextureRegistry.java
index 446c67f22..f5fee0b2c 100644
--- a/game/client/src/main/java/net/minecraft/client/render/texture/stitcher/TextureRegistry.java
+++ b/game/client/src/main/java/net/minecraft/client/render/texture/stitcher/TextureRegistry.java
@@ -53,25 +53,27 @@ public class TextureRegistry {
 
     @SuppressWarnings("unused")
     public static AtlasStitcher worldAtlas = register(
-        new AtlasStitcher(false, true, missingIconImage)
+        new AtlasStitcher(false, true)
             .addDirectory("block", "textures/block")
             .addDirectory("item", "textures/item")
             .addDirectory("particle", "textures/particle")
+//            .addLayer("maskColor", "cmask", 0xFFFFFFFF)
+            .addLayer("emissive", "emiss", 0x00000000)
     );
 
     @SuppressWarnings("unused")
     public static AtlasStitcher artAtlas = register(
-        new AtlasStitcher(false, true, null)
+        new AtlasStitcher(false, true)
             .addDirectory("art", "textures/art")
     );
     @SuppressWarnings("unused")
     public static AtlasStitcher guiSpriteAtlas = register(
-        new AtlasStitcher(true, false, null)
+        new AtlasStitcher(true, false)
             .addDirectory("gui", "textures/gui/sprites")
     );
     @SuppressWarnings("unused")
     public static AtlasStitcher signAtlas = register(
-        new AtlasStitcher(false, false, null)
+        new AtlasStitcher(false, false)
             .addDirectory("sign", "textures/gui/sign")
     );
 
@@ -103,7 +105,7 @@ public class TextureRegistry {
         final AtlasStitcher atlas = stitcherMap.get(atlasId);
         if (atlas == null) throw new IllegalArgumentException("Failed to find atlas '" + atlasId + "'!");
 
-        return atlas.textureMap.containsKey(NamespaceID.fromPool(id.namespace(), id.value().substring(slashIndex + 1)));
+        return atlas.iconMap.containsKey(NamespaceID.fromPool(id.namespace(), id.value().substring(slashIndex + 1)));
     }
     public static @NotNull AtlasStitcher register(@NotNull AtlasStitcher atlas){
         for (String id : atlas.idDirMap.keySet()) {
@@ -198,7 +200,7 @@ public class TextureRegistry {
                     writer.append("# Auto generated tiles mapping for atlas '").append(stitcherEntry.getKey()).append("'\n");
                     writer.append("# generated for version '").append(Global.VERSION).append("' at '").append(dateFormat.format(new Date())).append("'\n");
                     writer.append("size=").append(Integer.toString(stitcher.getAtlasWidth())).append("x").append(Integer.toString(stitcher.getAtlasHeight())).append("\n");
-                    for (final Map.Entry<NamespaceID, IconCoordinate> entry : stitcher.textureMap.entrySet()) {
+                    for (final Map.Entry<NamespaceID, IconCoordinate> entry : stitcher.iconMap.entrySet()) {
                         final IconCoordinate coordinate = entry.getValue();
                         writer.append(Integer.toString(coordinate.iconX)).append(",").append(Integer.toString(coordinate.iconY));
                         writer.append("=");
diff --git a/game/core/src/main/java/net/minecraft/core/util/helper/Buffer.java b/game/client/src/main/java/net/minecraft/client/util/helper/Buffer.java
similarity index 80%
rename from game/core/src/main/java/net/minecraft/core/util/helper/Buffer.java
rename to game/client/src/main/java/net/minecraft/client/util/helper/Buffer.java
index f6e3a2ba1..8304a7697 100644
--- a/game/core/src/main/java/net/minecraft/core/util/helper/Buffer.java
+++ b/game/client/src/main/java/net/minecraft/client/util/helper/Buffer.java
@@ -1,4 +1,8 @@
-package net.minecraft.core.util.helper;
+package net.minecraft.client.util.helper;
+
+import net.minecraft.core.util.helper.Color;
+import org.jetbrains.annotations.NotNull;
+import org.lwjgl.BufferUtils;
 
 import java.awt.image.BufferedImage;
 import java.nio.ByteBuffer;
@@ -6,22 +10,17 @@ import java.nio.ByteOrder;
 
 public abstract class Buffer {
 	
-	public static ByteBuffer buffer = createBuffer(2097152);
-	
-	public static ByteBuffer createBuffer(int size) {
-		return ByteBuffer.allocateDirect(size).order(ByteOrder.nativeOrder());
-	}
+	public static ByteBuffer buffer = BufferUtils.createByteBuffer(2097152);
 	
 	public static void checkBufferSize(int size) {
 		if(buffer.capacity() < size) {
-			buffer = createBuffer(size);
+			buffer = BufferUtils.createByteBuffer(size);
 			System.out.println("Expanding buffer to "+size);
 		}
 	}
 	
 	public static void reset() {
-		buffer.position(0);
-		buffer.limit(buffer.capacity());
+		buffer.clear();
 	}
 	
 	public static int getInt(int i) {
@@ -41,7 +40,7 @@ public abstract class Buffer {
         buffer.flip();
 	}
 
-	public static void put(BufferedImage image) {
+	public static void put(@NotNull BufferedImage image) {
 		checkBufferSize(image.getWidth() * image.getHeight() * 4);
 		reset();
 		
@@ -70,7 +69,7 @@ public abstract class Buffer {
 		put4Bytes(i, r, g, b, a);
 	}
 
-	public static void putColor(int i, Color color) {
+	public static void putColor(int i, @NotNull Color color) {
 		putARGB(i, color.value);
 	}
 	
diff --git a/game/client/src/main/java/net/minecraft/client/util/helper/ScreenshotHelper.java b/game/client/src/main/java/net/minecraft/client/util/helper/ScreenshotHelper.java
index 87889a252..86d2ff837 100644
--- a/game/client/src/main/java/net/minecraft/client/util/helper/ScreenshotHelper.java
+++ b/game/client/src/main/java/net/minecraft/client/util/helper/ScreenshotHelper.java
@@ -1,6 +1,6 @@
 package net.minecraft.client.util.helper;
 
-import static net.minecraft.core.util.helper.Buffer.*;
+import static net.minecraft.client.util.helper.Buffer.*;
 import static org.lwjgl.opengl.ARBFramebufferObject.*;
 import static org.lwjgl.opengl.GL11.*;
 import static org.lwjgl.opengl.GL12.GL_CLAMP_TO_EDGE;
@@ -16,7 +16,6 @@ import net.minecraft.client.render.FrameBuffer;
 import net.minecraft.client.render.Renderer;
 import net.minecraft.client.render.texture.Texture;
 import net.minecraft.core.Global;
-import net.minecraft.core.util.helper.Buffer;
 
 public class ScreenshotHelper {
 	
diff --git a/game/client/src/main/java/net/minecraft/client/util/helper/Textures.java b/game/client/src/main/java/net/minecraft/client/util/helper/Textures.java
index 5cf5452c2..332168a12 100644
--- a/game/client/src/main/java/net/minecraft/client/util/helper/Textures.java
+++ b/game/client/src/main/java/net/minecraft/client/util/helper/Textures.java
@@ -1,6 +1,6 @@
 package net.minecraft.client.util.helper;
 
-import static net.minecraft.core.util.helper.Buffer.*;
+import static net.minecraft.client.util.helper.Buffer.*;
 import static org.lwjgl.opengl.GL11.*;
 
 import java.awt.Color;
@@ -12,15 +12,12 @@ import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.ByteBuffer;
-import java.util.List;
 
 import javax.imageio.ImageIO;
 
 import com.mojang.logging.LogUtils;
 import it.unimi.dsi.fastutil.ints.IntList;
-import net.minecraft.client.render.texture.stitcher.AtlasStitcher;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
-import net.minecraft.core.util.helper.Buffer;
 import org.jetbrains.annotations.NotNull;
 import org.lwjgl.opengl.GL12;
 
diff --git a/game/client/src/main/java/org/useless/dragonfly/models/block/StaticBlockModel.java b/game/client/src/main/java/org/useless/dragonfly/models/block/StaticBlockModel.java
index 4d8d941fb..09ad1bf82 100644
--- a/game/client/src/main/java/org/useless/dragonfly/models/block/StaticBlockModel.java
+++ b/game/client/src/main/java/org/useless/dragonfly/models/block/StaticBlockModel.java
@@ -3,7 +3,6 @@ package org.useless.dragonfly.models.block;
 import net.minecraft.client.render.block.color.BlockColor;
 import net.minecraft.client.render.block.model.BlockModel;
 import net.minecraft.client.render.tessellator.TessellatorGeneral;
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.util.helper.Side;
@@ -22,7 +21,7 @@ public interface StaticBlockModel {
     /**
      * @return True if anything rendered, false otherwise
      */
-    boolean renderAttached(@NotNull BlockModel<? extends BlockLogic> sourceModel, @NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, int x, int y, int z, double xOff, double yOff, double zOff, boolean cullFaces, @Nullable IconCoordinate overrideTexture);
+    boolean renderAttached(@NotNull BlockModel<? extends BlockLogic> sourceModel, @NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, int x, int y, int z, double xOff, double yOff, double zOff, boolean cullFaces, @Nullable IconCoordinate overrideTexture);
 
     /**
      * @return Block texture to overlay when inside a block
diff --git a/game/client/src/main/java/org/useless/dragonfly/models/block/mojang/StaticBlockModelMojang.java b/game/client/src/main/java/org/useless/dragonfly/models/block/mojang/StaticBlockModelMojang.java
index 58d3241bf..057e81576 100644
--- a/game/client/src/main/java/org/useless/dragonfly/models/block/mojang/StaticBlockModelMojang.java
+++ b/game/client/src/main/java/org/useless/dragonfly/models/block/mojang/StaticBlockModelMojang.java
@@ -9,7 +9,6 @@ import net.minecraft.client.render.block.model.BlockModel;
 import net.minecraft.client.render.block.model.BlockModelStandard;
 import net.minecraft.client.render.renderer.GLRenderer;
 import net.minecraft.client.render.tessellator.TessellatorGeneral;
-import net.minecraft.client.render.tessellator.TessellatorTerrain;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.core.block.BlockLogic;
 import net.minecraft.core.util.helper.Color;
@@ -26,9 +25,7 @@ import org.useless.dragonfly.models.block.StaticBlockModel;
 
 import java.util.Locale;
 
-import static net.minecraft.client.render.block.model.BlockModel.ENABLE_DIRECTIONAL_LIGHTING;
 import static net.minecraft.client.render.block.model.BlockModel.FULL_CUBE_THRESHOLD;
-import static net.minecraft.client.render.block.model.BlockModel.SIDE_LIGHT_MULTIPLIER;
 import static org.useless.dragonfly.data.block.mojang.CompiledBlockModelMojangData.C_Element.FLOATS_PER_NORMAL;
 import static org.useless.dragonfly.data.block.mojang.CompiledBlockModelMojangData.C_Element.FLOATS_PER_VERTEX;
 import static org.useless.dragonfly.data.block.mojang.CompiledBlockModelMojangData.C_Element.NORMAL_FLOAT_X;
@@ -98,7 +95,7 @@ public class StaticBlockModelMojang implements StaticBlockModel {
     }
 
     @Override
-    public boolean renderAttached(@NotNull BlockModel<? extends BlockLogic> sourceModel, @NotNull TessellatorTerrain tessellator, @NotNull WorldSource worldSource, int x, int y, int z, double xOff, double yOff, double zOff, boolean cullFaces, @Nullable IconCoordinate overrideTexture) {
+    public boolean renderAttached(@NotNull BlockModel<? extends BlockLogic> sourceModel, @NotNull TessellatorGeneral tessellator, @NotNull WorldSource worldSource, int x, int y, int z, double xOff, double yOff, double zOff, boolean cullFaces, @Nullable IconCoordinate overrideTexture) {
         if (this.compiled.elements.length == 0) return false;
         boolean didRender = false;
         LIGHTING_CACHE.setupCache(sourceModel.block, worldSource, x, y, z);
@@ -307,18 +304,17 @@ public class StaticBlockModelMojang implements StaticBlockModel {
                     lightTL = lightBL = lightBR = lightTR = getBrightness(dirX2, dirY2, dirZ2, minBrightness);
                 }
 
-                final float sideLight = (element.shade && ENABLE_DIRECTIONAL_LIGHTING) ? SIDE_LIGHT_MULTIPLIER[direction.getId()] : 1;
-                float colorRedBottomLeft = r * sideLight;
+                float colorRedBottomLeft = r;
                 float colorRedBottomRight = colorRedBottomLeft;
                 float colorRedTopRight = colorRedBottomLeft;
                 float colorRedTopLeft = colorRedBottomLeft;
 
-                float colorGreenBottomLeft = g * sideLight;
+                float colorGreenBottomLeft = g;
                 float colorGreenBottomRight = colorGreenBottomLeft;
                 float colorGreenTopRight = colorGreenBottomLeft;
                 float colorGreenTopLeft = colorGreenBottomLeft;
 
-                float colorBlueBottomLeft = b * sideLight;
+                float colorBlueBottomLeft = b;
                 float colorBlueBottomRight = colorBlueBottomLeft;
                 float colorBlueTopRight = colorBlueBottomLeft;
                 float colorBlueTopLeft = colorBlueBottomLeft;
@@ -349,6 +345,7 @@ public class StaticBlockModelMojang implements StaticBlockModel {
 
                 final int offset = face * 4 * FLOATS_PER_VERTEX;
 
+                tessellator.setNormal(direction.getOffsetX(), direction.getOffsetY(), direction.getOffsetZ());
                 tessellator.setColorOpaque3f(colorRedTopLeft, colorGreenTopLeft, colorBlueTopLeft);
                 tessellator.setLightmapCoord1i(lightmapCoordTopLeft);
                 tessellator.addVertexWithUV(
@@ -385,6 +382,7 @@ public class StaticBlockModelMojang implements StaticBlockModel {
                     coordinate.getSubIconU(element.vertexData[offset + VERTEX_TOP_RIGHT * FLOATS_PER_VERTEX + VERTEX_FLOAT_U]),
                     coordinate.getSubIconV(element.vertexData[offset + VERTEX_TOP_RIGHT * FLOATS_PER_VERTEX + VERTEX_FLOAT_V]));
 
+                tessellator.setNormal(0, 1, 0);
                 didRender = true;
             }
         }
diff --git a/game/client/src/main/java/org/useless/dragonfly/models/entity/mojang/StaticEntityModelMojang.java b/game/client/src/main/java/org/useless/dragonfly/models/entity/mojang/StaticEntityModelMojang.java
index 353e0bad8..2b2969cd3 100644
--- a/game/client/src/main/java/org/useless/dragonfly/models/entity/mojang/StaticEntityModelMojang.java
+++ b/game/client/src/main/java/org/useless/dragonfly/models/entity/mojang/StaticEntityModelMojang.java
@@ -27,7 +27,7 @@ import java.util.Map;
 
 public class StaticEntityModelMojang implements StaticEntityModel {
     private static final BoneTransform DUMMY_TRANSFORM = new BoneTransform();
-    private static final TessellatorEntity entityTessellator = new TessellatorEntity(2048);
+    private static final TessellatorEntity entityTessellator = new TessellatorEntity(8192);
     public final @NotNull Map<@NotNull String, @NotNull BoneTransform> transformMap = new Object2ObjectOpenHashMap<>();
     public final @NotNull BoneTransform @NotNull [] transforms;
     public final @NotNull Bone @NotNull [] bones;
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/activator/front_active.emiss.png b/game/client/src/main/resources/assets/minecraft/textures/block/activator/front_active.emiss.png
new file mode 100644
index 000000000..9672dd133
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/activator/front_active.emiss.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/activator/front_active_overlay.png b/game/client/src/main/resources/assets/minecraft/textures/block/activator/front_active_overlay.png
deleted file mode 100644
index ec9aa8026..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/activator/front_active_overlay.png and /dev/null differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/activator/side_active.emiss.png b/game/client/src/main/resources/assets/minecraft/textures/block/activator/side_active.emiss.png
new file mode 100644
index 000000000..d182d4ae4
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/activator/side_active.emiss.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/activator/side_active_overlay.png b/game/client/src/main/resources/assets/minecraft/textures/block/activator/side_active_overlay.png
deleted file mode 100644
index 14bff6a5c..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/activator/side_active_overlay.png and /dev/null differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/activator/top_active.emiss.png b/game/client/src/main/resources/assets/minecraft/textures/block/activator/top_active.emiss.png
new file mode 100644
index 000000000..4e1cbce88
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/activator/top_active.emiss.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/activator/top_active_overlay.png b/game/client/src/main/resources/assets/minecraft/textures/block/activator/top_active_overlay.png
deleted file mode 100644
index 45d436aef..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/activator/top_active_overlay.png and /dev/null differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/block_nethercoal.emiss.png b/game/client/src/main/resources/assets/minecraft/textures/block/block_nethercoal.emiss.png
new file mode 100644
index 000000000..51b9ba7b4
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/block_nethercoal.emiss.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/block_nethercoal_overlay.png b/game/client/src/main/resources/assets/minecraft/textures/block/block_nethercoal_overlay.png
deleted file mode 100644
index dc0ec43e0..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/block_nethercoal_overlay.png and /dev/null differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/cobbled_netherrack/igneous_overlay.png b/game/client/src/main/resources/assets/minecraft/textures/block/cobbled_netherrack/igneous.emiss.png
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/block/cobbled_netherrack/igneous_overlay.png
rename to game/client/src/main/resources/assets/minecraft/textures/block/cobbled_netherrack/igneous.emiss.png
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/grass/side.png b/game/client/src/main/resources/assets/minecraft/textures/block/grass/side.png
index 21a7ae5ec..ef1502010 100644
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/grass/side.png and b/game/client/src/main/resources/assets/minecraft/textures/block/grass/side.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/grass/side_overlay.png b/game/client/src/main/resources/assets/minecraft/textures/block/grass/side_overlay.png
index 033220ada..ad1de140d 100644
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/grass/side_overlay.png and b/game/client/src/main/resources/assets/minecraft/textures/block/grass/side_overlay.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active0.emiss.png b/game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active0.emiss.png
new file mode 100644
index 000000000..44dc4abff
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active0.emiss.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active_overlay0.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active0.emiss.png.mcmeta
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active_overlay0.png.mcmeta
rename to game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active0.emiss.png.mcmeta
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active1.emiss.png b/game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active1.emiss.png
new file mode 100644
index 000000000..923aa551d
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active1.emiss.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active_overlay1.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active1.emiss.png.mcmeta
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active_overlay1.png.mcmeta
rename to game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active1.emiss.png.mcmeta
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active2.emiss.png b/game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active2.emiss.png
new file mode 100644
index 000000000..50f5502b4
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active2.emiss.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active_overlay2.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active2.emiss.png.mcmeta
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active_overlay2.png.mcmeta
rename to game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active2.emiss.png.mcmeta
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active3.emiss.png b/game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active3.emiss.png
new file mode 100644
index 000000000..d93e1b4b3
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active3.emiss.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active_overlay3.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active3.emiss.png.mcmeta
similarity index 100%
rename from game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active_overlay3.png.mcmeta
rename to game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active3.emiss.png.mcmeta
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active_overlay0.png b/game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active_overlay0.png
deleted file mode 100644
index f62911909..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active_overlay0.png and /dev/null differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active_overlay1.png b/game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active_overlay1.png
deleted file mode 100644
index 6d477d754..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active_overlay1.png and /dev/null differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active_overlay2.png b/game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active_overlay2.png
deleted file mode 100644
index 3fd4a6669..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active_overlay2.png and /dev/null differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active_overlay3.png b/game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active_overlay3.png
deleted file mode 100644
index d7b0810b4..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/matcher/front_active_overlay3.png and /dev/null differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/matcher/side_active.emiss.png b/game/client/src/main/resources/assets/minecraft/textures/block/matcher/side_active.emiss.png
new file mode 100644
index 000000000..d56bd594a
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/matcher/side_active.emiss.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/matcher/side_active_overlay.png b/game/client/src/main/resources/assets/minecraft/textures/block/matcher/side_active_overlay.png
deleted file mode 100644
index 7e18345b9..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/matcher/side_active_overlay.png and /dev/null differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/motion_sensor/active_front.emiss.png b/game/client/src/main/resources/assets/minecraft/textures/block/motion_sensor/active_front.emiss.png
new file mode 100644
index 000000000..344a2ca23
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/motion_sensor/active_front.emiss.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/motion_sensor/active_front_overlay.png b/game/client/src/main/resources/assets/minecraft/textures/block/motion_sensor/active_front_overlay.png
deleted file mode 100644
index 9a432b018..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/motion_sensor/active_front_overlay.png and /dev/null differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/ore/nethercoal/netherrack.emiss.png b/game/client/src/main/resources/assets/minecraft/textures/block/ore/nethercoal/netherrack.emiss.png
new file mode 100644
index 000000000..2f167ff52
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/ore/nethercoal/netherrack.emiss.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/ore/nethercoal/netherrack_overlay.png b/game/client/src/main/resources/assets/minecraft/textures/block/ore/nethercoal/netherrack_overlay.png
deleted file mode 100644
index 2350c681a..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/ore/nethercoal/netherrack_overlay.png and /dev/null differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/basalt_active.emiss.png b/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/basalt_active.emiss.png
new file mode 100644
index 000000000..267fc0175
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/basalt_active.emiss.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/basalt_active.png b/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/basalt_active.png
new file mode 100644
index 000000000..364d5c410
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/basalt_active.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/granite_active.emiss.png b/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/granite_active.emiss.png
new file mode 100644
index 000000000..434bac152
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/granite_active.emiss.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/granite_active.png b/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/granite_active.png
new file mode 100644
index 000000000..f43e644b0
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/granite_active.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/limestone_active.emiss.png b/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/limestone_active.emiss.png
new file mode 100644
index 000000000..405d97330
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/limestone_active.emiss.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/limestone_active.png b/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/limestone_active.png
new file mode 100644
index 000000000..a50f86e90
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/limestone_active.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/overlay.png b/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/overlay.png
deleted file mode 100644
index 967bd3fec..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/overlay.png and /dev/null differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/permafrost_active.emiss.png b/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/permafrost_active.emiss.png
new file mode 100644
index 000000000..d6d1c9d43
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/permafrost_active.emiss.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/permafrost_active.png b/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/permafrost_active.png
new file mode 100644
index 000000000..5c6ad28ab
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/permafrost_active.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/stone_active.emiss.png b/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/stone_active.emiss.png
new file mode 100644
index 000000000..5dcf98380
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/stone_active.emiss.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/stone_active.png b/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/stone_active.png
new file mode 100644
index 000000000..628fd1210
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/stone_active.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/stone_retro_active.emiss .png b/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/stone_retro_active.emiss .png
new file mode 100644
index 000000000..707d8fca8
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/stone_retro_active.emiss .png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/stone_retro_active.emiss.png b/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/stone_retro_active.emiss.png
new file mode 100644
index 000000000..32b213b20
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/stone_retro_active.emiss.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/stone_retro_active.png b/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/stone_retro_active.png
new file mode 100644
index 000000000..844a82d6f
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/ore/redstone/stone_retro_active.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/pumpkin_redstone/front.emiss.png b/game/client/src/main/resources/assets/minecraft/textures/block/pumpkin_redstone/front.emiss.png
new file mode 100644
index 000000000..31c297535
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/pumpkin_redstone/front.emiss.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/pumpkin_redstone/front_overlay.png b/game/client/src/main/resources/assets/minecraft/textures/block/pumpkin_redstone/front_overlay.png
deleted file mode 100644
index bc393b0e7..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/pumpkin_redstone/front_overlay.png and /dev/null differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/rail_detector/active.emiss.png b/game/client/src/main/resources/assets/minecraft/textures/block/rail_detector/active.emiss.png
new file mode 100644
index 000000000..df8a8a843
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/rail_detector/active.emiss.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/rail_detector/active.png b/game/client/src/main/resources/assets/minecraft/textures/block/rail_detector/active.png
new file mode 100644
index 000000000..0727d9b13
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/rail_detector/active.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/rail_detector/active_overlay.png b/game/client/src/main/resources/assets/minecraft/textures/block/rail_detector/active_overlay.png
deleted file mode 100644
index 51abdea39..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/rail_detector/active_overlay.png and /dev/null differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/rail_powered/active.emiss.png b/game/client/src/main/resources/assets/minecraft/textures/block/rail_powered/active.emiss.png
new file mode 100644
index 000000000..18be27324
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/block/rail_powered/active.emiss.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/rail_powered/active_overlay.png b/game/client/src/main/resources/assets/minecraft/textures/block/rail_powered/active_overlay.png
deleted file mode 100644
index 561630d52..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/rail_powered/active_overlay.png and /dev/null differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/repeater/active_overlay.png b/game/client/src/main/resources/assets/minecraft/textures/block/repeater/active_top.emiss.png
similarity index 86%
rename from game/client/src/main/resources/assets/minecraft/textures/block/repeater/active_overlay.png
rename to game/client/src/main/resources/assets/minecraft/textures/block/repeater/active_top.emiss.png
index 2be1a6a7a..f18bc11db 100644
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/repeater/active_overlay.png and b/game/client/src/main/resources/assets/minecraft/textures/block/repeater/active_top.emiss.png differ
diff --git a/game/client/src/main/resources/shaders/clouds.fsh b/game/client/src/main/resources/shaders/clouds.fsh
index dcaad24a3..707540157 100644
--- a/game/client/src/main/resources/shaders/clouds.fsh
+++ b/game/client/src/main/resources/shaders/clouds.fsh
@@ -26,8 +26,8 @@ layout (std140) uniform Matrices {
 uniform int isEyeInLiquid;
 uniform vec2 uViewPortSize;
 
-uniform sampler2D texture0;
-uniform sampler2D texture1;
+uniform sampler2D colortex;
+uniform sampler2D lighttex;
 
 float distance() {
 	vec4 fragPos = matrices.projectionInv * vec4((gl_FragCoord.xy / uViewPortSize) * 2.0f - 1.0f, gl_FragCoord.z * 2.0f - 1.0f, 1.0f);
@@ -37,7 +37,7 @@ float distance() {
 }
 
 void main() {
-	vec4 tex = texture(texture0, TexCoord);
+	vec4 tex = texture(colortex, TexCoord);
 	
 	// Alpha test
 	if(tex.a < 0.1f) {
diff --git a/game/client/src/main/resources/shaders/color_world.fsh b/game/client/src/main/resources/shaders/color_world.fsh
index dcfc19dd5..f74eec6b4 100644
--- a/game/client/src/main/resources/shaders/color_world.fsh
+++ b/game/client/src/main/resources/shaders/color_world.fsh
@@ -24,7 +24,7 @@ layout (std140) uniform Matrices {
     mat4 viewInv;
 } matrices;
 
-uniform sampler2D texture1;
+uniform sampler2D lighttex;
 
 float distance() {
     vec4 fragPos = matrices.projectionInv * vec4((gl_FragCoord.xy / uViewPortSize) * 2.0f - 1.0f, gl_FragCoord.z * 2.0f - 1.0f, 1.0f);
@@ -64,7 +64,7 @@ vec4 computeFog(vec4 color) {
 }
 
 void main() {
-    vec4 lightColor = texture(texture1, LightMapCoord);
+    vec4 lightColor = texture(lighttex, LightMapCoord);
 
     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/font.fsh b/game/client/src/main/resources/shaders/font.fsh
index b347f8cba..a5146ab49 100644
--- a/game/client/src/main/resources/shaders/font.fsh
+++ b/game/client/src/main/resources/shaders/font.fsh
@@ -7,11 +7,11 @@ in vec2 Lightmap;
 
 uniform vec4 uColor;
 
-uniform sampler2D texture0;
-uniform sampler2D texture1;
+uniform sampler2D colortex;
+uniform sampler2D lighttex;
 
 void main() {
-    FragColor = texture(texture0, TexCoord) * texture(texture1, Lightmap) * Color * uColor;
+    FragColor = texture(colortex, TexCoord) * texture(lighttex, Lightmap) * Color * uColor;
     if (FragColor.a < 0.1f) {
         discard;
     }
diff --git a/game/client/src/main/resources/shaders/interface.fsh b/game/client/src/main/resources/shaders/interface.fsh
index 8017968fb..d06927a62 100644
--- a/game/client/src/main/resources/shaders/interface.fsh
+++ b/game/client/src/main/resources/shaders/interface.fsh
@@ -6,8 +6,8 @@ in vec4 Color;
 in vec2 TexCoord;
 
 uniform vec4 uColor;
-uniform sampler2D texture0;
+uniform sampler2D colortex;
 
 void main() {
-    FragColor = texture(texture0, TexCoord) * Color * uColor;
+    FragColor = texture(colortex, TexCoord) * Color * uColor;
 }
diff --git a/game/client/src/main/resources/shaders/particle.fsh b/game/client/src/main/resources/shaders/particle.fsh
index f7ffa5db6..2d23f4c9e 100644
--- a/game/client/src/main/resources/shaders/particle.fsh
+++ b/game/client/src/main/resources/shaders/particle.fsh
@@ -5,11 +5,11 @@ in vec4 Color;
 in vec2 TexCoord;
 in vec2 Lightmap;
 
-uniform sampler2D texture0;
-uniform sampler2D texture1;
+uniform sampler2D colortex;
+uniform sampler2D lighttex;
 
 void main() {
-    FragColor = texture(texture0, TexCoord) * texture(texture1, Lightmap) * Color;
+    FragColor = texture(colortex, TexCoord) * texture(lighttex, Lightmap) * Color;
     if (FragColor.a < 0.1f) {
         discard;
     }
diff --git a/game/client/src/main/resources/shaders/terrain.fsh b/game/client/src/main/resources/shaders/terrain.fsh
new file mode 100644
index 000000000..e7b0b1e1f
--- /dev/null
+++ b/game/client/src/main/resources/shaders/terrain.fsh
@@ -0,0 +1,91 @@
+#version 410 core
+
+out vec4 FragColor;
+
+in vec4 Color;
+in vec2 TexCoord;
+in vec2 LightMapCoord;
+in vec3 Light;
+
+uniform vec4 uColor;
+uniform vec2 uViewPortSize;
+
+layout (std140) uniform FogState {
+    vec4 color;
+    int mode;
+    float start;
+    float end;
+    float density;
+} fogState;
+
+layout (std140) uniform Matrices {
+    mat4 projection;
+    mat4 projectionInv;
+    mat4 view;
+    mat4 viewInv;
+} matrices;
+
+uniform sampler2D colortex;
+uniform sampler2D lighttex;
+uniform sampler2D emmisivetex;
+//uniform sampler2D colormasktex;
+
+float distance() {
+    vec4 fragPos = matrices.projectionInv * vec4((gl_FragCoord.xy / uViewPortSize) * 2.0f - 1.0f, gl_FragCoord.z * 2.0f - 1.0f, 1.0f);
+    fragPos /= fragPos.w;
+
+    return length(fragPos.xyz);
+}
+
+// Taken from https://github.com/hughsk/glsl-fog
+float fogFactorLinear() {
+    return 1.0 - clamp(((fogState.end - (distance())) / (fogState.end - fogState.start)), 0.0, 1.0);
+}
+
+float fogFactorExp() {
+    return 1.0 - clamp(exp(-fogState.density * (distance())), 0.0, 1.0);
+}
+
+float fogFactorExp2() {
+    float LOG2 = -1.442695;
+    float d = fogState.density * (distance());
+    return 1.0 - clamp(exp2(d * d * LOG2), 0.0, 1.0);
+}
+
+
+vec4 computeFog(vec4 color) {
+    float f = 0;
+    if (fogState.mode == 0) { // Linear
+        f = fogFactorLinear();
+    }
+    else if (fogState.mode == 1) { // EXP
+        f = fogFactorExp();
+    }
+    else if (fogState.mode == 2) { // EXP2
+        f = fogFactorExp2();
+    }
+    return vec4(mix(color.rgb, fogState.color.rgb, f), color.a);
+}
+
+void main() {
+    vec4 emmisiveColor = texture(emmisivetex, TexCoord);
+    vec4 lightColor = texture(lighttex, vec2(max(LightMapCoord.x, emmisiveColor.r), max(LightMapCoord.y, emmisiveColor.g)));
+    vec4 texColor = texture(colortex, TexCoord);
+    //    vec4 maskColor = texture(colormasktex, TexCoord);
+
+    vec4 oColor = texColor * lightColor;
+
+//    vec4 c = mix(vec4(1, 1, 1, 1), Color, maskColor.r);
+    vec4 c = Color;
+
+    vec4 postColor = oColor * c * uColor;
+    vec4 litColor = vec4(postColor.rgb * clamp(Light, 0, 1), postColor.a);
+
+    vec4 fColor = computeFog(litColor);
+
+
+    FragColor = fColor;
+    if (FragColor.a < 0.1f) {
+        discard;
+    }
+}
diff --git a/game/client/src/main/resources/shaders/terrain.vsh b/game/client/src/main/resources/shaders/terrain.vsh
new file mode 100644
index 000000000..4df0a92fb
--- /dev/null
+++ b/game/client/src/main/resources/shaders/terrain.vsh
@@ -0,0 +1,39 @@
+#version 410 core
+layout (location = 0) in vec3 aPos;
+layout (location = 1) in vec4 aColor;
+layout (location = 2) in vec2 aUV;
+layout (location = 3) in vec2 aLightmap;
+layout (location = 4) in vec3 aNormal;
+
+out vec4 Color;
+out vec2 TexCoord;
+out vec2 LightMapCoord;
+out vec3 Light;
+
+uniform mat4 normalTransform;
+uniform vec4 lightModelAmbient;
+uniform vec4 lightSourcePosition[];
+uniform vec4 lightSourceDiffuse[];
+
+uniform mat4 model;
+
+layout (std140) uniform Matrices {
+    mat4 projection;
+    mat4 projectionInv;
+    mat4 view;
+    mat4 viewInv;
+} matrices;
+
+void main() {
+    vec4 p = vec4(aPos, 1);
+    gl_Position = matrices.projection * matrices.view * model * p;
+
+    TexCoord = aUV;
+    Color = aColor;
+    LightMapCoord = aLightmap;
+
+    vec3 norm = normalize(aNormal);
+    float d1 = max(0.0, dot(norm, vec3(-0.2f, 1f, -0.7f)));
+    float d2 = max(0.0, dot(norm, vec3( 0.2f, 1f,  0.7f)));
+    Light = vec3(0.5, 0.5, 0.5) + vec3(0.5, 0.5, 0.5) * clamp(d1 + d2, 0, 1);
+}
diff --git a/game/client/src/main/resources/shaders/world.fsh b/game/client/src/main/resources/shaders/world.fsh
index e4ecc285d..1dd6db044 100644
--- a/game/client/src/main/resources/shaders/world.fsh
+++ b/game/client/src/main/resources/shaders/world.fsh
@@ -25,8 +25,8 @@ layout (std140) uniform Matrices {
     mat4 viewInv;
 } matrices;
 
-uniform sampler2D texture0;
-uniform sampler2D texture1;
+uniform sampler2D colortex;
+uniform sampler2D lighttex;
 
 float distance() {
     vec4 fragPos = matrices.projectionInv * vec4((gl_FragCoord.xy / uViewPortSize) * 2.0f - 1.0f, gl_FragCoord.z * 2.0f - 1.0f, 1.0f);
@@ -66,8 +66,8 @@ vec4 computeFog(vec4 color) {
 }
 
 void main() {
-    vec4 lightColor = texture(texture1, LightMapCoord);
-    vec4 texColor = texture(texture0, TexCoord);
+    vec4 lightColor = texture(lighttex, LightMapCoord);
+    vec4 texColor = texture(colortex, TexCoord);
 
     vec4 oColor = texColor * lightColor * Color * uColor;
     vec4 litColor = vec4(oColor.rgb * clamp(Light, 0, 1), oColor.a);
diff --git a/game/core/src/main/java/net/minecraft/core/world/biome/provider/BiomeProviderB173.java b/game/core/src/main/java/net/minecraft/core/world/biome/provider/BiomeProviderB173.java
index be264996d..37d3867d4 100644
--- a/game/core/src/main/java/net/minecraft/core/world/biome/provider/BiomeProviderB173.java
+++ b/game/core/src/main/java/net/minecraft/core/world/biome/provider/BiomeProviderB173.java
@@ -35,19 +35,19 @@ public class BiomeProviderB173
         if (temperatures == null || temperatures.length < xSize * zSize) {
             temperatures = new double[xSize * zSize];
         }
-        this.temperatureMap.getValue(temperatures, x, z, xSize, xSize, 0.025, 0.025, 0.25);
+        this.temperatureMap.getRegion(temperatures, x, z, xSize, xSize, 0.025, 0.025, 0.25);
 
         if (humidities == null || humidities.length < xSize * zSize) {
             humidities = new double[xSize * zSize];
         }
-        this.downfallMap.getValue(humidities, x, z, xSize, xSize, 0.05, 0.05, 1.0 / 3.0);
+        this.downfallMap.getRegion(humidities, x, z, xSize, xSize, 0.05, 0.05, 1.0 / 3.0);
 
         if (varieties == null || varieties.length < xSize * zSize) {
             varieties = new double[xSize * zSize];
         }
         Arrays.fill(varieties, 0.0);
 
-        final double[] noises = this.noiseMap.getValue(null, x, z, xSize, xSize, 0.25, 0.25, 0.5882352941176471D);
+        final double[] noises = this.noiseMap.getRegion(null, x, z, xSize, xSize, 0.25, 0.25, 0.5882352941176471D);
 
         for (int xx = 0; xx < xSize; xx++) {
             for (int zz = 0; zz < zSize; zz++) {
@@ -94,8 +94,8 @@ public class BiomeProviderB173
             temperatures = new double[xSize * zSize];
         }
 
-        this.temperatureMap.getValue(temperatures, x, z, xSize, xSize, 0.025, 0.025, 0.25);
-        final double[] noises = this.noiseMap.getValue(null, x, z, xSize, zSize, 0.25, 0.25, 0.5882352941176471D);
+        this.temperatureMap.getRegion(temperatures, x, z, xSize, xSize, 0.025, 0.025, 0.25);
+        final double[] noises = this.noiseMap.getRegion(null, x, z, xSize, zSize, 0.25, 0.25, 0.5882352941176471D);
 
         int i = 0;
         for (int xx = 0; xx < xSize; xx++) {
@@ -126,7 +126,7 @@ public class BiomeProviderB173
             humidities = new double[xSize * zSize];
         }
 
-        return this.downfallMap.getValue(humidities, x, z, xSize, zSize, 0.05, 0.05, 0.5);
+        return this.downfallMap.getRegion(humidities, x, z, xSize, zSize, 0.05, 0.05, 0.5);
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/world/biome/provider/BiomeProviderNether.java b/game/core/src/main/java/net/minecraft/core/world/biome/provider/BiomeProviderNether.java
index 9635a88d9..22e0dcc4a 100644
--- a/game/core/src/main/java/net/minecraft/core/world/biome/provider/BiomeProviderNether.java
+++ b/game/core/src/main/java/net/minecraft/core/world/biome/provider/BiomeProviderNether.java
@@ -90,8 +90,8 @@ public final class BiomeProviderNether
     }
 
     public double getTemperature(double x, double z) {
-        double[] tnResult = temperatureNoise.getValue(null, x, z, 1, 1, temperatureXScale, temperatureZScale, temperatureExponent);
-        double[] fnResult = fuzzinessNoise.getValue(null, x, z, 1, 1, fuzzinessXScale, fuzzinessZScale, fuzzinessExponent);
+        double[] tnResult = temperatureNoise.getRegion(null, x, z, 1, 1, temperatureXScale, temperatureZScale, temperatureExponent);
+        double[] fnResult = fuzzinessNoise.getRegion(null, x, z, 1, 1, fuzzinessXScale, fuzzinessZScale, fuzzinessExponent);
 
         double fuzziness = fnResult[0] * 1.1 + 0.5;
 
@@ -118,8 +118,8 @@ public final class BiomeProviderNether
             temperatures = new double[xSize * zSize];
         }
 
-        double[] tnResult = temperatureNoise.getValue(null, x, z, xSize, zSize, temperatureXScale, temperatureZScale, temperatureExponent);
-        double[] fnResult = fuzzinessNoise.getValue(null, x, z, xSize, zSize, fuzzinessXScale, fuzzinessZScale, fuzzinessExponent);
+        double[] tnResult = temperatureNoise.getRegion(null, x, z, xSize, zSize, temperatureXScale, temperatureZScale, temperatureExponent);
+        double[] fnResult = fuzzinessNoise.getRegion(null, x, z, xSize, zSize, fuzzinessXScale, fuzzinessZScale, fuzzinessExponent);
 
         for (int dx = 0; dx < xSize; dx++)
         {
diff --git a/game/core/src/main/java/net/minecraft/core/world/biome/provider/BiomeProviderOverworld.java b/game/core/src/main/java/net/minecraft/core/world/biome/provider/BiomeProviderOverworld.java
index 8affa5997..01403dfc3 100644
--- a/game/core/src/main/java/net/minecraft/core/world/biome/provider/BiomeProviderOverworld.java
+++ b/game/core/src/main/java/net/minecraft/core/world/biome/provider/BiomeProviderOverworld.java
@@ -132,8 +132,8 @@ public final class BiomeProviderOverworld
             temperatures = new double[xSize * zSize];
         }
 
-        double[] tnResult = temperatureNoise.getValue(null, x, z, xSize, zSize, temperatureXScale, temperatureZScale, temperatureExponent);
-        double[] fnResult = fuzzinessNoise.getValue(null, x, z, xSize, zSize, fuzzinessXScale, fuzzinessZScale, fuzzinessExponent);
+        double[] tnResult = temperatureNoise.getRegion(null, x, z, xSize, zSize, temperatureXScale, temperatureZScale, temperatureExponent);
+        double[] fnResult = fuzzinessNoise.getRegion(null, x, z, xSize, zSize, fuzzinessXScale, fuzzinessZScale, fuzzinessExponent);
 
         for (int dx = 0; dx < xSize; dx++)
         {
@@ -169,8 +169,8 @@ public final class BiomeProviderOverworld
             humidities = new double[xSize * zSize];
         }
 
-        double[] hnResult = humidityNoise.getValue(null, x, z, xSize, zSize, humidityXScale, humidityZScale, humidityExponent);
-        double[] fnResult = fuzzinessNoise.getValue(null, x, z, xSize, zSize, fuzzinessXScale, fuzzinessZScale, fuzzinessExponent);
+        double[] hnResult = humidityNoise.getRegion(null, x, z, xSize, zSize, humidityXScale, humidityZScale, humidityExponent);
+        double[] fnResult = fuzzinessNoise.getRegion(null, x, z, xSize, zSize, fuzzinessXScale, fuzzinessZScale, fuzzinessExponent);
 
         for (int dx = 0; dx < xSize; dx++)
         {
@@ -205,8 +205,8 @@ public final class BiomeProviderOverworld
             varieties = new double[xSize * zSize];
         }
 
-        double[] vnResult = varietyNoise.getValue(null, x, z, xSize, zSize, varietyXScale, varietyZScale, varietyExponent);
-        double[] fnResult = fuzzinessNoise.getValue(null, x, z, xSize, zSize, fuzzinessXScale, fuzzinessZScale, fuzzinessExponent);
+        double[] vnResult = varietyNoise.getRegion(null, x, z, xSize, zSize, varietyXScale, varietyZScale, varietyExponent);
+        double[] fnResult = fuzzinessNoise.getRegion(null, x, z, xSize, zSize, fuzzinessXScale, fuzzinessZScale, fuzzinessExponent);
 
         for (int dx = 0; dx < xSize; dx++)
         {
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/IceFloeLargeFeature.java b/game/core/src/main/java/net/minecraft/core/world/generate/IceFloeLargeFeature.java
index db184f2c9..aa23ce91f 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/IceFloeLargeFeature.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/IceFloeLargeFeature.java
@@ -49,7 +49,7 @@ public class IceFloeLargeFeature
                     vec.y = (baseChunkZ + ((float) z / (float) Chunk.CHUNK_SIZE_Z)) * worleyScale;
                     WorleyNoise.getWorleyDistance2d(vec, worley);
                     final float lineScale = 10.0f;
-                    final float lineWidth = (float) (this.perlinNoise.get((baseChunkX * Chunk.CHUNK_SIZE_X + x) / lineScale, (baseChunkZ * Chunk.CHUNK_SIZE_Z + z) / lineScale) / 2.0 + 0.5);
+                    final float lineWidth = (float) (this.perlinNoise.getValue((baseChunkX * Chunk.CHUNK_SIZE_X + x) / lineScale, (baseChunkZ * Chunk.CHUNK_SIZE_Z + z) / lineScale) / 2.0 + 0.5);
                     if (MathHelper.unsignedMod(worley.index, 15) != 0) {
                         if (worley.distance > 0.9f + lineWidth * 0.05f) {
                             continue;
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/classic/ChunkGeneratorClassic.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/classic/ChunkGeneratorClassic.java
index 1beacac78..13650edd3 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/classic/ChunkGeneratorClassic.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/classic/ChunkGeneratorClassic.java
@@ -10,6 +10,7 @@ import net.minecraft.core.world.generate.chunk.perlin.SurfaceGenerator;
 import net.minecraft.core.world.generate.chunk.perlin.overworld.retro.ChunkDecoratorOverworldRetro;
 import net.minecraft.core.world.generate.chunk.perlin.overworld.retro.SurfaceGeneratorOverworldRetro;
 import net.minecraft.core.world.noise.CombinedPerlinNoise;
+import net.minecraft.core.world.noise.LegacyNoiseType;
 import net.minecraft.core.world.noise.PerlinNoise;
 import org.jetbrains.annotations.NotNull;
 
@@ -29,13 +30,13 @@ public class ChunkGeneratorClassic
         super(world, new ChunkDecoratorOverworldRetro(world));
         long seed = world.getRandomSeed();
 
-        this.combinedA = new CombinedPerlinNoise(new PerlinNoise(seed, 8, 0), new PerlinNoise(seed, 8, 8));
-        this.combinedB = new CombinedPerlinNoise(new PerlinNoise(seed, 8, 16), new PerlinNoise(seed, 8, 24));
-        this.combinedC = new CombinedPerlinNoise(new PerlinNoise(seed, 8, 32), new PerlinNoise(seed, 8, 40));
-        this.combinedD = new CombinedPerlinNoise(new PerlinNoise(seed, 8, 48), new PerlinNoise(seed, 8, 56));
+        this.combinedA = new CombinedPerlinNoise(new PerlinNoise(seed, 8, 0, LegacyNoiseType.ALPHA), new PerlinNoise(seed, 8, 8, LegacyNoiseType.ALPHA));
+        this.combinedB = new CombinedPerlinNoise(new PerlinNoise(seed, 8, 16, LegacyNoiseType.ALPHA), new PerlinNoise(seed, 8, 24, LegacyNoiseType.ALPHA));
+        this.combinedC = new CombinedPerlinNoise(new PerlinNoise(seed, 8, 32, LegacyNoiseType.ALPHA), new PerlinNoise(seed, 8, 40, LegacyNoiseType.ALPHA));
+        this.combinedD = new CombinedPerlinNoise(new PerlinNoise(seed, 8, 48, LegacyNoiseType.ALPHA), new PerlinNoise(seed, 8, 56, LegacyNoiseType.ALPHA));
 
-        this.octavesA = new PerlinNoise(seed, 6, 64);
-        this.octavesB = new PerlinNoise(seed, 8, 70);
+        this.octavesA = new PerlinNoise(seed, 6, 64, LegacyNoiseType.ALPHA);
+        this.octavesB = new PerlinNoise(seed, 8, 70, LegacyNoiseType.ALPHA);
 
         this.sg = new SurfaceGeneratorOverworldRetro(world);
         this.cg = new CavesLargeFeature();
@@ -57,7 +58,7 @@ public class ChunkGeneratorClassic
             for (int z = 0; z < Chunk.CHUNK_SIZE_Z; z++) {
                 final double noiseA = this.combinedA.get((chunkX * Chunk.CHUNK_SIZE_X + x) * mod, (chunkZ * Chunk.CHUNK_SIZE_Z + z) * mod) / 6.0D + -4;
                 double noiseB = this.combinedB.get((chunkX * Chunk.CHUNK_SIZE_X + x) * mod, (chunkZ * Chunk.CHUNK_SIZE_Z + z) * mod) / 5.0D + 10.0D + -4;
-                if (this.octavesA.get(chunkX * Chunk.CHUNK_SIZE_X + x, chunkZ * Chunk.CHUNK_SIZE_Z + z) / 8.0D > 0.0D) {
+                if (this.octavesA.getValue(chunkX * Chunk.CHUNK_SIZE_X + x, chunkZ * Chunk.CHUNK_SIZE_Z + z) / 8.0D > 0.0D) {
                     noiseB = noiseA;
                 }
 
@@ -86,7 +87,7 @@ public class ChunkGeneratorClassic
         // Soiling..
         for (int x = 0; x < Chunk.CHUNK_SIZE_X; x++) {
             for (int z = 0; z < Chunk.CHUNK_SIZE_Z; z++) {
-                final int val = (int) (this.octavesB.get(chunkX * Chunk.CHUNK_SIZE_X + x, chunkZ * Chunk.CHUNK_SIZE_Z + z) / 24.0D) - 4;
+                final int val = (int) (this.octavesB.getValue(chunkX * Chunk.CHUNK_SIZE_X + x, chunkZ * Chunk.CHUNK_SIZE_Z + z) / 24.0D) - 4;
                 int newHeight;
                 final int val2 = (newHeight = newHeightMap[x + z * Chunk.CHUNK_SIZE_X] + this.world.getWorldType().getOceanY()) + val;
                 newHeightMap[x + z * Chunk.CHUNK_SIZE_X] = Math.max(newHeight, val2);
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/indev/LevelGenerator.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/indev/LevelGenerator.java
index a7bd40a6b..b217a406e 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/indev/LevelGenerator.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/indev/LevelGenerator.java
@@ -5,7 +5,8 @@ import net.minecraft.core.world.World;
 import net.minecraft.core.world.chunk.Chunk;
 import net.minecraft.core.world.generate.chunk.ChunkGeneratorResult;
 import net.minecraft.core.world.noise.CombinedPerlinNoise;
-import net.minecraft.core.world.noise.RetroPerlinNoise;
+import net.minecraft.core.world.noise.LegacyNoiseType;
+import net.minecraft.core.world.noise.PerlinNoise;
 import org.jetbrains.annotations.NotNull;
 
 public final class LevelGenerator {
@@ -44,10 +45,10 @@ public final class LevelGenerator {
             } else {
                 // Raising phase
 //                System.out.println("Raising..");
-                CombinedPerlinNoise heightNoiseGeneratorA = new CombinedPerlinNoise(new RetroPerlinNoise(seed, 8, 0), new RetroPerlinNoise(seed, 8, 8));
-                CombinedPerlinNoise heightNoiseGeneratorB = new CombinedPerlinNoise(new RetroPerlinNoise(seed, 8, 16), new RetroPerlinNoise(seed, 8, 24));
-                RetroPerlinNoise heightNoiseGeneratorSelector = new RetroPerlinNoise(seed, 6, 32);
-                RetroPerlinNoise edgeNoiseGenerator = new RetroPerlinNoise(seed, 2, 38);
+                CombinedPerlinNoise heightNoiseGeneratorA = new CombinedPerlinNoise(new PerlinNoise(seed, 8, 0, LegacyNoiseType.ALPHA), new PerlinNoise(seed, 8, 8, LegacyNoiseType.ALPHA));
+                CombinedPerlinNoise heightNoiseGeneratorB = new CombinedPerlinNoise(new PerlinNoise(seed, 8, 16, LegacyNoiseType.ALPHA), new PerlinNoise(seed, 8, 24, LegacyNoiseType.ALPHA));
+                PerlinNoise heightNoiseGeneratorSelector = new PerlinNoise(seed, 6, 32, LegacyNoiseType.ALPHA);
+                PerlinNoise edgeNoiseGenerator = new PerlinNoise(seed, 2, 38, LegacyNoiseType.ALPHA);
 
                 for (int x = 0; x < Chunk.CHUNK_SIZE_X; x++) {
                     double xDistanceFromCenter = Math.abs(((double) (x + xOffset) / ((double) this.sizeX - 1.0) - 0.5) * 2.0);
@@ -58,7 +59,7 @@ public final class LevelGenerator {
                         // Generate noise to use for height
                         double heightNoiseA = heightNoiseGeneratorA.get((float) (x + xOffset) * 1.3F, (float) (z + zOffset) * 1.3F) / 6.0 + -4.0;
                         double heightNoiseB = heightNoiseGeneratorB.get((float) (x + xOffset) * 1.3F, (float) (z + zOffset) * 1.3F) / 5.0 + 10.0 + -4.0;
-                        double heightNoiseToUse = heightNoiseGeneratorSelector.get(x + xOffset, z + zOffset) / 8.0;
+                        double heightNoiseToUse = heightNoiseGeneratorSelector.getValue(x + xOffset, z + zOffset) / 8.0;
                         if (heightNoiseToUse > 0.0) {
                             heightNoiseB = heightNoiseA;
                         }
@@ -67,7 +68,7 @@ public final class LevelGenerator {
                         if (this.worldType == IndevWorldType.ISLAND) {
                             // Use the distance value to create the "hill" effect island terrain has
                             double distanceFromCenter = Math.sqrt(xDistanceFromCenter * xDistanceFromCenter + zDistanceFromCenter * zDistanceFromCenter) * (double) 1.2F;
-                            double edgeNoise = edgeNoiseGenerator.get((float) (x + xOffset) * 0.05F, (float) (z + zOffset) * 0.05F) / 4.0 + 1.0;
+                            double edgeNoise = edgeNoiseGenerator.getValue((float) (x + xOffset) * 0.05F, (float) (z + zOffset) * 0.05F) / 4.0 + 1.0;
                             distanceFromCenter = Math.min(distanceFromCenter, edgeNoise);
                             distanceFromCenter = Math.max(distanceFromCenter,
                                 Math.max(xDistanceFromCenter, zDistanceFromCenter));
@@ -96,8 +97,8 @@ public final class LevelGenerator {
 
                 // Eroding phase
 //                System.out.println("Eroding..");
-                CombinedPerlinNoise erosionPowerNoiseGenerator = new CombinedPerlinNoise(new RetroPerlinNoise(seed, 8, 40), new RetroPerlinNoise(seed, 8, 48));
-                CombinedPerlinNoise erosionAmountNoiseGenerator = new CombinedPerlinNoise(new RetroPerlinNoise(seed, 8, 56), new RetroPerlinNoise(seed, 8, 64));
+                CombinedPerlinNoise erosionPowerNoiseGenerator = new CombinedPerlinNoise(new PerlinNoise(seed, 8, 40, LegacyNoiseType.ALPHA), new PerlinNoise(seed, 8, 48, LegacyNoiseType.ALPHA));
+                CombinedPerlinNoise erosionAmountNoiseGenerator = new CombinedPerlinNoise(new PerlinNoise(seed, 8, 56, LegacyNoiseType.ALPHA), new PerlinNoise(seed, 8, 64, LegacyNoiseType.ALPHA));
 
                 for (int x = 0; x < Chunk.CHUNK_SIZE_X; x++) {
                     for (int z = 0; z < Chunk.CHUNK_SIZE_Z; z++) {
@@ -115,8 +116,8 @@ public final class LevelGenerator {
 
             // Soiling phase
 //            System.out.println("Soiling..");
-            RetroPerlinNoise soilNoiseGenerator = new RetroPerlinNoise(seed, 8, 72);
-            RetroPerlinNoise floatingLayerNoiseGenerator = new RetroPerlinNoise(seed, 8, 80);
+            PerlinNoise soilNoiseGenerator = new PerlinNoise(seed, 8, 72, LegacyNoiseType.ALPHA);
+            PerlinNoise floatingLayerNoiseGenerator = new PerlinNoise(seed, 8, 80, LegacyNoiseType.ALPHA);
 
             for (int x = 0; x < Chunk.CHUNK_SIZE_X; x++) {
                 double xDistanceFromCenter = Math.abs(((double) (x + xOffset) / ((double) this.sizeX - 1.0) - 0.5) * 2.0);
@@ -127,7 +128,7 @@ public final class LevelGenerator {
                     distanceFromCenter = distanceFromCenter * distanceFromCenter * distanceFromCenter;
 
                     // Determine the height of the soil layer
-                    int soilNoise = (int) (soilNoiseGenerator.get(x + xOffset, z + zOffset) / 24.0) - 4;
+                    int soilNoise = (int) (soilNoiseGenerator.getValue(x + xOffset, z + zOffset) / 24.0) - 4;
                     int height = heightMap[x + z * Chunk.CHUNK_SIZE_X] + waterLevel;
                     int soilHeight = height + soilNoise;
 
@@ -141,7 +142,7 @@ public final class LevelGenerator {
                     }
 
                     // Determine the minimum height of the layer (only applicable in floating island generation)
-                    double floatingLayerNoise = floatingLayerNoiseGenerator.get((double) (x + xOffset) * 2.3, (double) (z + zOffset) * 2.3) / 24.0;
+                    double floatingLayerNoise = floatingLayerNoiseGenerator.getValue((double) (x + xOffset) * 2.3, (double) (z + zOffset) * 2.3) / 24.0;
                     int floatingLayerMinY = (int) (Math.sqrt(Math.abs(floatingLayerNoise)) * Math.signum(floatingLayerNoise) * 20.0) + waterLevel;
                     floatingLayerMinY = (int) ((double) floatingLayerMinY * (1.0 - distanceFromCenter) + distanceFromCenter * (double) this.sizeY);
                     if (floatingLayerMinY > waterLevel) {
@@ -167,8 +168,8 @@ public final class LevelGenerator {
 
             // Growing phase - no idea why it's called this because it's very clearly generating beaches
 //            System.out.println("Growing..");
-            RetroPerlinNoise sandNoiseGenerator = new RetroPerlinNoise(seed, 8, 88);
-            RetroPerlinNoise gravelNoiseGenerator = new RetroPerlinNoise(seed, 8, 96);
+            PerlinNoise sandNoiseGenerator = new PerlinNoise(seed, 8, 88, LegacyNoiseType.ALPHA);
+            PerlinNoise gravelNoiseGenerator = new PerlinNoise(seed, 8, 96, LegacyNoiseType.ALPHA);
             int beachHeight = waterLevel - 1;
             if (this.worldTheme == IndevWorldTheme.PARADISE) {
                 beachHeight += 2;
@@ -176,19 +177,19 @@ public final class LevelGenerator {
 
             for (int x = 0; x < Chunk.CHUNK_SIZE_X; x++) {
                 for (int z = 0; z < Chunk.CHUNK_SIZE_Z; z++) {
-                    boolean isSand = sandNoiseGenerator.get(x + xOffset, z + zOffset) > 8.0;
-                    boolean isGravel = gravelNoiseGenerator.get(x + xOffset, z + zOffset) > 12.0;
+                    boolean isSand = sandNoiseGenerator.getValue(x + xOffset, z + zOffset) > 8.0;
+                    boolean isGravel = gravelNoiseGenerator.getValue(x + xOffset, z + zOffset) > 12.0;
 
                     if (this.worldType == IndevWorldType.ISLAND) {
-                        isSand = sandNoiseGenerator.get(x + xOffset, z + zOffset) > -8.0;
+                        isSand = sandNoiseGenerator.getValue(x + xOffset, z + zOffset) > -8.0;
                     }
 
                     if (this.worldTheme == IndevWorldTheme.PARADISE) {
-                        isSand = sandNoiseGenerator.get(x + xOffset, z + zOffset) > -32.0;
+                        isSand = sandNoiseGenerator.getValue(x + xOffset, z + zOffset) > -32.0;
                     }
 
                     if (this.worldTheme == IndevWorldTheme.HELL || this.worldTheme == IndevWorldTheme.WOODS) {
-                        isSand = sandNoiseGenerator.get(x + xOffset, z + zOffset) > -8.0;
+                        isSand = sandNoiseGenerator.getValue(x + xOffset, z + zOffset) > -8.0;
                     }
 
                     int height = heightMap[x + z * Chunk.CHUNK_SIZE_X];
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/drift/DensityGeneratorDrift.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/drift/DensityGeneratorDrift.java
index 38389b6ff..afb601249 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/drift/DensityGeneratorDrift.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/drift/DensityGeneratorDrift.java
@@ -62,9 +62,9 @@ public class DensityGeneratorDrift
         // uses temp and humidity to alter terrain shape.
 //        double[] scaleArray = scaleNoise.get(null, x, z, xSize, zSize, scaleNoiseScaleX, scaleNoiseScaleZ);
 //        double[] depthArray = depthNoise.get(null, x, z, xSize, zSize, depthNoiseScaleX, depthNoiseScaleZ);
-        double[] mainNoiseArray = this.mainNoise.get(null, x, y, z, xSize, ySize, zSize, coordScale / mainNoiseScaleX, heightScale / mainNoiseScaleY, coordScale / mainNoiseScaleZ);
-        double[] minLimitArray = this.minLimitNoise.get(null, x, y, z, xSize, ySize, zSize, coordScale, heightScale, coordScale);
-        double[] maxLimitArray = this.maxLimitNoise.get(null, x, y, z, xSize, ySize, zSize, coordScale, heightScale, coordScale);
+        double[] mainNoiseArray = this.mainNoise.getRegion(null, x, y, z, xSize, ySize, zSize, coordScale / mainNoiseScaleX, heightScale / mainNoiseScaleY, coordScale / mainNoiseScaleZ);
+        double[] minLimitArray = this.minLimitNoise.getRegion(null, x, y, z, xSize, ySize, zSize, coordScale, heightScale, coordScale);
+        double[] maxLimitArray = this.maxLimitNoise.getRegion(null, x, y, z, xSize, ySize, zSize, coordScale, heightScale, coordScale);
         int mainIndex = 0;
 //        int depthScaleIndex = 0;
         int xSizeScale = 16 / xSize;
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 bf6ddec81..bbe327f77 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
@@ -42,7 +42,7 @@ public class ChunkDecoratorNether
         if (biome == Biomes.NETHER_CRYSTAL_FOREST) {
             double noiseScale = 0.5;
 
-            int density = (int) ((this.crystalDensityNoise.get(x * noiseScale, z * noiseScale) - 6D + 36D) / 6D);
+            int density = (int) ((this.crystalDensityNoise.getValue(x * noiseScale, z * noiseScale) - 6D + 36D) / 6D);
 
             for (int i = 0; i < density - 5; i++) {
                 int xf = x + rand.nextInt(16) + 8;
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/DensityGeneratorNether.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/DensityGeneratorNether.java
index 28e430e6d..c43c0e0e9 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/DensityGeneratorNether.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/DensityGeneratorNether.java
@@ -147,9 +147,9 @@ public class DensityGeneratorNether
         final double upperLimitScale = 512.0;
         final double lowerLimitScale = 512.0;
 
-        double[] mainNoiseArray = this.mainNoise.get(null, x, y, z, xSize, ySize, zSize, coordScale / mainNoiseScaleX, heightScale / mainNoiseScaleY, coordScale / mainNoiseScaleZ);
-        double[] minLimitArray = this.minLimitNoise.get(null, x, y, z, xSize, ySize, zSize, coordScale, heightScale, coordScale);
-        double[] maxLimitArray = this.maxLimitNoise.get(null, x, y, z, xSize, ySize, zSize, coordScale, heightScale, coordScale);
+        double[] mainNoiseArray = this.mainNoise.getRegion(null, x, y, z, xSize, ySize, zSize, coordScale / mainNoiseScaleX, heightScale / mainNoiseScaleY, coordScale / mainNoiseScaleZ);
+        double[] minLimitArray = this.minLimitNoise.getRegion(null, x, y, z, xSize, ySize, zSize, coordScale, heightScale, coordScale);
+        double[] maxLimitArray = this.maxLimitNoise.getRegion(null, x, y, z, xSize, ySize, zSize, coordScale, heightScale, coordScale);
         int mainIndex = 0;
         double[] densityOffsetArray = new double[ySize];
         for (int dy = 0; dy < ySize; dy++) {
@@ -224,13 +224,13 @@ public class DensityGeneratorNether
 
         double ravineNoiseScale = 0.03D;
 
-        double[] scaleArray = this.scaleNoise.get(null, x, z, xSize, zSize, scaleNoiseScaleX, scaleNoiseScaleZ);
-        double[] depthArray = this.depthNoise.get(null, x, z, xSize, zSize, depthNoiseScaleX, depthNoiseScaleZ);
-        double[] mainNoiseArray = this.mainNoise.get(null, x, y, z, xSize, ySize, zSize, coordScale / mainNoiseScaleX, heightScale / mainNoiseScaleY, coordScale / mainNoiseScaleZ);
-        double[] minLimitArray = this.minLimitNoise.get(null, x, y, z, xSize, ySize, zSize, coordScale, heightScale, coordScale);
-        double[] maxLimitArray = this.maxLimitNoise.get(null, x, y, z, xSize, ySize, zSize, coordScale, heightScale, coordScale);
+        double[] scaleArray = this.scaleNoise.getRegion(null, x, z, xSize, zSize, scaleNoiseScaleX, scaleNoiseScaleZ);
+        double[] depthArray = this.depthNoise.getRegion(null, x, z, xSize, zSize, depthNoiseScaleX, depthNoiseScaleZ);
+        double[] mainNoiseArray = this.mainNoise.getRegion(null, x, y, z, xSize, ySize, zSize, coordScale / mainNoiseScaleX, heightScale / mainNoiseScaleY, coordScale / mainNoiseScaleZ);
+        double[] minLimitArray = this.minLimitNoise.getRegion(null, x, y, z, xSize, ySize, zSize, coordScale, heightScale, coordScale);
+        double[] maxLimitArray = this.maxLimitNoise.getRegion(null, x, y, z, xSize, ySize, zSize, coordScale, heightScale, coordScale);
 
-        double[] ravineNoise = this.ravineNoise2.getValue(null, x, z, xSize, zSize, ravineNoiseScale, ravineNoiseScale, 3.0D, 3.0D);
+        double[] ravineNoise = this.ravineNoise2.getRegion(null, x, z, xSize, zSize, ravineNoiseScale, ravineNoiseScale, 3.0D, 3.0D);
 //        double[] ravineMod = ravineNoise2.getValue(null, x, z, xSize, zSize, ravineNoiseScale, ravineNoiseScale, 0.25D, 0.6D);
 
         int mainIndex = 0;
@@ -351,12 +351,12 @@ public class DensityGeneratorNether
 
         final double noiseScale = 0.02;
 
-        double[] scaleArray = this.scaleNoise.get(null, x, z, xSize, zSize, scaleNoiseScaleX, scaleNoiseScaleZ);
-        double[] depthArray = this.depthNoise.get(null, x, z, xSize, zSize, depthNoiseScaleX, depthNoiseScaleZ);
-        double[] mainNoiseArray = this.mainNoise.get(null, x, y, z, xSize, ySize, zSize, coordScale / mainNoiseScaleX, heightScale / mainNoiseScaleY, coordScale / mainNoiseScaleZ);
-        double[] minLimitArray = this.minLimitNoise.get(null, x, y, z, xSize, ySize, zSize, coordScale, heightScale, coordScale);
-        double[] maxLimitArray = this.maxLimitNoise.get(null, x, y, z, xSize, ySize, zSize, coordScale, heightScale, coordScale);
-        double[] islandNoiseArray = this.islandNoise.getValue(null, x, z, xSize, zSize, noiseScale, noiseScale, 2, 2);
+        double[] scaleArray = this.scaleNoise.getRegion(null, x, z, xSize, zSize, scaleNoiseScaleX, scaleNoiseScaleZ);
+        double[] depthArray = this.depthNoise.getRegion(null, x, z, xSize, zSize, depthNoiseScaleX, depthNoiseScaleZ);
+        double[] mainNoiseArray = this.mainNoise.getRegion(null, x, y, z, xSize, ySize, zSize, coordScale / mainNoiseScaleX, heightScale / mainNoiseScaleY, coordScale / mainNoiseScaleZ);
+        double[] minLimitArray = this.minLimitNoise.getRegion(null, x, y, z, xSize, ySize, zSize, coordScale, heightScale, coordScale);
+        double[] maxLimitArray = this.maxLimitNoise.getRegion(null, x, y, z, xSize, ySize, zSize, coordScale, heightScale, coordScale);
+        double[] islandNoiseArray = this.islandNoise.getRegion(null, x, z, xSize, zSize, noiseScale, noiseScale, 2, 2);
 
         int mainIndex = 0;
 
@@ -465,11 +465,11 @@ public class DensityGeneratorNether
         final double upperLimitScale = 512;
         final double lowerLimitScale = 512;
 
-        double[] scaleArray = this.scaleNoise.get(null, x, z, xSize, zSize, scaleNoiseScaleX, scaleNoiseScaleZ);
-        double[] depthArray = this.depthNoise.get(null, x, z, xSize, zSize, depthNoiseScaleX, depthNoiseScaleZ);
-        double[] mainNoiseArray = this.mainNoise.get(null, x, y, z, xSize, ySize, zSize, coordScale / mainNoiseScaleX, heightScale / mainNoiseScaleY, coordScale / mainNoiseScaleZ);
-        double[] minLimitArray = this.minLimitNoise.get(null, x, y, z, xSize, ySize, zSize, coordScale, heightScale, coordScale);
-        double[] maxLimitArray = this.maxLimitNoise.get(null, x, y, z, xSize, ySize, zSize, coordScale, heightScale, coordScale);
+        double[] scaleArray = this.scaleNoise.getRegion(null, x, z, xSize, zSize, scaleNoiseScaleX, scaleNoiseScaleZ);
+        double[] depthArray = this.depthNoise.getRegion(null, x, z, xSize, zSize, depthNoiseScaleX, depthNoiseScaleZ);
+        double[] mainNoiseArray = this.mainNoise.getRegion(null, x, y, z, xSize, ySize, zSize, coordScale / mainNoiseScaleX, heightScale / mainNoiseScaleY, coordScale / mainNoiseScaleZ);
+        double[] minLimitArray = this.minLimitNoise.getRegion(null, x, y, z, xSize, ySize, zSize, coordScale, heightScale, coordScale);
+        double[] maxLimitArray = this.maxLimitNoise.getRegion(null, x, y, z, xSize, ySize, zSize, coordScale, heightScale, coordScale);
         int mainIndex = 0;
 
         int depthScaleIndex = 0;
@@ -571,13 +571,13 @@ public class DensityGeneratorNether
         final double upperLimitScale = 512;
         final double lowerLimitScale = 512;
 
-        double[] scaleArray = this.scaleNoise.get(null, x, z, xSize, zSize, scaleNoiseScaleX, scaleNoiseScaleZ);
-        double[] depthArray = this.depthNoise.get(null, x, z, xSize, zSize, depthNoiseScaleX, depthNoiseScaleZ);
-        double[] mainNoiseArray = this.mainNoise.get(null, x, y, z, xSize, ySize, zSize, coordScale / mainNoiseScaleX, heightScale / mainNoiseScaleY, coordScale / mainNoiseScaleZ);
-        double[] minLimitArray = this.minLimitNoise.get(null, x, y, z, xSize, ySize, zSize, coordScale, heightScale, coordScale);
-        double[] maxLimitArray = this.maxLimitNoise.get(null, x, y, z, xSize, ySize, zSize, coordScale, heightScale, coordScale);
-        double[] poolOverArray = this.poolNoiseOver.getValue(null, x, z, xSize, zSize, poolNoiseScale, poolNoiseScale, 1, 0.2);
-        double[] poolUnderArray = this.poolNoiseUnder.getValue(null, x, z, xSize, zSize, poolNoiseScale, poolNoiseScale, 0.01, 1);
+        double[] scaleArray = this.scaleNoise.getRegion(null, x, z, xSize, zSize, scaleNoiseScaleX, scaleNoiseScaleZ);
+        double[] depthArray = this.depthNoise.getRegion(null, x, z, xSize, zSize, depthNoiseScaleX, depthNoiseScaleZ);
+        double[] mainNoiseArray = this.mainNoise.getRegion(null, x, y, z, xSize, ySize, zSize, coordScale / mainNoiseScaleX, heightScale / mainNoiseScaleY, coordScale / mainNoiseScaleZ);
+        double[] minLimitArray = this.minLimitNoise.getRegion(null, x, y, z, xSize, ySize, zSize, coordScale, heightScale, coordScale);
+        double[] maxLimitArray = this.maxLimitNoise.getRegion(null, x, y, z, xSize, ySize, zSize, coordScale, heightScale, coordScale);
+        double[] poolOverArray = this.poolNoiseOver.getRegion(null, x, z, xSize, zSize, poolNoiseScale, poolNoiseScale, 1, 0.2);
+        double[] poolUnderArray = this.poolNoiseUnder.getRegion(null, x, z, xSize, zSize, poolNoiseScale, poolNoiseScale, 0.01, 1);
         int mainIndex = 0;
 
         int depthScaleIndex = 0;
@@ -686,11 +686,11 @@ public class DensityGeneratorNether
         final double upperLimitScale = 512;
         final double lowerLimitScale = 512;
 
-        double[] scaleArray = this.scaleNoise.get(null, x, z, xSize, zSize, scaleNoiseScaleX, scaleNoiseScaleZ);
-        double[] depthArray = this.depthNoise.get(null, x, z, xSize, zSize, depthNoiseScaleX, depthNoiseScaleZ);
-        double[] mainNoiseArray = this.mainNoise.get(null, x, y, z, xSize, ySize, zSize, coordScale / mainNoiseScaleX, heightScale / mainNoiseScaleY, coordScale / mainNoiseScaleZ);
-        double[] minLimitArray = this.minLimitNoise.get(null, x, y, z, xSize, ySize, zSize, coordScale, heightScale, coordScale);
-        double[] maxLimitArray = this.maxLimitNoise.get(null, x, y, z, xSize, ySize, zSize, coordScale, heightScale, coordScale);
+        double[] scaleArray = this.scaleNoise.getRegion(null, x, z, xSize, zSize, scaleNoiseScaleX, scaleNoiseScaleZ);
+        double[] depthArray = this.depthNoise.getRegion(null, x, z, xSize, zSize, depthNoiseScaleX, depthNoiseScaleZ);
+        double[] mainNoiseArray = this.mainNoise.getRegion(null, x, y, z, xSize, ySize, zSize, coordScale / mainNoiseScaleX, heightScale / mainNoiseScaleY, coordScale / mainNoiseScaleZ);
+        double[] minLimitArray = this.minLimitNoise.getRegion(null, x, y, z, xSize, ySize, zSize, coordScale, heightScale, coordScale);
+        double[] maxLimitArray = this.maxLimitNoise.getRegion(null, x, y, z, xSize, ySize, zSize, coordScale, heightScale, coordScale);
         int mainIndex = 0;
 
         int depthScaleIndex = 0;
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 4829802d3..945bdef32 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
@@ -40,9 +40,9 @@ public class SurfaceGeneratorNether
         Random rand = new Random((long) chunkX * 0x4F9939F508L + (long) chunkZ * 0x1EF1565BD5L);
 
         double beachScale = 0.03125D;
-        double[] sandBeachNoise = this.beachNoise.get(null, chunkX * 16, chunkZ * 16, 0.0D, 16, 16, 1, beachScale, beachScale, 1.0D);
-        double[] gravelBeachNoise = this.beachNoise.get(null, chunkX * 16, 109.0134D, chunkZ * 16, 16, 1, 16, beachScale, 1.0D, beachScale);
-        double[] soilThicknessNoise = this.soilNoise.get(null, chunkX * 16, chunkZ * 16, 0.0D, 16, 16, 1, beachScale * 2D, beachScale * 2D, beachScale * 2D);
+        double[] sandBeachNoise = this.beachNoise.getRegion(null, chunkX * 16, chunkZ * 16, 0.0D, 16, 16, 1, beachScale, beachScale, 1.0D);
+        double[] gravelBeachNoise = this.beachNoise.getRegion(null, chunkX * 16, 109.0134D, chunkZ * 16, 16, 1, 16, beachScale, 1.0D, beachScale);
+        double[] soilThicknessNoise = this.soilNoise.getRegion(null, chunkX * 16, chunkZ * 16, 0.0D, 16, 16, 1, beachScale * 2D, beachScale * 2D, beachScale * 2D);
         for (int z = 0; z < 16; z++) {
             for (int x = 0; x < 16; x++) {
                 boolean generateSandBeach = sandBeachNoise[z + x * 16] + rand.nextDouble() * 0.2D > 0.0D;
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/TerrainGeneratorNether.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/TerrainGeneratorNether.java
index ce8e73a70..559c013c1 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/TerrainGeneratorNether.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/TerrainGeneratorNether.java
@@ -73,7 +73,7 @@ public class TerrainGeneratorNether
         if (this.lastChunkX != chunk.pos.x || this.lastChunkZ != chunk.pos.z) {
             this.lastChunkX = chunk.pos.x;
             this.lastChunkZ = chunk.pos.z;
-            this.noise.get(this.cache, chunk.pos.x * Chunk.CHUNK_SIZE_X, 0, chunk.pos.z * Chunk.CHUNK_SIZE_Z, Chunk.CHUNK_SIZE_X, Chunk.CHUNK_SECTIONS * ChunkSection.SECTION_SIZE_Y, Chunk.CHUNK_SIZE_Z, 0.2, 0.2, 0.2);
+            this.noise.getRegion(this.cache, chunk.pos.x * Chunk.CHUNK_SIZE_X, 0, chunk.pos.z * Chunk.CHUNK_SIZE_Z, Chunk.CHUNK_SIZE_X, Chunk.CHUNK_SECTIONS * ChunkSection.SECTION_SIZE_Y, Chunk.CHUNK_SIZE_Z, 0.2, 0.2, 0.2);
 
             float avg = 0;
             for (int i = 0; i < this.cache.length; i++) {
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 16fbdd278..8d2144ccd 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
@@ -13,13 +13,13 @@ import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.material.Materials;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.biome.Biomes;
+import net.minecraft.core.world.noise.PerlinNoise;
 import net.minecraft.core.world.type.WorldTypes;
 import net.minecraft.core.world.biome.Biome;
 import net.minecraft.core.world.biome.overworld.BiomeOutback;
 import net.minecraft.core.world.chunk.Chunk;
 import net.minecraft.core.world.generate.chunk.ChunkDecorator;
 import net.minecraft.core.world.generate.feature.*;
-import net.minecraft.core.world.noise.PerlinNoise;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.Random;
@@ -250,7 +250,7 @@ public class ChunkDecoratorOverworld
 
 
         double d = 0.5D;
-        int k4 = (int) ((this.treeDensityNoise.get((double) x * d, (double) z * d) / 8D + rand.nextDouble() * 4D + 4D) / 3D);
+        int k4 = (int) ((this.treeDensityNoise.getValue((double) x * d, (double) z * d) / 8D + rand.nextDouble() * 4D + 4D) / 3D);
         int treeDensity = 0;
         if (rand.nextInt(10) == 0) {
             treeDensity++;
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/DensityGeneratorOverworld.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/DensityGeneratorOverworld.java
index d3bd5f73c..74e17969a 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/DensityGeneratorOverworld.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/DensityGeneratorOverworld.java
@@ -4,7 +4,6 @@ import net.minecraft.core.world.World;
 import net.minecraft.core.world.type.WorldTypes;
 import net.minecraft.core.world.chunk.Chunk;
 import net.minecraft.core.world.generate.chunk.perlin.DensityGenerator;
-import net.minecraft.core.world.noise.BasePerlinNoise;
 import net.minecraft.core.world.noise.PerlinNoise;
 import org.jetbrains.annotations.NotNull;
 
@@ -12,17 +11,25 @@ public class DensityGeneratorOverworld
     implements DensityGenerator {
     private final @NotNull World world;
 
-    private final @NotNull BasePerlinNoise<?> minLimitNoise;
-    private final @NotNull BasePerlinNoise<?> maxLimitNoise;
-    private final @NotNull BasePerlinNoise<?> mainNoise;
-    private final @NotNull BasePerlinNoise<?> scaleNoise;
-    private final @NotNull BasePerlinNoise<?> depthNoise;
+    private final @NotNull PerlinNoise minLimitNoise;
+    private final @NotNull PerlinNoise maxLimitNoise;
+    private final @NotNull PerlinNoise mainNoise;
+    private final @NotNull PerlinNoise scaleNoise;
+    private final @NotNull PerlinNoise depthNoise;
 
     private final boolean generateRivers;
-    private final @NotNull BasePerlinNoise<?> smoothingRiverNoise;
-    private final @NotNull BasePerlinNoise<?> carvingRiverNoise;
-
-    protected DensityGeneratorOverworld(@NotNull World world, @NotNull BasePerlinNoise<?> minLimitNoise, @NotNull BasePerlinNoise<?> maxLimitNoise, @NotNull BasePerlinNoise<?> mainNoise, @NotNull BasePerlinNoise<?> scaleNoise, @NotNull BasePerlinNoise<?> depthNoise, boolean generateRivers) {
+    private final @NotNull PerlinNoise smoothingRiverNoise;
+    private final @NotNull PerlinNoise carvingRiverNoise;
+
+    protected DensityGeneratorOverworld(
+        @NotNull World world,
+        @NotNull PerlinNoise minLimitNoise,
+        @NotNull PerlinNoise maxLimitNoise,
+        @NotNull PerlinNoise mainNoise,
+        @NotNull PerlinNoise scaleNoise,
+        @NotNull PerlinNoise depthNoise,
+        boolean generateRivers
+    ) {
         this.world = world;
 
         this.minLimitNoise = minLimitNoise;
@@ -56,9 +63,9 @@ public class DensityGeneratorOverworld
 
         double riverLevel = 0d;
 
-        double[] largeSmoothing = this.smoothingRiverNoise.get(null, x, z, xSize, zSize, 1 / (1000d / xSize), 1 / (1000d / zSize));
-        double[] mediumSmoothing = this.smoothingRiverNoise.get(null, x, z, xSize, zSize, 1 / (50d / xSize), 1 / (50d / zSize));
-        double[] smallSmoothing = this.smoothingRiverNoise.get(null, x, z, xSize, zSize, 1 / (10d / xSize), 1 / (10d / zSize));
+        double[] largeSmoothing = this.smoothingRiverNoise.getRegion(null, x, z, xSize, zSize, 1 / (1000d / xSize), 1 / (1000d / zSize));
+        double[] mediumSmoothing = this.smoothingRiverNoise.getRegion(null, x, z, xSize, zSize, 1 / (50d / xSize), 1 / (50d / zSize));
+        double[] smallSmoothing = this.smoothingRiverNoise.getRegion(null, x, z, xSize, zSize, 1 / (10d / xSize), 1 / (10d / zSize));
 
         double[] riverRadiuses = new double[]{0.006, 0.024, 0.036};
         double[] riverMults = new double[]{20, 60, 60};
@@ -102,9 +109,9 @@ public class DensityGeneratorOverworld
 
         double riverLevel = 0d;
 
-        double[] largeCarving = this.carvingRiverNoise.get(null, x, z, xSize, zSize, 1 / (1000d / xSize), 1 / (1000d / zSize));
-        double[] mediumCarving = this.carvingRiverNoise.get(null, x, z, xSize, zSize, 1 / (50d / xSize), 1 / (50d / zSize));
-        double[] smallCarving = this.carvingRiverNoise.get(null, x, z, xSize, zSize, 1 / (10d / xSize), 1 / (10d / zSize));
+        double[] largeCarving = this.carvingRiverNoise.getRegion(null, x, z, xSize, zSize, 1 / (1000d / xSize), 1 / (1000d / zSize));
+        double[] mediumCarving = this.carvingRiverNoise.getRegion(null, x, z, xSize, zSize, 1 / (50d / xSize), 1 / (50d / zSize));
+        double[] smallCarving = this.carvingRiverNoise.getRegion(null, x, z, xSize, zSize, 1 / (10d / xSize), 1 / (10d / zSize));
 
         double[] riverRadiuses = new double[]{0.012, 0.018, 0.024};
         double[] riverMults = new double[]{20, 60, 60};
@@ -178,11 +185,11 @@ public class DensityGeneratorOverworld
         final double lowerLimitScale = 512;
 
         // uses temp and humidity to alter terrain shape.
-        double[] scaleArray = this.scaleNoise.get(null, x, z, xSize, zSize, scaleNoiseScaleX, scaleNoiseScaleZ);
-        double[] depthArray = this.depthNoise.get(null, x, z, xSize, zSize, depthNoiseScaleX, depthNoiseScaleZ);
-        double[] mainNoiseArray = this.mainNoise.get(null, x, y, z, xSize, ySize, zSize, coordScale / mainNoiseScaleX, heightScale / mainNoiseScaleY, coordScale / mainNoiseScaleZ);
-        double[] minLimitArray = this.minLimitNoise.get(null, x, y, z, xSize, ySize, zSize, coordScale, heightScale, coordScale);
-        double[] maxLimitArray = this.maxLimitNoise.get(null, x, y, z, xSize, ySize, zSize, coordScale, heightScale, coordScale);
+        double[] scaleArray = this.scaleNoise.getRegion(null, x, z, xSize, zSize, scaleNoiseScaleX, scaleNoiseScaleZ);
+        double[] depthArray = this.depthNoise.getRegion(null, x, z, xSize, zSize, depthNoiseScaleX, depthNoiseScaleZ);
+        double[] mainNoiseArray = this.mainNoise.getRegion(null, x, y, z, xSize, ySize, zSize, coordScale / mainNoiseScaleX, heightScale / mainNoiseScaleY, coordScale / mainNoiseScaleZ);
+        double[] minLimitArray = this.minLimitNoise.getRegion(null, x, y, z, xSize, ySize, zSize, coordScale, heightScale, coordScale);
+        double[] maxLimitArray = this.maxLimitNoise.getRegion(null, x, y, z, xSize, ySize, zSize, coordScale, heightScale, coordScale);
         int mainIndex = 0;
         int depthScaleIndex = 0;
         int xSizeScale = 16 / xSize;
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/SurfaceGeneratorOverworld.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/SurfaceGeneratorOverworld.java
index 1f1e751d5..45c116ed5 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/SurfaceGeneratorOverworld.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/SurfaceGeneratorOverworld.java
@@ -9,7 +9,6 @@ import net.minecraft.core.world.biome.Biomes;
 import net.minecraft.core.world.chunk.Chunk;
 import net.minecraft.core.world.generate.chunk.ChunkGeneratorResult;
 import net.minecraft.core.world.generate.chunk.perlin.SurfaceGenerator;
-import net.minecraft.core.world.noise.BasePerlinNoise;
 import net.minecraft.core.world.noise.PerlinNoise;
 import org.jetbrains.annotations.NotNull;
 
@@ -18,13 +17,13 @@ public class SurfaceGeneratorOverworld
 {
     private final World world;
 
-    private final BasePerlinNoise<?> beachNoise;
-    private final BasePerlinNoise<?> soilNoise;
-    private final BasePerlinNoise<?> mainNoise;
+    private final PerlinNoise beachNoise;
+    private final PerlinNoise soilNoise;
+    private final PerlinNoise mainNoise;
 
     private final boolean generateStoneVariants;
 
-    protected SurfaceGeneratorOverworld(World world, BasePerlinNoise<?> beachNoise, BasePerlinNoise<?> soilNoise, BasePerlinNoise<?> mainNoise, boolean generateStoneVariants)
+    protected SurfaceGeneratorOverworld(World world, PerlinNoise beachNoise, PerlinNoise soilNoise, PerlinNoise mainNoise, boolean generateStoneVariants)
     {
         this.world = world;
         this.beachNoise = beachNoise;
@@ -59,18 +58,18 @@ public class SurfaceGeneratorOverworld
         Random rand = new Random((long) chunkX * 0x4F9939F508L + (long) chunkZ * 0x1EF1565BD5L);
 
         double beachScale = 0.03125;
-        double[] sandBeachNoise = beachNoise.get(null, chunkX * Chunk.CHUNK_SIZE_X, chunkZ * Chunk.CHUNK_SIZE_Z, 0.0D, Chunk.CHUNK_SIZE_X, Chunk.CHUNK_SIZE_Z, 1, beachScale, beachScale, 1.0D);
-        double[] gravelBeachNoise = beachNoise.get(null, chunkX * Chunk.CHUNK_SIZE_X, 109.0134D, chunkZ * Chunk.CHUNK_SIZE_Z, Chunk.CHUNK_SIZE_X, 1, Chunk.CHUNK_SIZE_Z, beachScale, 1.0D, beachScale);
-        double[] soilThicknessNoise = soilNoise.get(null, chunkX * Chunk.CHUNK_SIZE_X, chunkZ * Chunk.CHUNK_SIZE_Z, 0.0D, Chunk.CHUNK_SIZE_X, Chunk.CHUNK_SIZE_Z, 1, beachScale * 2D, beachScale * 2D, beachScale * 2D);
+        double[] sandBeachNoise = beachNoise.getRegion(null, chunkX * Chunk.CHUNK_SIZE_X, chunkZ * Chunk.CHUNK_SIZE_Z, 0.0D, Chunk.CHUNK_SIZE_X, Chunk.CHUNK_SIZE_Z, 1, beachScale, beachScale, 1.0D);
+        double[] gravelBeachNoise = beachNoise.getRegion(null, chunkX * Chunk.CHUNK_SIZE_X, 109.0134D, chunkZ * Chunk.CHUNK_SIZE_Z, Chunk.CHUNK_SIZE_X, 1, Chunk.CHUNK_SIZE_Z, beachScale, 1.0D, beachScale);
+        double[] soilThicknessNoise = soilNoise.getRegion(null, chunkX * Chunk.CHUNK_SIZE_X, chunkZ * Chunk.CHUNK_SIZE_Z, 0.0D, Chunk.CHUNK_SIZE_X, Chunk.CHUNK_SIZE_Z, 1, beachScale * 2D, beachScale * 2D, beachScale * 2D);
 
         double[] stoneLayerNoise = null;
         double[] stoneLayerNoiseGranite = null;
         double[] stoneLayerNoiseLimestone = null;
         if (generateStoneVariants)
         {
-            stoneLayerNoise = soilNoise.get(null, chunkX * Chunk.CHUNK_SIZE_X, chunkZ * Chunk.CHUNK_SIZE_Z, 0.0D, Chunk.CHUNK_SIZE_X, Chunk.CHUNK_SIZE_Z, 1, beachScale * 4D, beachScale * 4D, beachScale * 4D);
-            stoneLayerNoiseGranite = mainNoise.get(null, chunkX * Chunk.CHUNK_SIZE_X, chunkZ * Chunk.CHUNK_SIZE_Z, 0.0D, Chunk.CHUNK_SIZE_X, Chunk.CHUNK_SIZE_Z, 1, beachScale * 4D, beachScale * 4D, beachScale * 4D);
-            stoneLayerNoiseLimestone = beachNoise.get(null, chunkX * Chunk.CHUNK_SIZE_X, chunkZ * Chunk.CHUNK_SIZE_Z, 0.0D, Chunk.CHUNK_SIZE_X, Chunk.CHUNK_SIZE_Z, 1, beachScale * 4D, beachScale * 4D, beachScale * 4D);
+            stoneLayerNoise = soilNoise.getRegion(null, chunkX * Chunk.CHUNK_SIZE_X, chunkZ * Chunk.CHUNK_SIZE_Z, 0.0D, Chunk.CHUNK_SIZE_X, Chunk.CHUNK_SIZE_Z, 1, beachScale * 4D, beachScale * 4D, beachScale * 4D);
+            stoneLayerNoiseGranite = mainNoise.getRegion(null, chunkX * Chunk.CHUNK_SIZE_X, chunkZ * Chunk.CHUNK_SIZE_Z, 0.0D, Chunk.CHUNK_SIZE_X, Chunk.CHUNK_SIZE_Z, 1, beachScale * 4D, beachScale * 4D, beachScale * 4D);
+            stoneLayerNoiseLimestone = beachNoise.getRegion(null, chunkX * Chunk.CHUNK_SIZE_X, chunkZ * Chunk.CHUNK_SIZE_Z, 0.0D, Chunk.CHUNK_SIZE_X, Chunk.CHUNK_SIZE_Z, 1, beachScale * 4D, beachScale * 4D, beachScale * 4D);
         }
 
         for(int z = 0; z < Chunk.CHUNK_SIZE_Z; z++)
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 343f4fafb..973d8438e 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
@@ -8,6 +8,7 @@ import net.minecraft.core.world.biome.Biomes;
 import net.minecraft.core.world.chunk.Chunk;
 import net.minecraft.core.world.generate.chunk.ChunkDecorator;
 import net.minecraft.core.world.generate.feature.*;
+import net.minecraft.core.world.noise.LegacyNoiseType;
 import net.minecraft.core.world.noise.PerlinNoise;
 import org.jetbrains.annotations.NotNull;
 
@@ -21,7 +22,7 @@ public class ChunkDecoratorOverworldB173
     public ChunkDecoratorOverworldB173(final @NotNull World world) {
         this.world = world;
 
-        this.forestNoise = new PerlinNoise(world.getRandomSeed(), 8, 82);
+        this.forestNoise = new PerlinNoise(world.getRandomSeed(), 8, 82, LegacyNoiseType.BETA);
     }
 
     @Override
@@ -135,7 +136,7 @@ public class ChunkDecoratorOverworldB173
         }
 
         final double forestNoiseScale = 0.5;
-        final int forestNoiseValue = (int) ((this.forestNoise.get(wx * forestNoiseScale, wz * forestNoiseScale) / 8.0 + rand.nextDouble() * 4.0 + 4.0) / 3.0);
+        final int forestNoiseValue = (int) ((this.forestNoise.getValue(wx * forestNoiseScale, wz * forestNoiseScale) / 8.0 + rand.nextDouble() * 4.0 + 4.0) / 3.0);
         int numTrees = 0;
 
         if (rand.nextInt(10) == 0) {
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/b173/DensityGeneratorOverworldB173.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/b173/DensityGeneratorOverworldB173.java
index c212cec53..49b398e2b 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/b173/DensityGeneratorOverworldB173.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/b173/DensityGeneratorOverworldB173.java
@@ -2,7 +2,8 @@ package net.minecraft.core.world.generate.chunk.perlin.overworld.b173;
 
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.generate.chunk.perlin.overworld.DensityGeneratorOverworld;
-import net.minecraft.core.world.noise.BetaPerlinNoise;
+import net.minecraft.core.world.noise.LegacyNoiseType;
+import net.minecraft.core.world.noise.PerlinNoise;
 import org.jetbrains.annotations.NotNull;
 
 public class DensityGeneratorOverworldB173
@@ -10,11 +11,11 @@ public class DensityGeneratorOverworldB173
 
     public DensityGeneratorOverworldB173(final @NotNull World world) {
         super(world,
-            new BetaPerlinNoise(world.getRandomSeed(), 16, 0),
-            new BetaPerlinNoise(world.getRandomSeed(), 16, 16),
-            new BetaPerlinNoise(world.getRandomSeed(), 8, 32),
-            new BetaPerlinNoise(world.getRandomSeed(), 10, 48),
-            new BetaPerlinNoise(world.getRandomSeed(), 16, 58),
+            new PerlinNoise(world.getRandomSeed(), 16, 0, LegacyNoiseType.BETA),
+            new PerlinNoise(world.getRandomSeed(), 16, 16, LegacyNoiseType.BETA),
+            new PerlinNoise(world.getRandomSeed(), 8, 32, LegacyNoiseType.BETA),
+            new PerlinNoise(world.getRandomSeed(), 10, 48, LegacyNoiseType.BETA),
+            new PerlinNoise(world.getRandomSeed(), 16, 58, LegacyNoiseType.BETA),
             false
         );
     }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/b173/SurfaceGeneratorOverworldB173.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/b173/SurfaceGeneratorOverworldB173.java
index 96efed91b..add4478aa 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/b173/SurfaceGeneratorOverworldB173.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/b173/SurfaceGeneratorOverworldB173.java
@@ -2,16 +2,17 @@ package net.minecraft.core.world.generate.chunk.perlin.overworld.b173;
 
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.generate.chunk.perlin.overworld.SurfaceGeneratorOverworld;
-import net.minecraft.core.world.noise.BetaPerlinNoise;
+import net.minecraft.core.world.noise.LegacyNoiseType;
+import net.minecraft.core.world.noise.PerlinNoise;
 import org.jetbrains.annotations.NotNull;
 
 public class SurfaceGeneratorOverworldB173
     extends SurfaceGeneratorOverworld {
     public SurfaceGeneratorOverworldB173(final @NotNull World world) {
         super(world,
-            new BetaPerlinNoise(world.getRandomSeed(), 4, 40),
-            new BetaPerlinNoise(world.getRandomSeed(), 4, 44),
-            new BetaPerlinNoise(world.getRandomSeed(), 8, 32),
+            new PerlinNoise(world.getRandomSeed(), 4, 40, LegacyNoiseType.BETA),
+            new PerlinNoise(world.getRandomSeed(), 4, 44, LegacyNoiseType.BETA),
+            new PerlinNoise(world.getRandomSeed(), 8, 32, LegacyNoiseType.BETA),
             false
         );
     }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/hell/ChunkDecoratorOverworldHell.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/hell/ChunkDecoratorOverworldHell.java
index a0888acfb..493abff0f 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/hell/ChunkDecoratorOverworldHell.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/hell/ChunkDecoratorOverworldHell.java
@@ -6,11 +6,9 @@ import net.minecraft.core.block.BlockLogicOreGold;
 import net.minecraft.core.block.BlockLogicOreIron;
 import net.minecraft.core.block.BlockLogicOreLapis;
 import net.minecraft.core.block.BlockLogicOreRedstone;
-import net.minecraft.core.block.BlockLogicSand;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.chunk.Chunk;
-import net.minecraft.core.world.generate.chunk.ChunkDecorator;
 import net.minecraft.core.world.generate.chunk.ChunkFeatureDecorator;
 import net.minecraft.core.world.generate.feature.*;
 import net.minecraft.core.world.generate.feature.tree.WorldFeatureTree;
@@ -18,8 +16,6 @@ import net.minecraft.core.world.generate.feature.tree.WorldFeatureTreeFancy;
 import net.minecraft.core.world.noise.PerlinNoise;
 import org.jetbrains.annotations.NotNull;
 
-import java.util.Random;
-
 public class ChunkDecoratorOverworldHell
     extends ChunkFeatureDecorator {
     private final @NotNull PerlinNoise treeDensityNoise;
@@ -179,7 +175,7 @@ public class ChunkDecoratorOverworldHell
 
         this.register(14, (world, chunk, worldX, worldZ, minY, maxY, rangeY, rand) -> {
             final double d = 0.5D;
-            int treeDensity = (int) ((this.treeDensityNoise.get((double) worldX * d, (double) worldZ * d) / 8D + rand.nextDouble() * 4D + 4D) / 3D);
+            int treeDensity = (int) ((this.treeDensityNoise.getValue((double) worldX * d, (double) worldZ * d) / 8D + rand.nextDouble() * 4D + 4D) / 3D);
             if (rand.nextInt(10) == 0) {
                 treeDensity++;
             }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/retro/ChunkDecoratorOverworldRetro.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/retro/ChunkDecoratorOverworldRetro.java
index ab9769f6e..fa68e82fa 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/retro/ChunkDecoratorOverworldRetro.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/retro/ChunkDecoratorOverworldRetro.java
@@ -14,7 +14,8 @@ import net.minecraft.core.world.generate.chunk.ChunkDecorator;
 import net.minecraft.core.world.generate.feature.*;
 import net.minecraft.core.world.generate.feature.tree.WorldFeatureTree;
 import net.minecraft.core.world.generate.feature.tree.WorldFeatureTreeFancy;
-import net.minecraft.core.world.noise.RetroPerlinNoise;
+import net.minecraft.core.world.noise.LegacyNoiseType;
+import net.minecraft.core.world.noise.PerlinNoise;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.Random;
@@ -22,14 +23,14 @@ import java.util.Random;
 public class ChunkDecoratorOverworldRetro
     implements ChunkDecorator {
     private final @NotNull World world;
-    private final @NotNull RetroPerlinNoise treeDensityNoise;
+    private final @NotNull PerlinNoise treeDensityNoise;
 
     private final boolean snowCovered;
 
     public ChunkDecoratorOverworldRetro(@NotNull World world) {
         this.world = world;
 
-        this.treeDensityNoise = new RetroPerlinNoise(world.getRandomSeed(), 8, 74);
+        this.treeDensityNoise = new PerlinNoise(world.getRandomSeed(), 8, 74, LegacyNoiseType.ALPHA);
 
         this.snowCovered = false;//new Random(world.getRandomSeed()).nextBoolean();
     }
@@ -115,7 +116,7 @@ public class ChunkDecoratorOverworldRetro
         }
 
         double d = 0.5D;
-        int l3 = (int) ((this.treeDensityNoise.get((double) k * d, (double) l * d) / 8D + rand.nextDouble() * 4D + 4D) / 3D);
+        int l3 = (int) ((this.treeDensityNoise.getValue((double) k * d, (double) l * d) / 8D + rand.nextDouble() * 4D + 4D) / 3D);
         if (l3 < 0) {
             l3 = 0;
         }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/retro/DensityGeneratorOverworldRetro.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/retro/DensityGeneratorOverworldRetro.java
index 746c7b494..e7f96ccc2 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/retro/DensityGeneratorOverworldRetro.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/retro/DensityGeneratorOverworldRetro.java
@@ -2,18 +2,19 @@ package net.minecraft.core.world.generate.chunk.perlin.overworld.retro;
 
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.generate.chunk.perlin.overworld.DensityGeneratorOverworld;
-import net.minecraft.core.world.noise.RetroPerlinNoise;
+import net.minecraft.core.world.noise.LegacyNoiseType;
+import net.minecraft.core.world.noise.PerlinNoise;
 import org.jetbrains.annotations.NotNull;
 
 public class DensityGeneratorOverworldRetro
     extends DensityGeneratorOverworld {
     public DensityGeneratorOverworldRetro(@NotNull World world) {
         super(world,
-            new RetroPerlinNoise(world.getRandomSeed(), 16, 0),
-            new RetroPerlinNoise(world.getRandomSeed(), 16, 16),
-            new RetroPerlinNoise(world.getRandomSeed(), 8, 32),
-            new RetroPerlinNoise(world.getRandomSeed(), 10, 48),
-            new RetroPerlinNoise(world.getRandomSeed(), 16, 58),
+            new PerlinNoise(world.getRandomSeed(), 16, 0, LegacyNoiseType.ALPHA),
+            new PerlinNoise(world.getRandomSeed(), 16, 16, LegacyNoiseType.ALPHA),
+            new PerlinNoise(world.getRandomSeed(), 8, 32, LegacyNoiseType.ALPHA),
+            new PerlinNoise(world.getRandomSeed(), 10, 48, LegacyNoiseType.ALPHA),
+            new PerlinNoise(world.getRandomSeed(), 16, 58, LegacyNoiseType.ALPHA),
             false
         );
     }
diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/retro/SurfaceGeneratorOverworldRetro.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/retro/SurfaceGeneratorOverworldRetro.java
index 6af246763..ec1e983d9 100644
--- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/retro/SurfaceGeneratorOverworldRetro.java
+++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/overworld/retro/SurfaceGeneratorOverworldRetro.java
@@ -2,16 +2,17 @@ package net.minecraft.core.world.generate.chunk.perlin.overworld.retro;
 
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.generate.chunk.perlin.overworld.SurfaceGeneratorOverworld;
-import net.minecraft.core.world.noise.RetroPerlinNoise;
+import net.minecraft.core.world.noise.LegacyNoiseType;
+import net.minecraft.core.world.noise.PerlinNoise;
 import org.jetbrains.annotations.NotNull;
 
 public class SurfaceGeneratorOverworldRetro
     extends SurfaceGeneratorOverworld {
     public SurfaceGeneratorOverworldRetro(@NotNull World world) {
         super(world,
-            new RetroPerlinNoise(world.getRandomSeed(), 4, 40),
-            new RetroPerlinNoise(world.getRandomSeed(), 4, 44),
-            new RetroPerlinNoise(world.getRandomSeed(), 8, 32),
+            new PerlinNoise(world.getRandomSeed(), 4, 40, LegacyNoiseType.ALPHA),
+            new PerlinNoise(world.getRandomSeed(), 4, 44, LegacyNoiseType.ALPHA),
+            new PerlinNoise(world.getRandomSeed(), 8, 32, LegacyNoiseType.ALPHA),
             false
         );
     }
diff --git a/game/core/src/main/java/net/minecraft/core/world/noise/BaseImprovedNoise.java b/game/core/src/main/java/net/minecraft/core/world/noise/BaseImprovedNoise.java
deleted file mode 100644
index 00d57e28d..000000000
--- a/game/core/src/main/java/net/minecraft/core/world/noise/BaseImprovedNoise.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package net.minecraft.core.world.noise;
-
-import org.jetbrains.annotations.NotNull;
-
-import java.util.Random;
-
-// Derived from Ken Perlin's Improved Noise reference implementation: https://cs.nyu.edu/~perlin/noise/
-public abstract class BaseImprovedNoise {
-    protected final int @NotNull [] p;
-    public final double xo;
-    public final double yo;
-    public final double zo;
-
-    public BaseImprovedNoise(final @NotNull Random random) {
-        this.p = new int[512];
-        this.xo = random.nextDouble() * 256;
-        this.yo = random.nextDouble() * 256;
-        this.zo = random.nextDouble() * 256;
-
-        // Assign initial values for each permutation
-        for (int i = 0; i < 256; i++) {
-            this.p[i] = i;
-        }
-
-        // Shuffle values
-        for (int i = 0; i < 256; i++) {
-            final int newI = random.nextInt(256 - i) + i;
-            final int temp = this.p[i];
-            this.p[i] = this.p[newI];
-            this.p[newI] = temp;
-            this.p[i + 256] = this.p[i];
-        }
-    }
-
-    public double getValue(final double x, final double y) {
-        return this.getValue(x, y, 0);
-    }
-
-    public double getValue(double x, double y, double z) {
-        // Find unit cube that contains point
-        final int X = (int) Math.floor(x) & 255;
-        final int Y = (int) Math.floor(y) & 255;
-        final int Z = (int) Math.floor(z) & 255;
-
-        // Find relative XYZ of point in cube
-        x -= Math.floor(x);
-        y -= Math.floor(y);
-        z -= Math.floor(z);
-
-        // Compute fade curves for each of X, Y, and Z
-        final double u = this.fade(x);
-        final double v = this.fade(y);
-        final double w = this.fade(z);
-
-        // Hash coordinates of the 8 cube corners
-        final int A  = this.p[X    ] + Y;
-        final int AA = this.p[A    ] + Z;
-        final int AB = this.p[A + 1] + Z;
-        final int B =  this.p[X + 1] + Y;
-        final int BA = this.p[B    ] + Z;
-        final int BB = this.p[B + 1] + Z;
-
-        // Add blended results from 8 corners of the cube
-        return this.lerp(
-            w,
-            this.lerp(
-                v,
-                this.lerp(
-                    u,
-                    this.grad(this.p[AA], x, y, z),
-                    this.grad(this.p[BA], x - 1, y, z)
-                ),
-                this.lerp(
-                    u,
-                    this.grad(this.p[AB], x, y - 1, z),
-                    this.grad(this.p[BB], x - 1, y - 1, z)
-                )
-            ),
-            this.lerp(
-                v,
-                this.lerp(
-                    u,
-                    this.grad(this.p[AA + 1], x, y, z - 1),
-                    this.grad(this.p[BA + 1], x - 1, y, z - 1)),
-                this.lerp(
-                    u,
-                    this.grad(this.p[AB + 1], x, y - 1, z - 1),
-                    this.grad(this.p[BB + 1], x - 1, y - 1, z - 1)
-                )
-            )
-        );
-    }
-
-    protected double grad2(final int hash, final double x, final double y) {
-        final int h = hash & 15;
-        final double u = (double) (1 - ((h & 8) >> 3)) * x;
-        final double v = h < 4 ? 0.0D : h == 12 || h == 14 ? x : y;
-
-        return ((h & 1) != 0 ? -u : u) + ((h & 2) != 0 ? -v : v);
-    }
-
-    protected double fade(final double t) {
-        return t * t * t * (t * (t * 6 - 15) + 10);
-    }
-
-    protected double lerp(final double t, final double a, final double b) {
-        return a + t * (b - a);
-    }
-
-    protected double grad(final int hash, final double x, final double y, final double z) {
-        // Converts low 4 bits of hash code into 12 gradient directions.
-        final int h = hash & 15;
-        final double u = h < 8 ? x : y;
-        final double v = h < 4 ? y : h == 12 || h == 14 ? x : z;
-
-        return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
-    }
-
-    public abstract void add(double[] out, double x, double y, double z, int xSize, int ySize, int zSize, double xScale, double yScale, double zScale, double valueScale);
-}
diff --git a/game/core/src/main/java/net/minecraft/core/world/noise/BasePerlinNoise.java b/game/core/src/main/java/net/minecraft/core/world/noise/BasePerlinNoise.java
deleted file mode 100644
index 578e223c0..000000000
--- a/game/core/src/main/java/net/minecraft/core/world/noise/BasePerlinNoise.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package net.minecraft.core.world.noise;
-
-import java.util.Arrays;
-import java.util.Random;
-
-public abstract class BasePerlinNoise<T extends BaseImprovedNoise>
-    extends SurfaceNoise
-{
-    private static final double MAX_2D = Math.sqrt(2.0 / 4.0);
-
-    private final T[] octaves;
-    private final int numOctaves;
-    final double maxValue;
-
-    public BasePerlinNoise(long seed, int numOctaves)
-    {
-        this(seed, numOctaves, 0);
-    }
-
-    public BasePerlinNoise(long seed, int numOctaves, int preOctaves)
-    {
-        Random random = new Random(seed);
-
-        for (int i = 0; i < preOctaves; i++)
-        {
-            random.nextDouble();
-            random.nextDouble();
-            random.nextDouble();
-
-            for (int j = 0; j < 256; j++)
-            {
-                random.nextInt(256 - j);
-            }
-        }
-        this.numOctaves = numOctaves;
-        this.octaves = newOctaves(random, numOctaves);
-
-        double maxValue = 0.0;
-        double levelScale = 1.0;
-        for (int i = 0; i < this.numOctaves; i++) {
-            maxValue += MAX_2D / levelScale;
-            levelScale /= 2.0;
-        }
-
-        this.maxValue = maxValue;
-    }
-
-    protected abstract T[] newOctaves(Random random, int numOctaves);
-
-    public double get(double x, double y)
-    {
-        double out = 0.0D;
-        double levelScale = 1.0D;
-
-        for(int i = 0; i < numOctaves; i++)
-        {
-            out += octaves[i].getValue(x * levelScale, y * levelScale) / levelScale;
-            levelScale /= 2;
-        }
-
-        return out;
-    }
-
-    public double getNormalized(double x, double y) {
-        final double value = this.get(x, y);
-
-        // Map to +-1.0
-        double workingValue = value / this.maxValue;
-
-        // Map to 0.0-1.0
-        workingValue = 0.5 + (workingValue / 2.0);
-
-        return workingValue;
-    }
-
-    public double[] get(double[] noiseArray, double x, double y, double z,
-                        int xSize, int ySize, int zSize, double scaleX, double scaleY,
-                        double scaleZ)
-    {
-        if (noiseArray == null)
-        {
-            noiseArray = new double[xSize * ySize * zSize];
-        }
-        else
-        {
-            Arrays.fill(noiseArray, 0.0D);
-        }
-
-        double frequency = 1.0D;
-        for(int i = 0; i < numOctaves; i++)
-        {
-            octaves[i].add(noiseArray, x, y, z, xSize, ySize, zSize, scaleX * frequency, scaleY * frequency, scaleZ * frequency, frequency);
-            frequency /= 2D;
-        }
-
-        return noiseArray;
-    }
-
-    public double[] get(double[] densityArray, int x, int z, int xSize, int zSize, double scaleX, double scaleZ)
-    {
-        return get(densityArray, x, 0, z, xSize, 1, zSize, scaleX, 1.0, scaleZ);
-    }
-}
diff --git a/game/core/src/main/java/net/minecraft/core/world/noise/BetaPerlinNoise.java b/game/core/src/main/java/net/minecraft/core/world/noise/BetaPerlinNoise.java
deleted file mode 100644
index 60b83da3b..000000000
--- a/game/core/src/main/java/net/minecraft/core/world/noise/BetaPerlinNoise.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package net.minecraft.core.world.noise;
-
-import java.util.Random;
-
-public class BetaPerlinNoise
-    extends BasePerlinNoise<ImprovedNoise>
-{
-    public BetaPerlinNoise(final long seed, final int numOctaves) {
-        super(seed, numOctaves);
-    }
-
-    public BetaPerlinNoise(final long seed, final int numOctaves, final int preOctaves) {
-        super(seed, numOctaves, preOctaves);
-    }
-
-    @Override
-    protected ImprovedNoise[] newOctaves(final Random random, final int numOctaves) {
-        ImprovedNoise[] levels = new ImprovedNoise[numOctaves];
-
-        for (int i = 0; i < numOctaves; i++) {
-            levels[i] = new ImprovedNoise(random, LegacyNoiseType.BETA);
-        }
-
-        return levels;
-    }
-}
diff --git a/game/core/src/main/java/net/minecraft/core/world/noise/CombinedPerlinNoise.java b/game/core/src/main/java/net/minecraft/core/world/noise/CombinedPerlinNoise.java
index 6a0c3618b..b71b4b2ab 100644
--- a/game/core/src/main/java/net/minecraft/core/world/noise/CombinedPerlinNoise.java
+++ b/game/core/src/main/java/net/minecraft/core/world/noise/CombinedPerlinNoise.java
@@ -1,17 +1,17 @@
 package net.minecraft.core.world.noise;
 
-public class CombinedPerlinNoise
-{
-    private final BasePerlinNoise<?> perlinNoiseA;
-    private final BasePerlinNoise<?> perlinNoiseB;
+import org.jetbrains.annotations.NotNull;
 
-    public CombinedPerlinNoise(BasePerlinNoise<?> perlinNoiseA, BasePerlinNoise<?> perlinNoiseB) {
+public class CombinedPerlinNoise {
+    private final @NotNull PerlinNoise perlinNoiseA;
+    private final @NotNull PerlinNoise perlinNoiseB;
+
+    public CombinedPerlinNoise(final @NotNull PerlinNoise perlinNoiseA, final @NotNull PerlinNoise perlinNoiseB) {
         this.perlinNoiseA = perlinNoiseA;
         this.perlinNoiseB = perlinNoiseB;
     }
 
-    public double get(double x, double y)
-    {
-        return this.perlinNoiseA.get(x + this.perlinNoiseB.get(x, y), y);
+    public double get(final double x, final double y) {
+        return this.perlinNoiseA.getValue(x + this.perlinNoiseB.getValue(x, y), y);
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/noise/SurfaceNoise.java b/game/core/src/main/java/net/minecraft/core/world/noise/FractalBrownianNoise.java
similarity index 53%
rename from game/core/src/main/java/net/minecraft/core/world/noise/SurfaceNoise.java
rename to game/core/src/main/java/net/minecraft/core/world/noise/FractalBrownianNoise.java
index 584e4cf8f..90db48580 100644
--- a/game/core/src/main/java/net/minecraft/core/world/noise/SurfaceNoise.java
+++ b/game/core/src/main/java/net/minecraft/core/world/noise/FractalBrownianNoise.java
@@ -1,5 +1,4 @@
 package net.minecraft.core.world.noise;
 
-public abstract class SurfaceNoise
-{
+public class FractalBrownianNoise {
 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/noise/ImprovedNoise.java b/game/core/src/main/java/net/minecraft/core/world/noise/ImprovedNoise.java
index a2f3d8542..352940ae3 100644
--- a/game/core/src/main/java/net/minecraft/core/world/noise/ImprovedNoise.java
+++ b/game/core/src/main/java/net/minecraft/core/world/noise/ImprovedNoise.java
@@ -4,30 +4,134 @@ import org.jetbrains.annotations.NotNull;
 
 import java.util.Random;
 
-public class ImprovedNoise
-    extends BaseImprovedNoise {
+// Derived from Ken Perlin's Improved Noise reference implementation: https://cs.nyu.edu/~perlin/noise/
+public class ImprovedNoise {
     private final @NotNull LegacyNoiseType legacyNoiseType;
 
-    public ImprovedNoise(final @NotNull Random random, final @NotNull LegacyNoiseType legacyNoiseType) {
-        super(random);
+    private final int @NotNull [] p;
+
+    public final double xo;
+    public final double yo;
+    public final double zo;
 
+    public ImprovedNoise(final @NotNull Random random) {
+        this(random, LegacyNoiseType.DEFAULT);
+    }
+
+    public ImprovedNoise(final @NotNull Random random, final @NotNull LegacyNoiseType legacyNoiseType) {
         this.legacyNoiseType = legacyNoiseType;
+
+        this.p = new int[512];
+        this.xo = random.nextDouble() * 256;
+        this.yo = random.nextDouble() * 256;
+        this.zo = random.nextDouble() * 256;
+
+        // Assign initial values for each permutation
+        for (int i = 0; i < 256; i++) {
+            this.p[i] = i;
+        }
+
+        // Shuffle values
+        for (int i = 0; i < 256; i++) {
+            final int newI = random.nextInt(256 - i) + i;
+            final int temp = this.p[i];
+            this.p[i] = this.p[newI];
+            this.p[newI] = temp;
+            this.p[i + 256] = this.p[i];
+        }
     }
 
-    public ImprovedNoise(final @NotNull Random random) {
-        this(random, LegacyNoiseType.NONE);
+    public double getValue(final double x, final double z) {
+        return this.getValue(x, z, 0);
+    }
+
+    public double getValue(double x, double y, double z) {
+        // Find unit cube that contains point
+        final int X = (int) Math.floor(x) & 255;
+        final int Y = (int) Math.floor(y) & 255;
+        final int Z = (int) Math.floor(z) & 255;
+
+        // Find relative XYZ of point in cube
+        x -= Math.floor(x);
+        y -= Math.floor(y);
+        z -= Math.floor(z);
+
+        // Compute fade curves for each of X, Y, and Z
+        final double u = this.fade(x);
+        final double v = this.fade(y);
+        final double w = this.fade(z);
+
+        // Hash coordinates of the 8 cube corners
+        final int A  = this.p[X    ] + Y;
+        final int AA = this.p[A    ] + Z;
+        final int AB = this.p[A + 1] + Z;
+        final int B =  this.p[X + 1] + Y;
+        final int BA = this.p[B    ] + Z;
+        final int BB = this.p[B + 1] + Z;
+
+        // Add blended results from 8 corners of the cube
+        return this.lerp(
+            w,
+            this.lerp(
+                v,
+                this.lerp(
+                    u,
+                    this.grad(this.p[AA], x, y, z),
+                    this.grad(this.p[BA], x - 1, y, z)
+                ),
+                this.lerp(
+                    u,
+                    this.grad(this.p[AB], x, y - 1, z),
+                    this.grad(this.p[BB], x - 1, y - 1, z)
+                )
+            ),
+            this.lerp(
+                v,
+                this.lerp(
+                    u,
+                    this.grad(this.p[AA + 1], x, y, z - 1),
+                    this.grad(this.p[BA + 1], x - 1, y, z - 1)),
+                this.lerp(
+                    u,
+                    this.grad(this.p[AB + 1], x, y - 1, z - 1),
+                    this.grad(this.p[BB + 1], x - 1, y - 1, z - 1)
+                )
+            )
+        );
+    }
+
+    protected double grad2(final int hash, final double x, final double y) {
+        final int h = hash & 15;
+        final double u = (double) (1 - ((h & 8) >> 3)) * x;
+        final double v = h < 4 ? 0.0D : h == 12 || h == 14 ? x : y;
+
+        return ((h & 1) != 0 ? -u : u) + ((h & 2) != 0 ? -v : v);
+    }
+
+    protected double fade(final double t) {
+        return t * t * t * (t * (t * 6 - 15) + 10);
+    }
+
+    protected double lerp(final double t, final double a, final double b) {
+        return a + t * (b - a);
+    }
+
+    protected double grad(final int hash, final double x, final double y, final double z) {
+        // Converts low 4 bits of hash code into 12 gradient directions.
+        final int h = hash & 15;
+        final double u = h < 8 ? x : y;
+        final double v = h < 4 ? y : h == 12 || h == 14 ? x : z;
+
+        return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
     }
 
-    @Override
     public void add(
         final double @NotNull [] out,
         final double x, final double y, final double z,
         final int xSize, final int ySize, final int zSize,
         final double xScale, final double yScale, final double zScale,
-        final double valueScale
+        final double amplitude
     ) {
-        final double scale = 1.0 / valueScale;
-
         if (ySize == 1 && this.legacyNoiseType.handleEdgeCaseY) {
             int i = 0;
             for (int xi = 0; xi < xSize; xi++) {
@@ -75,7 +179,7 @@ public class ImprovedNoise
                         )
                     );
 
-                    out[i++] += value * scale;
+                    out[i++] += value * amplitude;
                 }
             }
         } else if (zSize == 1 && this.legacyNoiseType.handleEdgeCaseZ) {
@@ -125,7 +229,7 @@ public class ImprovedNoise
                         )
                     );
 
-                    out[i++] += value * scale;
+                    out[i++] += value * amplitude;
                 }
             }
         } else {
@@ -211,7 +315,7 @@ public class ImprovedNoise
                         final double lerpedXYNegZ = this.lerp(v, lerpedXNegZ, lerpedXNegYNegZ);
                         final double lerpedXYZ = this.lerp(w, lerpedXY, lerpedXYNegZ);
 
-                        out[i++] += lerpedXYZ * scale;
+                        out[i++] += lerpedXYZ * amplitude;
                     }
                 }
             }
diff --git a/game/core/src/main/java/net/minecraft/core/world/noise/LegacyNoiseType.java b/game/core/src/main/java/net/minecraft/core/world/noise/LegacyNoiseType.java
index 1d8b330f8..bea0c9c24 100644
--- a/game/core/src/main/java/net/minecraft/core/world/noise/LegacyNoiseType.java
+++ b/game/core/src/main/java/net/minecraft/core/world/noise/LegacyNoiseType.java
@@ -1,7 +1,7 @@
 package net.minecraft.core.world.noise;
 
 public enum LegacyNoiseType {
-    NONE(true, true),
+    DEFAULT(true, true),
     ALPHA(false, false),
     BETA(true, false);
 
diff --git a/game/core/src/main/java/net/minecraft/core/world/noise/Noise.java b/game/core/src/main/java/net/minecraft/core/world/noise/Noise.java
new file mode 100644
index 000000000..48e731b87
--- /dev/null
+++ b/game/core/src/main/java/net/minecraft/core/world/noise/Noise.java
@@ -0,0 +1,20 @@
+package net.minecraft.core.world.noise;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public interface Noise {
+    double getValue(final double x, final double y);
+    double getValue(final double x, final double y, final double z);
+
+    double @NotNull [] getRegion(
+        final double @Nullable [] out,
+        final double x, final double z,
+        final double xScale, final double zScale
+    );
+    double @NotNull [] getRegion(
+        final double @Nullable [] out,
+        final double x, final double y, final double z,
+        final double xScale, final double yScale, final double zScale
+    );
+}
diff --git a/game/core/src/main/java/net/minecraft/core/world/noise/PerlinNoise.java b/game/core/src/main/java/net/minecraft/core/world/noise/PerlinNoise.java
index daeb826c7..ac9077f77 100644
--- a/game/core/src/main/java/net/minecraft/core/world/noise/PerlinNoise.java
+++ b/game/core/src/main/java/net/minecraft/core/world/noise/PerlinNoise.java
@@ -1,30 +1,136 @@
 package net.minecraft.core.world.noise;
 
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Arrays;
 import java.util.Random;
 
-public class PerlinNoise
-        extends BasePerlinNoise<ImprovedNoise>
-{
-    public PerlinNoise(long seed, int levels)
-    {
-        super(seed, levels);
+public class PerlinNoise {
+    private static final double MAX_2D = Math.sqrt(2.0 / 4.0);
+
+    private final @NotNull ImprovedNoise @NotNull [] octaves;
+    private final int numOctaves;
+    final double maxValue;
+
+    public PerlinNoise(final long seed, final int numOctaves) {
+        this(seed, numOctaves, LegacyNoiseType.DEFAULT);
+    }
+
+    public PerlinNoise(final long seed, final int numOctaves, final int preOctaves) {
+        this(seed, numOctaves, preOctaves, LegacyNoiseType.DEFAULT);
     }
 
-    public PerlinNoise(long seed, int levels, int preLevels)
-    {
-        super(seed, levels, preLevels);
+    public PerlinNoise(final long seed, final int numOctaves, final @NotNull LegacyNoiseType legacyNoiseType) {
+        this(seed, numOctaves, 0, legacyNoiseType);
+    }
+
+    public PerlinNoise(final long seed, final int numOctaves, final int preOctaves, final @NotNull LegacyNoiseType legacyNoiseType) {
+        final @NotNull Random random = new Random(seed);
+
+        for (int i = 0; i < preOctaves; i++) {
+            random.nextDouble();
+            random.nextDouble();
+            random.nextDouble();
+
+            for (int j = 0; j < 256; j++) {
+                random.nextInt(256 - j);
+            }
+        }
+        this.numOctaves = numOctaves;
+        this.octaves = new ImprovedNoise[numOctaves];
+        for (int i = 0; i < numOctaves; i++) {
+            this.octaves[i] = new ImprovedNoise(random, legacyNoiseType);
+        }
+
+        double maxValue = 0.0;
+        double levelScale = 1.0;
+        for (int i = 0; i < this.numOctaves; i++) {
+            maxValue += MAX_2D / levelScale;
+            levelScale /= 2.0;
+        }
+
+        this.maxValue = maxValue;
     }
 
-    @Override
-    protected ImprovedNoise[] newOctaves(Random random, int numOctaves)
-    {
-        ImprovedNoise[] levels = new ImprovedNoise[numOctaves];
+    public double getValue(final double x, final double y) {
+        final double lacunarity = 0.5;
+        final double persistence = 2.0;
+
+        double out = 0.0;
+        double frequency = 1.0;
+        double amplitude = 1.0;
+
+        for (int i = 0; i < this.numOctaves; i++) {
+            out += this.octaves[i].getValue(x * frequency, y * frequency) * amplitude;
+            frequency *= lacunarity;
+            amplitude *= persistence;
+        }
+
+        return out;
+    }
+
+    public double getValue(final double x, final double y, final double z) {
+        final double lacunarity = 0.5;
+        final double persistence = 2.0;
+
+        double out = 0.0;
+        double frequency = 1.0;
+        double amplitude = 1.0;
+
+        for (int i = 0; i < this.numOctaves; i++) {
+            out += this.octaves[i].getValue(x * frequency, y * frequency, z * frequency) * amplitude;
+            frequency *= lacunarity;
+            amplitude *= persistence;
+        }
+
+        return out;
+    }
+
+    public double getNormalized(final double x, final double y) {
+        final double value = this.getValue(x, y);
+
+        // Map to +-1.0
+        double workingValue = value / this.maxValue;
+
+        // Map to 0.0-1.0
+        workingValue = 0.5 + (workingValue / 2.0);
+
+        return workingValue;
+    }
+
+    public double @NotNull [] getRegion(
+        final double @Nullable [] densityArray,
+        final double x, final double z,
+        final int xSize, final int zSize,
+        final double scaleX, final double scaleZ
+    ) {
+        return this.getRegion(densityArray, x, 0, z, xSize, 1, zSize, scaleX, 1.0, scaleZ);
+    }
+
+    public double @NotNull [] getRegion(
+        double @Nullable [] noiseArray,
+        final double x, final double y, final double z,
+        final int xSize, final int ySize, final int zSize,
+        final double xScale, final double yScale, final double zScale
+    ) {
+        if (noiseArray == null) {
+            noiseArray = new double[xSize * ySize * zSize];
+        } else {
+            Arrays.fill(noiseArray, 0.0);
+        }
+
+        final double lacunarity = 0.5;
+        final double persistence = 2.0;
 
-        for (int i = 0; i < numOctaves; i++)
-        {
-            levels[i] = new ImprovedNoise(random);
+        double frequency = 1.0;
+        double amplitude = 1.0;
+        for (int i = 0; i < this.numOctaves; i++) {
+            this.octaves[i].add(noiseArray, x, y, z, xSize, ySize, zSize, xScale * frequency, yScale * frequency, zScale * frequency, amplitude);
+            frequency *= lacunarity;
+            amplitude *= persistence;
         }
 
-        return levels;
+        return noiseArray;
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/world/noise/PerlinSimplexNoise.java b/game/core/src/main/java/net/minecraft/core/world/noise/PerlinSimplexNoise.java
index 92ac51555..0fd929e45 100644
--- a/game/core/src/main/java/net/minecraft/core/world/noise/PerlinSimplexNoise.java
+++ b/game/core/src/main/java/net/minecraft/core/world/noise/PerlinSimplexNoise.java
@@ -1,70 +1,49 @@
 package net.minecraft.core.world.noise;
 
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
 import java.util.Arrays;
 import java.util.Random;
 
-public class PerlinSimplexNoise extends SurfaceNoise
-{
-    private final SimplexNoise[] octaves;
+public class PerlinSimplexNoise {
+    private final @NotNull SimplexNoise @NotNull [] octaves;
     private final int numOctaves;
 
-    public PerlinSimplexNoise(Random random, int numOctaves)
-    {
+    public PerlinSimplexNoise(final @NotNull Random random, final int numOctaves) {
         this.numOctaves = numOctaves;
-        octaves = new SimplexNoise[numOctaves];
-        for(int i = 0; i < numOctaves; i++)
-        {
-            octaves[i] = new SimplexNoise(random);
+        this.octaves = new SimplexNoise[numOctaves];
+        for (int i = 0; i < numOctaves; i++) {
+            this.octaves[i] = new SimplexNoise(random);
         }
     }
 
-    public double getMaximumValue()
-    {
-        return getMaximumValue(0.5);
+    public double @NotNull [] getRegion(
+        final double @Nullable [] out,
+        final double x, final double z,
+        final int xSize, final int zSize,
+        final double xScale, final double zScale,
+        final double lacunarity
+    ) {
+        return this.getRegion(out, x, z, xSize, zSize, xScale, zScale, lacunarity, 0.5);
     }
 
-    // Gets the maximum value for a given value of amplitudeScale. For those values, the range is from -getMaximumValue to getMaximumValue.
-    public double getMaximumValue(double amplitudeScale)
-    {
-        double max = 0.0;
-
-        double amplitude = 1.0;
-        for (int l = 0; l < numOctaves; l++)
-        {
-            max += 0.55D / amplitude;
-            amplitude *= amplitudeScale;
-        }
-
-        return max;
-    }
+    public double @NotNull [] getRegion(double @Nullable [] out, final double x, final double z, final int xSize, final int zSize, double xScale, double zScale, final double lacunarity, final double persistence) {
+        xScale /= 1.5;
+        zScale /= 1.5;
 
-    public double[] getValue(double[] out, double x, double z, int xSize, int zSize, double xScale, double zScale, double frequencyScale)
-    {
-        return getValue(out, x, z, xSize, zSize, xScale, zScale, frequencyScale, 0.5D);
-    }
-
-    // Uses Fractal Brownian Motion to refine the noise.
-    public double[] getValue(double[] out, double x, double z, int xSize, int zSize, double xScale, double zScale, double frequencyScale, double amplitudeScale)
-    {
-        xScale /= 1.5D;
-        zScale /= 1.5D;
-
-        if (out == null || out.length < xSize * zSize)
-        {
+        if (out == null || out.length < xSize * zSize) {
             out = new double[xSize * zSize];
-        }
-        else
-        {
-            Arrays.fill(out, 0.0D);
+        } else {
+            Arrays.fill(out, 0.0);
         }
 
-        double frequency = 1.0D;
-        double amplitude = 1.0D;
-        for(int l = 0; l < numOctaves; l++)
-        {
-            octaves[l].add(out, x, z, xSize, zSize, xScale * frequency, zScale * frequency, 0.55D / amplitude);
-            frequency *= frequencyScale;
-            amplitude *= amplitudeScale;
+        double frequency = 1.0;
+        double amplitude = 1.0;
+        for (int l = 0; l < this.numOctaves; l++) {
+            this.octaves[l].add(out, x, z, xSize, zSize, xScale * frequency, zScale * frequency, 0.55D / amplitude);
+            frequency *= lacunarity;
+            amplitude *= persistence;
         }
 
         return out;
diff --git a/game/core/src/main/java/net/minecraft/core/world/noise/RetroPerlinNoise.java b/game/core/src/main/java/net/minecraft/core/world/noise/RetroPerlinNoise.java
deleted file mode 100644
index c73f9a104..000000000
--- a/game/core/src/main/java/net/minecraft/core/world/noise/RetroPerlinNoise.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package net.minecraft.core.world.noise;
-
-import java.util.Random;
-
-public class RetroPerlinNoise
-		extends BasePerlinNoise<ImprovedNoise>
-{
-	public RetroPerlinNoise(long seed, int levels)
-	{
-		super(seed, levels);
-	}
-
-	public RetroPerlinNoise(long seed, int levels, int preLevels)
-	{
-		super(seed, levels, preLevels);
-	}
-
-	@Override
-	protected ImprovedNoise[] newOctaves(Random random, int numOctaves)
-	{
-		ImprovedNoise[] levels = new ImprovedNoise[numOctaves];
-
-		for (int i = 0; i < numOctaves; i++)
-		{
-			levels[i] = new ImprovedNoise(random, LegacyNoiseType.ALPHA);
-		}
-
-		return levels;
-	}
-}
diff --git a/game/core/src/main/java/net/minecraft/core/world/noise/SimplexNoise.java b/game/core/src/main/java/net/minecraft/core/world/noise/SimplexNoise.java
index fd9bff937..ce482f915 100644
--- a/game/core/src/main/java/net/minecraft/core/world/noise/SimplexNoise.java
+++ b/game/core/src/main/java/net/minecraft/core/world/noise/SimplexNoise.java
@@ -1,86 +1,86 @@
 package net.minecraft.core.world.noise;
 
+import org.jetbrains.annotations.NotNull;
+
 import java.util.Random;
 
-public class SimplexNoise
-{
-    private static final int[][] GRAD = {
-            {  1,  1,  0 }, { -1,  1,  0 }, {  1, -1,  0 },
-            { -1, -1,  0 }, {  1,  0,  1 }, { -1,  0,  1 },
-            {  1,  0, -1 }, { -1,  0, -1 }, {  0,  1,  1 },
-            {  0, -1,  1 }, {  0,  1, -1 }, {  0, -1, -1 }
+public class SimplexNoise {
+    private static final int @NotNull [] @NotNull [] GRAD = {
+        {  1,  1,  0 }, { -1,  1,  0 }, {  1, -1,  0 },
+        { -1, -1,  0 }, {  1,  0,  1 }, { -1,  0,  1 },
+        {  1,  0, -1 }, { -1,  0, -1 }, {  0,  1,  1 },
+        {  0, -1,  1 }, {  0,  1, -1 }, {  0, -1, -1 }
     };
     private static final double F2 = 0.5D * (Math.sqrt(3D) - 1.0D);
     private static final double G2 = (3D - Math.sqrt(3D)) / 6D;
-    private final int[] p;
+
+    private final int @NotNull [] p;
     public final double xo;
     public final double yo;
     public final double zo;
 
-    public SimplexNoise(Random random)
-    {
-        p = new int[512];
-        xo = random.nextDouble() * 256D;
-        yo = random.nextDouble() * 256D;
-        zo = random.nextDouble() * 256D;
+    public SimplexNoise(final @NotNull Random random) {
+        this.p = new int[512];
+        this.xo = random.nextDouble() * 256D;
+        this.yo = random.nextDouble() * 256D;
+        this.zo = random.nextDouble() * 256D;
 
-        for(int i = 0; i < 256; i++)
-        {
-            p[i] = i;
+        for (int i = 0; i < 256; i++) {
+            this.p[i] = i;
         }
 
-        for(int i = 0; i < 256; i++)
-        {
-            int k = random.nextInt(256 - i) + i;
-            int l = p[i];
-            p[i] = p[k];
-            p[k] = l;
-            p[i + 256] = p[i];
+        for (int i = 0; i < 256; i++) {
+            final int newI = random.nextInt(256 - i) + i;
+            final int temp = this.p[i];
+            this.p[i] = this.p[newI];
+            this.p[newI] = temp;
+            this.p[i + 256] = this.p[i];
         }
     }
 
-    private static int wrap(double d)
-    {
-        return d <= 0.0D ? (int)d - 1 : (int)d;
+    private static int fastFloor(final double d) {
+        return d <= 0.0D ? (int) d - 1 : (int) d;
     }
 
-    private static double dot(int[] vec, double x, double y)
-    {
-        return (double)vec[0] * x + (double)vec[1] * y;
+    private static double dot(final int @NotNull [] vec, final double x, final double y) {
+        return (double) vec[0] * x + (double) vec[1] * y;
     }
 
     // Values generated are guaranteed to be between -1.0 and 1.0, multiplied by amplitude.
-    public void add(double[] out, double xOffset, double zOffset, int xSize, int zSize, double xScale, double zScale, double amplitude)
-    {
+    public void add(
+        final double @NotNull [] out,
+        final double xOffset, final double zOffset,
+        final int xSize, final int zSize,
+        final double xScale, final double zScale,
+        final double amplitude
+    ) {
         int index = 0;
-        for(int dx = 0; dx < xSize; dx++)
-        {
-            double x = (xOffset + (double)dx) * xScale + xo;
-            for(int dz = 0; dz < zSize; dz++)
-            {
-                double z = (zOffset + (double)dz) * zScale + yo;
+        for (int dx = 0; dx < xSize; dx++) {
+            final double x = (xOffset + (double) dx) * xScale + this.xo;
+            for (int dz = 0; dz < zSize; dz++) {
+                final double z = (zOffset + (double) dz) * zScale + this.yo;
 
                 // Skew the input space to determine which simplex cell we're in
-                double s = (x + z) * F2;
-                int i = wrap(x + s);
-                int j = wrap(z + s);
+                final double s = (x + z) * F2;
+                final int i = fastFloor(x + s);
+                final int j = fastFloor(z + s);
 
                 // Unskew the cell origin back to (x, z) space
-                double t = (double)(i + j) * G2;
-                double X0 = (double)i - t;
-                double Z0 = (double)j - t;
-                double x0 = x - X0;
-                double z0 = z - Z0;
+                final double t = (double) (i + j) * G2;
+                final double X0 = (double) i - t;
+                final double Z0 = (double) j - t;
+                final double x0 = x - X0;
+                final double z0 = z - Z0;
 
                 // For the 2D case, the simplex shape is an equilateral triangle.
                 // Determine which simplex we are in.
-                int i1, j1; // Offsets for second (middle) corner of simplex in (i, j) coords
-                if(x0 > z0) // Lower triangle, XZ order: (0, 0) -> (1, 0) -> (1, 1)
+                final int i1;  // Offsets for second (middle) corner of simplex in (i, j) coords
+                final int j1;
+                if (x0 > z0) // Lower triangle, XZ order: (0, 0) -> (1, 0) -> (1, 1)
                 {
                     i1 = 1;
                     j1 = 0;
-                }
-                else // Upper triangle, ZX order: (0, 0) -> (0, 1) -> (1, 1)
+                } else // Upper triangle, ZX order: (0, 0) -> (0, 1) -> (1, 1)
                 {
                     i1 = 0;
                     j1 = 1;
@@ -90,58 +90,49 @@ public class SimplexNoise
                 // a step of (0, 1) in (i, j) means a step of (-c, 1 - c) in (x, z), where
                 // c = (3 - sqrt(3)) / 6
 
-                double x1 = (x0 - (double)i1) + G2; // Offsets for middle corner in (x, z) unskewed coords
-                double z1 = (z0 - (double)j1) + G2;
-                double x2 = (x0 - 1.0D) + 2D * G2;  // Offsets for last corner in (x, z) unskewed coords
-                double z2 = (z0 - 1.0D) + 2D * G2;
+                final double x1 = (x0 - (double) i1) + G2; // Offsets for middle corner in (x, z) unskewed coords
+                final double z1 = (z0 - (double) j1) + G2;
+                final double x2 = (x0 - 1.0D) + 2D * G2;  // Offsets for last corner in (x, z) unskewed coords
+                final double z2 = (z0 - 1.0D) + 2D * G2;
 
                 // Work out the hashed gradient indices of the three simplex corners
-                int ib = i & 0xff;
-                int jb = j & 0xff;
-                int gi0 = p[ib + p[jb]] % 12;
-                int gi1 = p[ib + i1 + p[jb + j1]] % 12;
-                int gi2 = p[ib + 1 + p[jb + 1]] % 12;
+                final int ib = i & 0xff;
+                final int jb = j & 0xff;
+                final int gi0 = this.p[ib + this.p[jb]] % 12;
+                final int gi1 = this.p[ib + i1 + this.p[jb + j1]] % 12;
+                final int gi2 = this.p[ib + 1 + this.p[jb + 1]] % 12;
 
                 // Calculate the contribution from the first corner
                 double t0 = 0.5D - x0 * x0 - z0 * z0;
-                double n0;
-                if(t0 < 0.0D)
-                {
+                final double n0;
+                if (t0 < 0.0D) {
                     n0 = 0.0D;
-                }
-                else
-                {
+                } else {
                     t0 *= t0;
                     n0 = t0 * t0 * dot(GRAD[gi0], x0, z0);
                 }
 
                 // Calculate the contribution from the second corner
                 double t1 = 0.5D - x1 * x1 - z1 * z1;
-                double n1;
-                if(t1 < 0.0D)
-                {
+                final double n1;
+                if (t1 < 0.0D) {
                     n1 = 0.0D;
-                }
-                else
-                {
+                } else {
                     t1 *= t1;
                     n1 = t1 * t1 * dot(GRAD[gi1], x1, z1);
                 }
 
                 // Calculate the contribution from the third corner
                 double t2 = 0.5D - x2 * x2 - z2 * z2;
-                double n2;
-                if(t2 < 0.0D)
-                {
+                final double n2;
+                if (t2 < 0.0D) {
                     n2 = 0.0D;
-                }
-                else
-                {
+                } else {
                     t2 *= t2;
                     n2 = t2 * t2 * dot(GRAD[gi2], x2, z2);
                 }
 
-                double value = 70 * (n0 + n1 + n2);
+                final double value = 70 * (n0 + n1 + n2);
                 out[index++] += value * amplitude;
             }
         }
diff --git a/game/core/src/test/java/TestNoise.java b/game/core/src/test/java/TestNoise.java
new file mode 100644
index 000000000..1e7cc850a
--- /dev/null
+++ b/game/core/src/test/java/TestNoise.java
@@ -0,0 +1,75 @@
+import net.minecraft.core.world.noise.ImprovedNoise;
+import net.minecraft.core.world.noise.PerlinNoise;
+import net.minecraft.core.world.noise.PerlinSimplexNoise;
+import net.minecraft.core.world.noise.SimplexNoise;
+import org.apache.logging.log4j.core.util.Assert;
+import org.jetbrains.annotations.NotNull;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.Random;
+
+public class TestNoise {
+    @Test
+    public void testImprovedPerlin() {
+        final @NotNull ImprovedNoise improvedNoise = new ImprovedNoise(new Random(0));
+
+        // 2D single value read
+        Assertions.assertEquals(-0.2610573416239221, improvedNoise.getValue(54.43272, 578.437364));
+
+        // 3D single value read
+        Assertions.assertEquals(0.05634836007719454, improvedNoise.getValue(35.43255, 434.487327, 42442.453));
+
+        // 3D region read
+        final double @NotNull [] expected = {-0.09566354243549174, -0.09566354243543021, -0.09566354243567703, -0.09566354243567703, -0.09566354243549227, -0.09566354243543072, -0.09566354243567755, -0.09566354243567755, -0.09566354243549227, -0.09566354243543072, -0.09566354243567755, -0.09566354243567755, -0.09566354243549227, -0.09566354243543072, -0.09566354243567755, -0.09566354243567755, -0.09566354243548755, -0.09566354243542602, -0.09566354243567284, -0.09566354243567284, -0.09566354243548808, -0.09566354243542653, -0.09566354243567336, -0.09566354243567336, -0.09566354243548808, -0.09566354243542653, -0.09566354243567336, -0.09566354243567336, -0.09566354243548808, -0.09566354243542653, -0.09566354243567336, -0.09566354243567336, -0.09566354243548755, -0.09566354243542602, -0.09566354243567284, -0.09566354243567284, -0.09566354243548808, -0.09566354243542653, -0.09566354243567336, -0.09566354243567336, -0.09566354243548808, -0.09566354243542653, -0.09566354243567336, -0.09566354243567336, -0.09566354243548808, -0.09566354243542653, -0.09566354243567336, -0.09566354243567336, -0.09566354243548755, -0.09566354243542602, -0.09566354243567284, -0.09566354243567284, -0.09566354243548808, -0.09566354243542653, -0.09566354243567336, -0.09566354243567336, -0.09566354243548808, -0.09566354243542653, -0.09566354243567336, -0.09566354243567336, -0.09566354243548808, -0.09566354243542653, -0.09566354243567336, -0.09566354243567336};
+        final double @NotNull [] out = new double[4 * 4 * 4];
+        improvedNoise.add(out, 0.0, 0.0, 0.0, 4, 4, 4, 512.0, 512.0, 512.0, 1.0);
+        Assertions.assertArrayEquals(expected, out);
+    }
+
+    @Test
+    public void testImprovedPerlinFBM() {
+        final @NotNull PerlinNoise perlinNoise = new PerlinNoise(0, 8);
+
+        // 2D single value read
+        Assertions.assertEquals(-40.12729053826283, perlinNoise.getValue(54.43272, 578.437364));
+
+        // 3D single value read
+        Assertions.assertEquals(67.0385971709751, perlinNoise.getValue(35.43255, 434.487327, 42442.453));
+
+        // 2D region read
+        final double @NotNull [] expected2d = new double[] {61.950994907627866, -8.08499106324795, 33.54088554556982, -55.19445688361638, 33.12453263018101, -21.356523887058557, -33.85847020057665, -65.83217787461822, -43.289010013795675, 17.76642722796277, 1.53508356692332, 28.917484979363007, -53.13527753764363, -51.201894007654545, 19.824587667787917, 23.29990684105529};
+        final double @NotNull [] out2d = new double[4 * 4];
+        perlinNoise.getRegion(out2d, 0.0, 0.0, 4, 4, 512.0, 512.0);
+        Assertions.assertArrayEquals(expected2d, out2d);
+
+        // 3D region read
+        final double @NotNull [] expected3d = new double[] {-52.94877239154948, -20.229741105662946, -13.726395113201534, 62.646048698626586, 26.012520791734683, -21.866601436110123, -20.480913125818166, 42.108104137207725, 18.876442162827974, 71.93128265471545, -73.80347864839412, 20.905108993467973, -24.837719079317772, 57.21713644456972, 62.312696753695384, 86.56386825865695, 21.540197362962093, -6.210718033344947, 30.66456418783226, 55.64510000757258, 32.49385747706018, 46.36145683657786, -39.075071541731745, 31.977961049298187, 53.17637535161104, -38.71491541542254, -4.376679379064646, -20.19764203108379, 95.65521786656561, -27.21197623996188, -5.447306439230173, -27.731024288593126, -5.1454843044222525, -8.380703785547745, -6.410801712473942, 58.910356263213075, 54.62464975380971, -3.4841527978120475, 10.413836844506623, 73.47587388332853, 18.824143915138368, 48.4389685183457, 72.36196271056366, -16.126273892553897, 9.172464647264015, 41.1305148374761, -57.43738803778975, -23.189534627720985, 47.730341363163674, -3.4708119038243765, 13.205547562947967, 21.57719685694134, -10.89760123693829, -7.510231751068822, 56.68282871047338, -26.310950214382274, 27.505318431779937, 121.47519536753694, -53.310737582378955, 10.619514015057254, 19.644574490880622, -18.675505072748763, 30.54855500643345, -36.43503182362011};
+        final double @NotNull [] out3d = new double[4 * 4 * 4];
+        perlinNoise.getRegion(out3d, 0.0, 0.0, 0.0, 4, 4, 4, 512.0, 512.0, 512.0);
+        Assertions.assertArrayEquals(expected3d, out3d);
+    }
+
+    @Test
+    public void testSimplex() {
+        final @NotNull SimplexNoise simplexNoise = new SimplexNoise(new Random(0));
+
+        // 3D region read
+        final double @NotNull [] expected = new double[] {-0.1742994852638034, -0.03465459789724085, -0.3536905075085449, 0.118920155221024, -0.03465459789706194, -0.3536905075092016, 0.11892015522101985, -0.4494057992596276, -0.35369050750903475, 0.11892015522084308, -0.4494057992596276, -0.346400636257933, 0.11892015522086728, -0.44940579925952345, -0.346400636257933, 0.6678974698632795};
+        final double @NotNull [] out = new double[4 * 4];
+        simplexNoise.add(out, 0.0, 0.0, 4, 4, 512.0, 512.0, 1.0);
+        Assertions.assertArrayEquals(expected, out);
+    }
+
+    @Test
+    public void testSimplexFBM() {
+        final @NotNull PerlinSimplexNoise perlinSimplexNoise = new PerlinSimplexNoise(new Random(0), 8);
+
+        // 2D region read
+        final double @NotNull [] expected = new double[] {50.84574324927897, 58.62470059533197, 29.96009128707059, -24.82665220496603, -14.95484987852672, -5.132647986808635, -56.84226192427461, -51.14227181041018, -8.522713417039947, 8.694440778390828, 1.1532938487621358, 24.27113975380712, -54.324564442351644, -14.929257621046592, 39.5916240857992, -38.96919968269769};
+        final double @NotNull [] out = new double[4 * 4];
+        perlinSimplexNoise.getRegion(out, 0.0, 0.0, 4, 4, 512.0, 512.0, 0.5);
+        Assertions.assertArrayEquals(expected, out);
+    }
+}
