diff --git a/game/client/src/main/java/net/minecraft/client/gui/container/ScreenActivator.java b/game/client/src/main/java/net/minecraft/client/gui/container/ScreenActivator.java
index 8078651e2..d59d6a034 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/container/ScreenActivator.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/container/ScreenActivator.java
@@ -1,12 +1,16 @@
 package net.minecraft.client.gui.container;
 
+import net.minecraft.client.Minecraft;
 import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.ItemElement;
 import net.minecraft.client.render.renderer.GLRenderer;
+import net.minecraft.client.util.helper.ItemDragHandler;
 import net.minecraft.core.InventoryAction;
 import net.minecraft.core.block.entity.TileEntityActivator;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.player.inventory.container.ContainerInventory;
 import net.minecraft.core.player.inventory.menu.MenuActivator;
+import net.minecraft.core.player.inventory.slot.Slot;
 import net.minecraft.core.sound.SoundCategory;
 
 import java.util.ArrayList;
@@ -17,7 +21,7 @@ public class ScreenActivator extends ScreenContainerAbstract {
     protected final List<ButtonElement> slotButtons = new ArrayList<>();
 
     public ScreenActivator(ContainerInventory inventory, TileEntityActivator activatorBlock) {
-        super(new MenuActivator(inventory, activatorBlock));
+        super(new MenuActivator(inventory, activatorBlock), ItemDragHandlerActivator::new);
         this.tileEntityActivator = activatorBlock;
     }
 
@@ -73,4 +77,65 @@ public class ScreenActivator extends ScreenContainerAbstract {
             drawTexturedModalRect(startX + 18 * this.tileEntityActivator.stackSelector, startY, 176, 0, 18, 34);
         }
     }
+
+    private static class ItemDragHandlerActivator extends ItemDragHandler {
+        public ItemDragHandlerActivator(Minecraft minecraft, ScreenContainerAbstract screen, ItemElement itemElement) {
+            super(minecraft, screen, itemElement);
+            assert this.container instanceof ScreenActivator;
+        }
+
+        private byte dragAction;
+        private static final byte NONE = 0, LOCK = 1, UNLOCK = 2;
+
+        @Override
+        protected void mousePressed(int x, int y, Slot slot, int button) {
+            if (button != 1 || super.isDragging() ||
+                super.getGrabbedItem() != null || slot.getItemStack() != null
+            ) {
+                super.mousePressed(x, y, slot, button);
+                return;
+            }
+            this.draggingButton = button;
+            this.draggedSlots.clear();
+            this.dragAction = NONE;
+        }
+
+        @Override
+        protected void mouseReleased(int x, int y, Slot slot, int button) {
+            if (button != 1 || this.draggingButton != 1 || this.cancelButtonRelease == 1 ||
+                !super.isDragging() || this.draggingItemStack != null
+            ) {
+                super.mouseReleased(x, y, slot, button);
+                return;
+            }
+            super.stopDragging();
+        }
+
+        @Override
+        protected void onDragOverSlot(Slot slot) {
+            if (slot == null) return;
+            if (this.draggingButton != 1 || this.draggingItemStack != null) {
+                super.onDragOverSlot(slot);
+                return;
+            }
+            final var activator = (ScreenActivator)this.container;
+            if (slot.index < 0 || slot.index >= activator.slotButtons.size()) return;    
+
+            final var button = activator.slotButtons.get(slot.index);
+            if (!button.enabled) return;
+            if (activator.tileEntityActivator.getItem(button.id) != null) return;
+
+            final var action = activator.tileEntityActivator.locked(button.id) ? UNLOCK : LOCK;
+            if (this.dragAction == NONE) this.dragAction = action;
+            else if (this.dragAction != action) return;
+
+            activator.mc.playerController.handleInventoryMouseClick(activator.inventorySlots.containerId, InventoryAction.LOCK, new int[]{button.id, 0}, this.mc.thePlayer);
+            if (button.playSound) activator.mc.sndManager.playSound("random.click", SoundCategory.GUI_SOUNDS, 1.0F, 1.0F);
+        }
+
+        @Override
+        protected void onDragOutsideOfSlots() {
+            this.dragAction = NONE;
+        }
+    }
 }
\ No newline at end of file
diff --git a/game/client/src/main/java/net/minecraft/client/gui/container/ScreenContainerAbstract.java b/game/client/src/main/java/net/minecraft/client/gui/container/ScreenContainerAbstract.java
index 35af4f5ae..064a9a1b3 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/container/ScreenContainerAbstract.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/container/ScreenContainerAbstract.java
@@ -31,6 +31,9 @@ import net.minecraft.core.player.inventory.menu.*;
 import net.minecraft.core.player.inventory.slot.Slot;
 import net.minecraft.core.player.inventory.slot.SlotResult;
 import net.minecraft.core.player.inventory.slot.SlotCreative;
+
+import java.util.List;
+
 import org.jetbrains.annotations.NotNull;
 import org.lwjgl.input.Keyboard;
 
@@ -43,13 +46,22 @@ public abstract class ScreenContainerAbstract extends Screen {
     public ItemDragHandler itemDragHandler;
 
     public ScreenContainerAbstract(final MenuAbstract container) {
+        this(container, ItemDragHandler::new);
+    }
+
+    @FunctionalInterface
+    protected static interface ItemDragHandlerCtor {
+        @NotNull ItemDragHandler make(Minecraft minecraft, ScreenContainerAbstract screen, ItemElement itemElement);
+    }
+
+    protected ScreenContainerAbstract(final MenuAbstract container, final ItemDragHandlerCtor dragHandlerCtor) {
         Minecraft mc = Minecraft.getMinecraft();
         this.xSize = 176;
         this.ySize = 166;
         this.inventorySlots = container;
         this.tooltipElement = new TooltipElement(mc);
         this.itemElement = new ItemElement(mc);
-        this.itemDragHandler = new ItemDragHandler(mc, this, this.itemElement);
+        this.itemDragHandler = dragHandlerCtor.make(mc, this, this.itemElement);
     }
 
     @Override
@@ -134,6 +146,33 @@ public abstract class ScreenContainerAbstract extends Screen {
         return null;
     }
 
+    public boolean getHasMouseMovedOverSlot(final Slot slot, int x0, int y0, int x1, int y1) {
+        final int xo = (this.width - this.xSize) / 2;
+        final int yo = (this.height - this.ySize) / 2;
+        x0 -= xo; x1 -= xo;
+        y0 -= yo; y1 -= yo;
+        final int mxMin, mxMax, myMin, myMax; {
+            mxMin = Math.min(x0,x1); mxMax = Math.max(x0,x1);
+            myMin = Math.min(y0,y1); myMax = Math.max(y0,y1);
+        }
+        final int sxMin, sxMax, syMin, syMax; {
+            sxMin = slot.x - 1; sxMax = slot.x + 16 + 1;
+            syMin = slot.y - 1; syMax = slot.y + 16 + 1;
+        }
+        // test if at least 2 parralel sides of the rectange between xy0 xy1 intersects with the button
+        // this sacrifices (skips) diagonal dragging in exchange for a much simpler logic
+        if (mxMin >= sxMin && mxMax < sxMax) return myMin < syMax && myMax > syMin;
+        if (myMin >= syMin && myMax < syMax) return mxMin < sxMax && mxMax > sxMin;
+        return false;
+    }
+
+    public void getSlotsBetweenPositions(int x0, int y0, int x1, int y1, @NotNull List<Slot> outBuffer) {
+        for (int k = 0; k < this.inventorySlots.slots.size(); k++) {
+            final Slot slot = this.inventorySlots.slots.get(k);
+            if (getHasMouseMovedOverSlot(slot, x0, y0, x1, y1)) outBuffer.add(slot);
+        }
+    }
+
     @Override
     public void init() {
         super.init();
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 fb11ab398..005acdcb5 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
@@ -619,7 +619,6 @@ public final class BlockModelDispatcher
         addDispatch(new BlockModelGeneric<>(Blocks.BOULDER_MAGMATIC, loadDataModel("minecraft:block/boulder_magmatic")).render3D(false));
         addDispatch(new BlockModelGeneric<>(Blocks.BOULDER_SULFURIC, loadDataModel("minecraft:block/boulder_sulfuric")).render3D(false));
         addDispatch(new BlockModelGeneric<>(Blocks.SULFUR, loadDataModel("minecraft:block/sulfur")));
-        addDispatch(new BlockModelGeneric<>(Blocks.SULFUR_HARDENED, loadDataModel("minecraft:block/sulfur_hardened")));
         addDispatch(new BlockModelGeneric<>(Blocks.EMBER, loadDataModel("minecraft:block/ember")));
         addDispatch(new BlockModelGeneric<>(Blocks.SLATE_CARVED, loadDataModel("minecraft:block/carved_slate")));
         addDispatch(new BlockModelGeneric<>(Blocks.BRIMSTONE, loadDataModel("minecraft:block/brimstone")));
diff --git a/game/client/src/main/java/net/minecraft/client/util/helper/ItemDragHandler.java b/game/client/src/main/java/net/minecraft/client/util/helper/ItemDragHandler.java
index a51f2bcb6..bc9cc7de2 100644
--- a/game/client/src/main/java/net/minecraft/client/util/helper/ItemDragHandler.java
+++ b/game/client/src/main/java/net/minecraft/client/util/helper/ItemDragHandler.java
@@ -29,12 +29,15 @@ public class ItemDragHandler extends Gui {
 	
 	private final IntSet cancelRelease = new IntArraySet();
 	
-	private int cancelButtonRelease = -1; 
-	
-	private int draggingButton = -1;
-	private ItemStack draggingItemStack;
-	private final List<Slot> draggedSlots = new ArrayList<>();
+	protected int cancelButtonRelease = -1; 
 	
+	protected int draggingButton = -1;
+	protected ItemStack draggingItemStack;
+	protected final List<Slot> draggedSlots = new ArrayList<>();
+
+	private int lastX = Integer.MAX_VALUE; private int lastY = Integer.MAX_VALUE;
+	private final ArrayList<Slot> dragOverBuffer = new ArrayList<>(2);
+
 	private ItemStack renderItemStack;
 	private int renderItemStackCount;
 	
@@ -55,38 +58,46 @@ public class ItemDragHandler extends Gui {
         this.renderOffsetY = 0;
 		
 		if(isDragging()) {
-			Slot slot = getSlotAt(mouseX, mouseY);
+			this.dragOverBuffer.clear();
+			if (Math.max(this.lastX, this.lastY) == Integer.MAX_VALUE) {
+				final var slot = this.container.getSlotAtPosition(mouseX, mouseY);
+				if (slot != null) dragOverBuffer.add(slot);
+			} else {
+				this.container.getSlotsBetweenPositions(this.lastX, this.lastY, mouseX, mouseY, this.dragOverBuffer);
+			}
+			this.lastX = mouseX;
+			this.lastY = mouseY;
+			if (this.dragOverBuffer.size() == 0) this.onDragOutsideOfSlots();
+			else for (final var slot : this.dragOverBuffer) onDragOverSlot(slot);
+
+			if (this.draggedSlots.size() == 0) return;
+
+			this.renderItemStack = this.draggingItemStack.copy();
+			this.renderItemStack.stackSize = 1;
+
+			boolean isCreativeDragging = this.draggingButton == 2 && !this.mc.thePlayer.getGamemode().hasBlockConsumption();
 			
-			onDragOverSlot(slot);
+			if(isCreativeDragging) {
+				this.renderItemStackCount = this.draggingItemStack.getMaxStackSize();
+			}else if(this.draggingButton == 1) {
+				this.renderItemStackCount = 1;
+			}else {
+				this.renderItemStackCount = this.draggingItemStack.stackSize / this.draggedSlots.size();
+			}
 			
-			if(this.draggedSlots.size() > 1) {
-                this.renderItemStack = this.draggingItemStack.copy();
-                this.renderItemStack.stackSize = 1;
-
-				boolean isCreativeDragging = this.draggingButton == 2 && !this.mc.thePlayer.getGamemode().hasBlockConsumption();
-				
-				if(isCreativeDragging) {
-                    this.renderItemStackCount = this.draggingItemStack.getMaxStackSize();
-				}else if(this.draggingButton == 1) {
-                    this.renderItemStackCount = 1;
-				}else {
-                    this.renderItemStackCount = this.draggingItemStack.stackSize / this.draggedSlots.size();
-				}
-				
-				for(int i = 0; i < this.draggedSlots.size(); i++) {
-					drawSlotOverlayWhileDragging(this.draggedSlots.get(i));
-				}
-				
-				if(isCreativeDragging) {
-                    this.renderItemStack.stackSize = 1;
-				}else {
-                    this.renderItemStack.stackSize = this.draggingItemStack.stackSize - (this.draggedSlots.size() * this.renderItemStackCount);
-				}
+			for(int i = 0; i < this.draggedSlots.size(); i++) {
+				drawSlotOverlayWhileDragging(this.draggedSlots.get(i));
+			}
+			
+			if(isCreativeDragging) {
+				this.renderItemStack.stackSize = 1;
+			}else {
+				this.renderItemStack.stackSize = this.draggingItemStack.stackSize - (this.draggedSlots.size() * this.renderItemStackCount);
 			}
 		}
 	}
 	
-	private void onDragOverSlot(Slot slot) {
+	protected void onDragOverSlot(Slot slot) {
 		if(slot == null) return;
 		
 		boolean isCreativeDragging = this.draggingButton == 2 && !this.mc.thePlayer.getGamemode().hasBlockConsumption();
@@ -102,6 +113,8 @@ public class ItemDragHandler extends Gui {
 			}
 		}
 	}
+
+	protected void onDragOutsideOfSlots() {}
 	
 	private void drawSlotOverlayWhileDragging(Slot slot) {
 		if(slot == null) throw new NullPointerException("Slot is null");
@@ -134,7 +147,7 @@ public class ItemDragHandler extends Gui {
 		boolean space = Keyboard.isKeyDown(Keyboard.KEY_SPACE);
 		boolean mod = shift || control || alt || space;
 		
-		Slot slot = getSlotAt(x, y);
+		Slot slot = this.container.getSlotAtPosition(x, y);
 		
 		if(pressed) {
 			if(mod) {
@@ -157,7 +170,7 @@ public class ItemDragHandler extends Gui {
         this.mc.playerController.handleInventoryMouseClick(this.container.inventorySlots.containerId, action, args, this.mc.thePlayer);
 	}
 	
-	private void mousePressed(final int x, final int y, final Slot slot, int button) {
+	protected void mousePressed(final int x, final int y, final Slot slot, int button) {
 		ItemStack stack = getGrabbedItem();
 		
 		if(button == 0) {
@@ -182,7 +195,7 @@ public class ItemDragHandler extends Gui {
 		}
 	}
 	
-	private void mouseReleased(final int x, final int y, final Slot slot, int button) {
+	protected void mouseReleased(final int x, final int y, final Slot slot, int button) {
 		ItemStack stack = getGrabbedItem();
 		
 		if(stack == null) {
@@ -224,10 +237,11 @@ public class ItemDragHandler extends Gui {
 		}
 	}
 	
-	private void stopDragging() {
+	protected final void stopDragging() {
         this.draggingButton = -1;
         this.draggingItemStack = null;
         this.draggedSlots.clear();
+		this.lastX = this.lastY = Integer.MAX_VALUE;
 	}
 	
 	private void spreadItemsAcrossDraggedSlots(int x, int y, int mode) {
@@ -267,14 +281,10 @@ public class ItemDragHandler extends Gui {
 		return this.draggingButton != -1;
 	}
 	
-	private Slot getSlotAt(int x, int y) {
-		return this.container.getSlotAtPosition(x, y);
-	}
-	
-	private ItemStack getGrabbedItem() {
+	protected final ItemStack getGrabbedItem() {
 		return this.mc.thePlayer.inventory.getHeldItemStack();
 	}
-	
+
 	public boolean isSlotDragged(Slot slot) {
 		return this.draggedSlots.size() > 1 && this.draggedSlots.contains(slot);
 	}
diff --git a/game/client/src/main/resources/assets/minecraft/models/block/block.json b/game/client/src/main/resources/assets/minecraft/models/block/block.json
index aefa892bf..cdb9058db 100644
--- a/game/client/src/main/resources/assets/minecraft/models/block/block.json
+++ b/game/client/src/main/resources/assets/minecraft/models/block/block.json
@@ -17,19 +17,18 @@
             "scale":[ 0.5, 0.5, 0.5 ]
         },
         "thirdperson_righthand": {
-            "rotation": [ 75, 45, 0 ],
+            "rotation": [75, 135, 0],
             "translation": [ 0, 2.5, 0],
             "scale": [ 0.375, 0.375, 0.375 ]
         },
         "firstperson_righthand": {
-            "rotation": [ 0, 45, 0 ],
+            "rotation": [ 0, 135, 0 ],
             "translation": [ 0, 0, 0 ],
             "scale": [ 0.40, 0.40, 0.40 ]
         },
         "firstperson_lefthand": {
-            "rotation": [ 0, 225, 0 ],
-            "translation": [ 0, 0, 0 ],
-            "scale": [ 0.40, 0.40, 0.40 ]
+            "rotation": [0, 135, 0],
+            "scale": [0.4, 0.4, 0.4]
         }
     }
 }
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/fluid/acid/flowing.emiss.png b/game/client/src/main/resources/assets/minecraft/textures/block/fluid/acid/flowing.emiss.png
index 8201df983..b24cb7f1c 100644
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/fluid/acid/flowing.emiss.png and b/game/client/src/main/resources/assets/minecraft/textures/block/fluid/acid/flowing.emiss.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/fluid/acid/flowing.emiss.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/block/fluid/acid/flowing.emiss.png.mcmeta
index 8dabee5ed..b20a20474 100644
--- a/game/client/src/main/resources/assets/minecraft/textures/block/fluid/acid/flowing.emiss.png.mcmeta
+++ b/game/client/src/main/resources/assets/minecraft/textures/block/fluid/acid/flowing.emiss.png.mcmeta
@@ -11,14 +11,7 @@
       4,
       5,
       6,
-      7,
-      8,
-      9,
-      10,
-      11,
-      12,
-      13,
-      14
+      7
     ]
   }
 }
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/fluid/acid/flowing.png b/game/client/src/main/resources/assets/minecraft/textures/block/fluid/acid/flowing.png
index f93a9ab79..5642ed70d 100644
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/fluid/acid/flowing.png and b/game/client/src/main/resources/assets/minecraft/textures/block/fluid/acid/flowing.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/fluid/acid/flowing.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/block/fluid/acid/flowing.png.mcmeta
index 8dabee5ed..b20a20474 100644
--- a/game/client/src/main/resources/assets/minecraft/textures/block/fluid/acid/flowing.png.mcmeta
+++ b/game/client/src/main/resources/assets/minecraft/textures/block/fluid/acid/flowing.png.mcmeta
@@ -11,14 +11,7 @@
       4,
       5,
       6,
-      7,
-      8,
-      9,
-      10,
-      11,
-      12,
-      13,
-      14
+      7
     ]
   }
 }
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/fluid/acid/still.emiss.png b/game/client/src/main/resources/assets/minecraft/textures/block/fluid/acid/still.emiss.png
index a3ddce1ed..14a448763 100644
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/fluid/acid/still.emiss.png and b/game/client/src/main/resources/assets/minecraft/textures/block/fluid/acid/still.emiss.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/fluid/acid/still.emiss.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/block/fluid/acid/still.emiss.png.mcmeta
index 9d8c68748..e0fcfa6e6 100644
--- a/game/client/src/main/resources/assets/minecraft/textures/block/fluid/acid/still.emiss.png.mcmeta
+++ b/game/client/src/main/resources/assets/minecraft/textures/block/fluid/acid/still.emiss.png.mcmeta
@@ -1,7 +1,7 @@
 {
   "animation": {
     "interpolate": true,
-    "frametime": 20,
+    "frametime": 30,
     "frames": [
       0,
       1,
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/fluid/acid/still.png b/game/client/src/main/resources/assets/minecraft/textures/block/fluid/acid/still.png
index 9044a1ce7..455c9dba4 100644
Binary files a/game/client/src/main/resources/assets/minecraft/textures/block/fluid/acid/still.png and b/game/client/src/main/resources/assets/minecraft/textures/block/fluid/acid/still.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/block/fluid/acid/still.png.mcmeta b/game/client/src/main/resources/assets/minecraft/textures/block/fluid/acid/still.png.mcmeta
index 9d8c68748..781fd9305 100644
--- a/game/client/src/main/resources/assets/minecraft/textures/block/fluid/acid/still.png.mcmeta
+++ b/game/client/src/main/resources/assets/minecraft/textures/block/fluid/acid/still.png.mcmeta
@@ -1,12 +1,16 @@
 {
   "animation": {
     "interpolate": true,
-    "frametime": 20,
+    "frametime": 30,
     "frames": [
       0,
       1,
       2,
-      3
+      3,
+      0,
+      3,
+      2,
+      1
     ]
   }
 }
\ No newline at end of file
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicBrimthaw.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicBrimthaw.java
index a8884933e..ffe98004f 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicBrimthaw.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicBrimthaw.java
@@ -16,6 +16,7 @@ public class BlockLogicBrimthaw extends BlockLogicMagma {
 
     public BlockLogicBrimthaw(@NotNull Block<?> block) {
         super(block);
+        block.setTicking(true);
     }
 
     @Override
@@ -25,7 +26,7 @@ public class BlockLogicBrimthaw extends BlockLogicMagma {
         for (final Direction dir : Direction.all) {
             final Block<?> block = world.getBlockType(tilePos.add(dir, queryPos));
             final Material adjacentMaterial = block.getMaterial();
-            if (adjacentMaterial == Materials.WATER) {
+            if (adjacentMaterial == Materials.WATER ||  adjacentMaterial == Materials.LAVA) {
                 return false;
             }
             canMelt |= adjacentMaterial == Materials.ACID;
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicFluid.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFluid.java
index 01e71607e..ebabd1f2f 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicFluid.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFluid.java
@@ -129,6 +129,10 @@ public abstract class BlockLogicFluid extends BlockLogic {
         return this.fluid.tickDelay();
     }
 
+    public int tickDelay(final @NotNull World world, final @NotNull TilePosc tilePos) {
+        return this.fluid.getTickDelay(this, world, tilePos);
+    }
+
     @Override
     public float getBrightness(final @NotNull WorldSource source, final @NotNull TilePosc tilePos) {
         final float br = source.getLightBrightness(tilePos);
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicFluidFlowing.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFluidFlowing.java
index 55dd2555a..9318f640f 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicFluidFlowing.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFluidFlowing.java
@@ -68,7 +68,7 @@ public class BlockLogicFluidFlowing extends BlockLogicFluid {
                     world.setBlockTypeNotify(tilePos, Blocks.AIR);
                 } else {
                     world.setBlockDataNotify(tilePos, localFlowDecay);
-                    world.scheduleBlockUpdate(tilePos, this.block, tickDelay());
+                    world.scheduleBlockUpdate(tilePos, this.block, tickDelay(world, tilePos));
                     world.notifyBlocksOfNeighborChange(tilePos, this.block);
                 }
             } else {
@@ -141,7 +141,7 @@ public class BlockLogicFluidFlowing extends BlockLogicFluid {
             if (!isFluidBlocking(world, queryPos.set(checkX, checkY - 1, checkZ))) {
                 return l;
             }
-            if (l >= 4) {
+            if (l >= this.fluid.getMaxHorizontalSpread(this, world, tilePos)) {
                 continue;
             }
             int k2 = getSlopeDistance(world, queryPos.set(checkX, checkY, checkZ), l + 1, d);
@@ -226,7 +226,7 @@ public class BlockLogicFluidFlowing extends BlockLogicFluid {
     public void onPlacedByWorld(@NotNull World world, @NotNull TilePosc tilePos) {
         super.onPlacedByWorld(world, tilePos);
         if (world.getBlockType(tilePos) == this.block) {
-            world.scheduleBlockUpdate(tilePos, this.block, tickDelay());
+            world.scheduleBlockUpdate(tilePos, this.block, tickDelay(world, tilePos));
         }
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicFluidStill.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFluidStill.java
index cceaa8ec0..67f80c927 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicFluidStill.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFluidStill.java
@@ -30,7 +30,7 @@ public class BlockLogicFluidStill extends BlockLogicFluid {
         world.noNeighborUpdate = true;
         world.setBlockTypeData(tilePos, this.blockFlowing, meta);
         world.markBlocksDirty(tilePos, tilePos);
-        world.scheduleBlockUpdate(tilePos, this.blockFlowing, tickDelay());
+        world.scheduleBlockUpdate(tilePos, this.blockFlowing, tickDelay(world, tilePos));
         world.noNeighborUpdate = false;
     }
 
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicMagma.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicMagma.java
index 4083ba26a..6c1d51c53 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicMagma.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicMagma.java
@@ -51,11 +51,11 @@ public class BlockLogicMagma extends BlockLogic {
 
     public boolean canMelt(@NotNull World world, @NotNull TilePosc tilePos) {
         boolean canMelt = false;
-        TilePos queryPos = new TilePos();
+        final TilePos queryPos = new TilePos();
         for (final var dir : Direction.all) {
             Block<?> block = world.getBlockType(tilePos.add(dir, queryPos));
             Material adjacentMaterial = block.getMaterial();
-            if (adjacentMaterial == Materials.WATER) {
+            if (adjacentMaterial == Materials.WATER ||  adjacentMaterial == Materials.ACID) {
                 return false;
             }
             canMelt |= adjacentMaterial == Materials.LAVA;
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicSulfurHardened.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSulfurHardened.java
deleted file mode 100644
index dec03b406..000000000
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicSulfurHardened.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package net.minecraft.core.block;
-
-import net.minecraft.core.block.entity.TileEntity;
-import net.minecraft.core.entity.Mob;
-import net.minecraft.core.entity.player.Player;
-import net.minecraft.core.enums.EnumDropCause;
-import net.minecraft.core.item.Item;
-import net.minecraft.core.item.ItemStack;
-import net.minecraft.core.sound.SoundCategory;
-import net.minecraft.core.util.helper.Side;
-import net.minecraft.core.world.World;
-import net.minecraft.core.world.pos.TilePosc;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.Random;
-
-public class BlockLogicSulfurHardened extends BlockLogicSulfur {
-
-    public BlockLogicSulfurHardened(@NotNull Block<?> block) {
-        super(block);
-        block.setTicking(false);
-    }
-
-    @Override
-    public ItemStack[] getBreakResult(@NotNull World world, @NotNull EnumDropCause dropCause, int data, @Nullable TileEntity tileEntity) {
-        return switch (dropCause) {
-            case PICK_BLOCK, SILK_TOUCH -> new ItemStack[]{new ItemStack(Blocks.SULFUR_HARDENED)};
-            default -> null;
-        };
-    }
-
-    @Override
-    public void onDestroyedByPlayer(final @NotNull World world, final @NotNull TilePosc tilePos, final @NotNull Side side, final int data, final @NotNull Player player, final @Nullable Item item) {
-        super.onDestroyedByPlayer(world, tilePos, side, data, player, item);
-        world.playSoundEffect(
-            player,
-            SoundCategory.WORLD_SOUNDS,
-            tilePos.x() + 0.5,
-            tilePos.y() + 0.5,
-            tilePos.z() + 0.5,
-            "mob.skeleton",
-            1.0F,
-            2.0F
-        );
-
-        world.playSoundEffect(
-            player,
-            SoundCategory.WORLD_SOUNDS,
-            tilePos.x() + 0.5,
-            tilePos.y() + 0.5,
-            tilePos.z() + 0.5,
-            "step.stone",
-            1.0F,
-            0.8F
-        );
-    }
-
-    @Override
-    public boolean canMelt(@NotNull World world, @NotNull TilePosc tilePos) {
-        return false;
-    }
-
-    @Override
-    public void onNeighborChanged(@NotNull World world, @NotNull TilePosc tilePos, @NotNull Block<?> block) {
-    }
-
-    @Override
-    public void onPlacedByWorld(@NotNull World world, @NotNull TilePosc tilePos) {
-    }
-
-    @Override
-    public void updateTick(@NotNull World world, @NotNull TilePosc tilePos, @NotNull Random rand, boolean isRandomTick) {
-    }
-
-    @Override
-    public void onPlacedByMob(final @NotNull World world, final @NotNull TilePosc tilePos, final @NotNull Side side, final @NotNull Mob mob, final double xHit, final double yHit) {
-        world.playSoundEffect(
-            mob,
-            SoundCategory.WORLD_SOUNDS,
-            tilePos.x() + 0.5,
-            tilePos.y() + 0.5,
-            tilePos.z() + 0.5,
-            "mob.skeleton",
-            1.0F,
-            2.0F
-        );
-        world.playSoundEffect(
-            mob,
-            SoundCategory.WORLD_SOUNDS,
-            tilePos.x() + 0.5,
-            tilePos.y() + 0.5,
-            tilePos.z() + 0.5,
-            "step.stone",
-            1.0F,
-            0.8F
-        );
-        this.onPlacedOnSide(world, tilePos, side, xHit, yHit);
-    }
-}
\ No newline at end of file
diff --git a/game/core/src/main/java/net/minecraft/core/block/Blocks.java b/game/core/src/main/java/net/minecraft/core/block/Blocks.java
index 5bfa788ba..907e57760 100644
--- a/game/core/src/main/java/net/minecraft/core/block/Blocks.java
+++ b/game/core/src/main/java/net/minecraft/core/block/Blocks.java
@@ -1512,9 +1512,6 @@ public final class Blocks {
     public static final Block<?> SULFUR = register("sulfur", "minecraft:block/sulfur", 1098, BlockLogicSulfur::new)
         .withSound(BlockSounds.SAND).withHardness(0.5f).withOverrideColor(MaterialColor.paintedYellow)
         .withTags(BlockTags.MINEABLE_BY_SHOVEL, BlockTags.NETHER_SURFACE_BLOCK, BlockTags.NETHER_MOBS_SPAWN, BlockTags.CAVES_CUT_THROUGH, BlockTags.INFINITE_BURN_SULFURIC);
-    public static final Block<?> SULFUR_HARDENED = register("sulfur_hardened", "minecraft:block/sulfur_hardened", 1099, BlockLogicSulfurHardened::new)
-        .withSound(BlockSounds.SAND).withHardness(0.5f).withOverrideColor(MaterialColor.paintedYellow)
-        .withTags(BlockTags.MINEABLE_BY_PICKAXE, BlockTags.NETHER_SURFACE_BLOCK, BlockTags.NETHER_MOBS_SPAWN, BlockTags.CAVES_CUT_THROUGH, BlockTags.INFINITE_BURN_SULFURIC);
 
     public static final @NotNull Block<?> PRESSURE_PLATE_COBBLE_BASALT = register("pressureplate.cobble.basalt", "minecraft:block/pressure_plate_cobble_basalt", 1100, (b) -> new BlockLogicPressurePlate<>(b, Player.class, Materials.BASALT))
         .withSound(BlockSounds.STONE).withHardness(0.5F).withDisabledNeighborNotifyOnMetadataChange()
diff --git a/game/core/src/main/java/net/minecraft/core/block/Fluid.java b/game/core/src/main/java/net/minecraft/core/block/Fluid.java
index 531d4e431..73c90a336 100644
--- a/game/core/src/main/java/net/minecraft/core/block/Fluid.java
+++ b/game/core/src/main/java/net/minecraft/core/block/Fluid.java
@@ -11,6 +11,14 @@ import java.util.Random;
 public interface Fluid {
     int tickDelay();
 
+    default int getTickDelay(final @NotNull BlockLogicFluid logicFluid, final @NotNull World world, final @NotNull TilePosc tilePos) {
+        return tickDelay();
+    }
+
+    default int getMaxHorizontalSpread(final @NotNull BlockLogicFluid logicFluid, final @NotNull World world, final @NotNull TilePosc tilePos) {
+        return 4;
+    }
+
     @Deprecated
     default void animationTick(final @NotNull BlockLogicFluid logicFluid, final @NotNull World world, final int x, final int y, final int z, final @NotNull Random rand) {
         animationTick(logicFluid, world, new TilePos(x, y, z), rand);
diff --git a/game/core/src/main/java/net/minecraft/core/block/FluidAcid.java b/game/core/src/main/java/net/minecraft/core/block/FluidAcid.java
index fea0f28f9..62745563d 100644
--- a/game/core/src/main/java/net/minecraft/core/block/FluidAcid.java
+++ b/game/core/src/main/java/net/minecraft/core/block/FluidAcid.java
@@ -17,10 +17,15 @@ public class FluidAcid implements Fluid {
 	public FluidAcid() {
 	}
 
+	@Override
 	public int tickDelay() {
 		return 40;
 	}
 
+	private static boolean isNether(@NotNull World world) {
+		return world.getWorldType().hasTag(WorldTypeTags.NETHER);
+	}
+
 	@Override
 	public void animationTick(@NotNull BlockLogicFluid logicFluid, @NotNull World world, @NotNull TilePosc tilePos, @NotNull Random rand) {
 		int data = world.getBlockData(tilePos) & 15;
@@ -53,32 +58,7 @@ public class FluidAcid implements Fluid {
 
 	@Override
 	public boolean checkForHarden(@NotNull BlockLogicFluid logicFluid, @NotNull World world, @NotNull TilePosc tilePos, @NotNull Material encountered) {
-		if (encountered == Materials.LAVA || encountered == Materials.WATER) {
-			final int data = world.getBlockData(tilePos) & 15;
-			final boolean netherWorld = world.getWorldType().hasTag(WorldTypeTags.NETHER);
-			if (netherWorld) {
-				if (data == 0) {
-					world.setBlockTypeNotify(tilePos, Blocks.BRIMTHAW);
-				} else {
-					world.setBlockTypeNotify(tilePos, Blocks.BRIMSTONE);
-				}
-			} else {
-				if (data == 0) {
-					world.setBlockTypeNotify(tilePos, Blocks.SULFUR);
-				} else {
-					world.setBlockTypeNotify(tilePos, Blocks.SULFUR_HARDENED);
-				}
-			}
-
-			world.playSoundEffect(null, SoundCategory.WORLD_SOUNDS, (float) tilePos.x() + 0.5F, (float) tilePos.y() + 0.5F, (float) tilePos.z() + 0.5F, "random.fizz", 0.5F, 2.6F + (world.rand.nextFloat() - world.rand.nextFloat()) * 0.8F);
-
-			for (int i = 0; i < 8; ++i) {
-				world.spawnParticle("largesmoke", (double) tilePos.x() + Math.random(), (double) tilePos.y() + 1.01, (double) tilePos.z() + Math.random(), 0.0F, 0.0F, 0.0F, 0, false);
-			}
-			return true;
-		} else {
-			return false;
-		}
+		return FluidHardening.hardenAcid(world, tilePos, encountered);
 	}
 
 	public boolean shouldTick() {
@@ -88,10 +68,22 @@ public class FluidAcid implements Fluid {
 	public void updateTickStill(@NotNull BlockLogicFluid logicFluid, @NotNull World world, @NotNull TilePosc tilePos, @NotNull Random rand) {
 	}
 
+	@Override
+	public int getTickDelay(@NotNull BlockLogicFluid logicFluid, @NotNull World world, @NotNull TilePosc tilePos) {
+		return isNether(world) ? 25 : 40;
+	}
+
+	@Override
 	public byte getFlowDecayMod(@NotNull BlockLogicFluid logicFluid, @NotNull World world, @NotNull TilePosc tilePos) {
-		return 2;
+		return isNether(world) ? (byte) 1 : (byte) 2;
+	}
+
+	@Override
+	public int getMaxHorizontalSpread(@NotNull BlockLogicFluid logicFluid, @NotNull World world, @NotNull TilePosc tilePos) {
+		return isNether(world) ? 8 : 4;
 	}
 
+	@Override
 	public boolean canBecomeSource(@NotNull BlockLogicFluid logicFluid, @NotNull World world, @NotNull TilePosc tilePos, @NotNull Random rand) {
 		return false;
 	}
@@ -104,5 +96,6 @@ public class FluidAcid implements Fluid {
 	public boolean canSpreadTo(@NotNull BlockLogicFluid logicFluid, @NotNull World world, @NotNull TilePos tilePos, @NotNull Material material) {
 		return material != Materials.LAVA && material != Materials.WATER;
 	}
+
 }
 
diff --git a/game/core/src/main/java/net/minecraft/core/block/FluidHardening.java b/game/core/src/main/java/net/minecraft/core/block/FluidHardening.java
new file mode 100644
index 000000000..fef77ac99
--- /dev/null
+++ b/game/core/src/main/java/net/minecraft/core/block/FluidHardening.java
@@ -0,0 +1,142 @@
+package net.minecraft.core.block;
+
+import net.minecraft.core.block.material.Material;
+import net.minecraft.core.block.material.Materials;
+import net.minecraft.core.sound.SoundCategory;
+import net.minecraft.core.world.World;
+import net.minecraft.core.world.pos.TilePosc;
+import net.minecraft.core.world.type.tag.WorldTypeTags;
+import org.jetbrains.annotations.NotNull;
+
+public final class FluidHardening {
+    private FluidHardening() {
+    }
+
+    public static boolean hardenWater(final @NotNull World world, final @NotNull TilePosc tilePos, final @NotNull Material encountered) {
+        if (encountered == Materials.LAVA) {
+            return hardenWaterWithLava(world, tilePos);
+        }
+        if (encountered == Materials.ACID) {
+            return hardenWaterWithAcid(world, tilePos);
+        }
+        return false;
+    }
+
+    public static boolean hardenLava(final @NotNull World world, final @NotNull TilePosc tilePos, final @NotNull Material encountered) {
+        if (encountered == Materials.WATER) {
+            return hardenLavaWithWater(world, tilePos);
+        }
+        if (encountered == Materials.ACID) {
+            return hardenLavaWithAcid(world, tilePos);
+        }
+        return false;
+    }
+
+    public static boolean hardenAcid(final @NotNull World world, final @NotNull TilePosc tilePos, final @NotNull Material encountered) {
+        if (encountered == Materials.LAVA) {
+            return hardenAcidWithLava(world, tilePos);
+        }
+        if (encountered == Materials.WATER) {
+            return hardenAcidWithWater(world, tilePos);
+        }
+        return false;
+    }
+
+    private static boolean hardenWaterWithLava(final @NotNull World world, final @NotNull TilePosc tilePos) {
+        final int data = world.getBlockData(tilePos) & 0x0F;
+        if (world.getWorldType().hasTag(WorldTypeTags.NETHER)) {
+            world.setBlockTypeNotify(tilePos, data == 0 ? Blocks.OBSIDIAN : Blocks.COBBLE_GLOOMSTONE);
+        } else {
+            world.setBlockTypeNotify(tilePos, Blocks.COBBLE_LIMESTONE);
+        }
+        BlockLogicFluid.fizz(world, tilePos);
+        return true;
+    }
+
+    private static boolean hardenWaterWithAcid(final @NotNull World world, final @NotNull TilePosc tilePos) {
+        final int data = world.getBlockData(tilePos) & 0x0F;
+        if (world.getWorldType().hasTag(WorldTypeTags.NETHER)) {
+            world.setBlockTypeNotify(tilePos, data == 0 ? Blocks.OBSIDIAN : Blocks.GLOOMSTONE);
+        } else {
+            world.setBlockTypeNotify(tilePos, Blocks.LIMESTONE);
+        }
+        BlockLogicFluid.fizz(world, tilePos);
+        return true;
+    }
+
+    private static boolean hardenLavaWithWater(final @NotNull World world, final @NotNull TilePosc tilePos) {
+        final int data = world.getBlockData(tilePos) & 0x0F;
+        if (world.getWorldType().hasTag(WorldTypeTags.NETHER)) {
+            world.setBlockTypeNotify(tilePos, data == 0 ? Blocks.MAGMA : Blocks.COBBLE_NETHERRACK);
+        } else if (data == 0) {
+            world.setBlockTypeNotify(tilePos, Blocks.OBSIDIAN);
+        } else if (data <= 2) {
+            world.setBlockTypeNotify(tilePos, Blocks.COBBLE_GRANITE);
+        } else if (data <= 4) {
+            world.setBlockTypeNotify(tilePos, Blocks.COBBLE_STONE);
+        } else {
+            world.setBlockTypeNotify(tilePos, Blocks.COBBLE_BASALT);
+        }
+        BlockLogicFluid.fizz(world, tilePos);
+        return true;
+    }
+
+    private static boolean hardenLavaWithAcid(final @NotNull World world, final @NotNull TilePosc tilePos) {
+        final int data = world.getBlockData(tilePos) & 0x0F;
+        if (world.getWorldType().hasTag(WorldTypeTags.NETHER)) {
+            world.setBlockTypeNotify(tilePos, data == 0 ? Blocks.MAGMA : Blocks.NETHERRACK);
+        } else if (data == 0) {
+            world.setBlockTypeNotify(tilePos, Blocks.OBSIDIAN);
+        } else if (data <= 2) {
+            world.setBlockTypeNotify(tilePos, Blocks.GRANITE);
+        } else if (data <= 4) {
+            world.setBlockTypeNotify(tilePos, Blocks.STONE);
+        } else {
+            world.setBlockTypeNotify(tilePos, Blocks.BASALT);
+        }
+        BlockLogicFluid.fizz(world, tilePos);
+        return true;
+    }
+
+    private static boolean hardenAcidWithLava(final @NotNull World world, final @NotNull TilePosc tilePos) {
+        final int data = world.getBlockData(tilePos) & 0x0F;
+        if (world.getWorldType().hasTag(WorldTypeTags.NETHER)) {
+            world.setBlockTypeNotify(tilePos, data == 0 ? Blocks.BRIMTHAW : Blocks.BRIMSTONE);
+            fizzAcidNether(world, tilePos);
+        } else {
+            hardenAcidOverworld(world, tilePos, data);
+        }
+        return true;
+    }
+
+    private static boolean hardenAcidWithWater(final @NotNull World world, final @NotNull TilePosc tilePos) {
+        final int data = world.getBlockData(tilePos) & 0x0F;
+        if (world.getWorldType().hasTag(WorldTypeTags.NETHER)) {
+            world.setBlockTypeNotify(tilePos, data == 0 ? Blocks.BRIMTHAW : Blocks.BRIMSTONE);
+            fizzAcidNether(world, tilePos);
+        } else {
+            hardenAcidOverworld(world, tilePos, data);
+        }
+        return true;
+    }
+
+    private static void hardenAcidOverworld(final @NotNull World world, final @NotNull TilePosc tilePos, final int data) {
+        if (data == 0) {
+            world.setBlockTypeNotify(tilePos, Blocks.SULFUR);
+        } else if (data <= 2) {
+            world.setBlockTypeNotify(tilePos, Blocks.GRANITE);
+        } else if (data <= 4) {
+            world.setBlockTypeNotify(tilePos, Blocks.STONE);
+        } else {
+            world.setBlockTypeNotify(tilePos, Blocks.BASALT);
+        }
+        BlockLogicFluid.fizz(world, tilePos);
+    }
+
+    private static void fizzAcidNether(final @NotNull World world, final @NotNull TilePosc tilePos) {
+        world.playSoundEffect(null, SoundCategory.WORLD_SOUNDS, (float) tilePos.x() + 0.5F, (float) tilePos.y() + 0.5F, (float) tilePos.z() + 0.5F, "random.fizz", 0.5F, 2.6F + (world.rand.nextFloat() - world.rand.nextFloat()) * 0.8F);
+        for (int i = 0; i < 8; ++i) {
+            world.spawnParticle("largesmoke", (double) tilePos.x() + Math.random(), (double) tilePos.y() + 1.01, (double) tilePos.z() + Math.random(), 0.0F, 0.0F, 0.0F, 0, false);
+        }
+    }
+}
diff --git a/game/core/src/main/java/net/minecraft/core/block/FluidLava.java b/game/core/src/main/java/net/minecraft/core/block/FluidLava.java
index 911979cc1..356b23d54 100644
--- a/game/core/src/main/java/net/minecraft/core/block/FluidLava.java
+++ b/game/core/src/main/java/net/minecraft/core/block/FluidLava.java
@@ -40,35 +40,7 @@ public class FluidLava
 
     @Override
     public boolean checkForHarden(final @NotNull BlockLogicFluid logicFluid, final @NotNull World world, final @NotNull TilePosc tilePos, final @NotNull Material encountered) {
-        if (encountered == Materials.WATER) {
-            final int data = world.getBlockData(tilePos) & 0x0F;
-
-            if (world.getWorldType().hasTag(WorldTypeTags.NETHER)) {
-                if (data == 0) {
-                    world.setBlockTypeNotify(tilePos, Blocks.MAGMA);
-                } else {
-                    world.setBlockTypeNotify(tilePos, Blocks.NETHERRACK);
-                }
-            } else {
-                if (data == 0) {
-                    world.setBlockTypeNotify(tilePos, Blocks.OBSIDIAN);
-                } else if (data <= 2) {
-                    world.setBlockTypeNotify(tilePos, Blocks.COBBLE_GRANITE);
-                } else if (data <= 4) {
-                    world.setBlockTypeNotify(tilePos, Blocks.COBBLE_STONE);
-                } else {
-                    world.setBlockTypeNotify(tilePos, Blocks.COBBLE_BASALT);
-                }
-            }
-
-            BlockLogicFluid.fizz(world, tilePos);
-            return true;
-        } else if (encountered == Blocks.FLUID_ACID_STILL.getMaterial()) {
-            world.setBlockTypeNotify(tilePos, Blocks.SULFUR_HARDENED);
-            BlockLogicFluid.fizz(world, tilePos);
-            return true;
-        }
-        return false;
+        return FluidHardening.hardenLava(world, tilePos, encountered);
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/block/FluidWater.java b/game/core/src/main/java/net/minecraft/core/block/FluidWater.java
index 435ed8aa1..3336d57b1 100644
--- a/game/core/src/main/java/net/minecraft/core/block/FluidWater.java
+++ b/game/core/src/main/java/net/minecraft/core/block/FluidWater.java
@@ -51,23 +51,7 @@ public class FluidWater
 
     @Override
     public boolean checkForHarden(final @NotNull BlockLogicFluid logicFluid, final @NotNull World world, final @NotNull TilePosc tilePos, final @NotNull Material encountered) {
-        if (encountered == Materials.LAVA) {
-            final int data = world.getBlockData(tilePos) & 0x0F;
-            if (data == 0) {
-                if (world.getWorldType().hasTag(WorldTypeTags.NETHER)) {
-                    world.setBlockTypeNotify(tilePos, Blocks.NETHERRACK);
-                } else {
-                    world.setBlockTypeNotify(tilePos, Blocks.COBBLE_LIMESTONE);
-                }
-            }
-            BlockLogicFluid.fizz(world, tilePos);
-            return true;
-        } else if (encountered == Blocks.FLUID_ACID_STILL.getMaterial()) {
-            world.setBlockTypeNotify(tilePos, Blocks.SULFUR_HARDENED);
-            BlockLogicFluid.fizz(world, tilePos);
-            return true;
-        }
-        return false;
+        return FluidHardening.hardenWater(world, tilePos, encountered);
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/entity/Mob.java b/game/core/src/main/java/net/minecraft/core/entity/Mob.java
index 363436919..c426b3f89 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/Mob.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/Mob.java
@@ -712,7 +712,7 @@ public abstract class Mob extends Entity {
 
             // 0.25 Speed and 1.00 Smoothness is vanilla creative mode
             float flySpeed = MathHelper.lerp(0.5f, 0.1f, this.flightSmoothness) * 2.0f * adjustedSpeed;
-            float verticalFlySpeed = MathHelper.lerp(0.3f, 0.15f, this.flightSmoothness) * 4.0f * (adjustedSpeed > 0.25f ? ((adjustedSpeed) - 0.25f) * 0.5f + 0.25f : 0.25f);
+            float verticalFlySpeed = MathHelper.lerp(0.3f, 0.15f, this.flightSmoothness) * 4.0f * (adjustedSpeed == 0 ? 0 : ((adjustedSpeed - 0.25f) * 0.5f + 0.25f));
 
             this.yd += verticalFlySpeed * vertical;
 
diff --git a/game/core/src/main/java/net/minecraft/core/item/Item.java b/game/core/src/main/java/net/minecraft/core/item/Item.java
index 1ff7f6a8c..7f60b5693 100644
--- a/game/core/src/main/java/net/minecraft/core/item/Item.java
+++ b/game/core/src/main/java/net/minecraft/core/item/Item.java
@@ -45,7 +45,8 @@ public class Item implements ITaggable<Item>, IItemConvertible {
     protected boolean hasSubtypes;
     private @Nullable Item containerItem;
     private @Nullable Supplier<@NotNull IItemConvertible> statParent = null;
-    private final @NotNull String key;
+    @SuppressWarnings("FieldMayBeFinal")
+    private @NotNull String key;
 
     protected static final Map<String, List<Stat>> statsInCategory = new HashMap<>();
     protected final @NotNull Map<@NotNull String, @NotNull Stat> stats = new HashMap<>();
diff --git a/game/core/src/main/java/net/minecraft/core/player/inventory/CreativeMenuContents.java b/game/core/src/main/java/net/minecraft/core/player/inventory/CreativeMenuContents.java
index 53766556e..fde062915 100644
--- a/game/core/src/main/java/net/minecraft/core/player/inventory/CreativeMenuContents.java
+++ b/game/core/src/main/java/net/minecraft/core/player/inventory/CreativeMenuContents.java
@@ -485,7 +485,6 @@ public final class CreativeMenuContents {
 		addBlock(list, Blocks.BRIMTHAW);
 		addBlock(list, Blocks.GLOWSTONE);
 		addBlock(list, Blocks.SULFUR);
-		addBlock(list, Blocks.SULFUR_HARDENED);
 		newLine(list);
 
 		addBlock(list, Blocks.ICE);
diff --git a/game/core/src/main/java/net/minecraft/core/player/inventory/menu/MenuAbstract.java b/game/core/src/main/java/net/minecraft/core/player/inventory/menu/MenuAbstract.java
index ecf125695..21e256655 100644
--- a/game/core/src/main/java/net/minecraft/core/player/inventory/menu/MenuAbstract.java
+++ b/game/core/src/main/java/net/minecraft/core/player/inventory/menu/MenuAbstract.java
@@ -704,13 +704,20 @@ public abstract class MenuAbstract
 		if(action == InventoryAction.CREATIVE_DRAG) {
 			for(int i=0; i < slots.length; i++) {
 				Slot slot = getSlot(slots[i]);
-				if(slot == null || !slot.enableDragAndPickup() || !slot.mayPlace(draggingItemStack) || slot.getItemStack() != null) {
+				if(slot == null || !slot.enableDragAndPickup() || !slot.mayPlace(draggingItemStack)) {
 					continue;
 				}
-				ItemStack stack = draggingItemStack.copy();
-				stack.stackSize = stack.getMaxStackSize();
-				slot.set(stack);
-				slot.setChanged();
+				final var srcStack = slot.getItemStack();
+				if (srcStack == null) {
+					final var stack = draggingItemStack.copy();
+					stack.stackSize = stack.getMaxStackSize();
+					slot.set(stack);
+					slot.setChanged();
+				} else {
+					if (!srcStack.canStackWith(draggingItemStack)) continue;
+					srcStack.stackSize = srcStack.getMaxStackSize();
+					slot.setChanged();
+				}
 			}
 			player.inventory.setHeldItemStack(null);
 			return;
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 80c28a081..367b6cf12 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
@@ -26,7 +26,6 @@ public class SurfaceGeneratorNether implements SurfaceGenerator {
     // Cache common block IDs to avoid lookups
     private final short soulSandId = (short) Blocks.SOULSAND.id();
     private final short sulfurId = (short) Blocks.SULFUR.id();
-    private final short sulfurHardenedId = (short) Blocks.SULFUR_HARDENED.id();
     private final short brimsandId = (short) Blocks.BRIMSAND.id();
     private final short brimstoneId = (short) Blocks.BRIMSTONE.id();
     private final short netherrackId = (short) Blocks.NETHERRACK.id();
@@ -153,8 +152,8 @@ public class SurfaceGeneratorNether implements SurfaceGenerator {
                                     fillerBlock = soulSandId;
                                 }
                             } else if (y <= oceanY && cachedBiomeGeneratesSulfur) {
-                                topBlock = sulfurId;
-                                fillerBlock = sulfurHardenedId;
+                                topBlock = brimsandId;
+                                fillerBlock = brimstoneId;
                             }
                         }
 
diff --git a/game/core/src/main/resources/assets/minecraft/lang/en_US/item.lang b/game/core/src/main/resources/assets/minecraft/lang/en_US/item.lang
index 684c26c67..479a773cf 100644
--- a/game/core/src/main/resources/assets/minecraft/lang/en_US/item.lang
+++ b/game/core/src/main/resources/assets/minecraft/lang/en_US/item.lang
@@ -568,14 +568,14 @@ item.statue.gloomstone.name=Gloomstone Statue
 item.statue.gloomstone.desc=A decorative statue carved from gloomy stone.
 
 item.ammo.arrow.flaming.name=Flaming Arrow
-item.ammo.arrow.flaming.desc=An arrow tipped with highly combustible sulfur.
+item.ammo.arrow.flaming.desc=An arrow tipped with highly flammable sulfur.
 
 item.sulfur.name=Sulfur
 item.sulfur.desc=A pungent, flammable powder sourced from acidic pools.
 
 item.bucket.iron.acid.name=Iron Acid Bucket
-item.bucket.iron.acid.desc=A sturdy bucket carefully filled with corrosive acid.
+item.bucket.iron.acid.desc=A bucket carefully filled with vile acid.
 
 item.bucket.steel.acid.name=Steel Acid Bucket
-item.bucket.steel.acid.desc=A large sturdy bucket carefully filled with corrosive acid.
+item.bucket.steel.acid.desc=A large bucket carefully filled with vile acid.
 
