diff --git a/game/client/src/main/java/net/minecraft/client/Minecraft.java b/game/client/src/main/java/net/minecraft/client/Minecraft.java
index 4432309dd..3cec32889 100644
--- a/game/client/src/main/java/net/minecraft/client/Minecraft.java
+++ b/game/client/src/main/java/net/minecraft/client/Minecraft.java
@@ -17,10 +17,13 @@ import com.mojang.logging.LogUtils;
 import com.mojang.nbt.tags.CompoundTag;
 import net.minecraft.client.entity.ClientSkinVariantList;
 import net.minecraft.client.entity.player.PlayerLocal;
+import net.minecraft.client.enums.EnumGPUVendor;
 import net.minecraft.client.gui.*;
 import net.minecraft.client.gui.achievements.ScreenAchievements;
 import net.minecraft.client.gui.chat.ScreenChat;
 import net.minecraft.client.gui.chat.ScreenSleepMP;
+import net.minecraft.client.gui.options.data.OptionsPage;
+import net.minecraft.client.gui.options.data.OptionsPages;
 import net.minecraft.client.gui.toasts.GuiElementToastsHud;
 import net.minecraft.client.holiday.Holidays;
 import net.minecraft.client.net.handler.PacketHandlerClient;
@@ -193,6 +196,7 @@ public class Minecraft
     public static final String VERSION = Global.VERSION;
     public static final boolean isMultiplayerDisabled = false;
     public static boolean doPartialTick = true;
+    public static EnumGPUVendor GPU_VENDOR = EnumGPUVendor.UNKNOWN;
     private static Minecraft INSTANCE;
     public PlayerController playerController;
     public boolean hasCrashed;
@@ -468,6 +472,15 @@ public class Minecraft
 		
 		gameWindow.init(this, overrideWidth != null ? overrideWidth : gameSettings.windowWidth.value, overrideHeight != null ? overrideHeight : gameSettings.windowHeight.value);
 
+        final @Nullable String vendorString = GL11.glGetString(GL_VENDOR);
+        if (vendorString != null) {
+            GPU_VENDOR = EnumGPUVendor.getVendorFromString(vendorString);
+            if (GPU_VENDOR == EnumGPUVendor.INTEL) {
+                // Intel cannot handle the sheer complexity of drawing the lightmap texture upon a quad
+                gameSettings.lightmapStyle.set(LightmapStyle.DISABLED);
+            }
+        }
+
         LOGGER.info("Resolution: {} x {}", gameWindow.getWidthPixels(), gameWindow.getHeightPixels());
 
         resolution.setScale(gameSettings.guiScale.value);
@@ -558,6 +571,8 @@ public class Minecraft
         
         textureManager.refreshTextures(new ArrayList<>());
 
+        OptionsPages.init();
+
         loadScreen();	// Update loading screen so it doesn't say no response
 
         LOGGER.info("Initializing Renderer...");
diff --git a/game/client/src/main/java/net/minecraft/client/enums/EnumGPUVendor.java b/game/client/src/main/java/net/minecraft/client/enums/EnumGPUVendor.java
new file mode 100644
index 000000000..028dc35be
--- /dev/null
+++ b/game/client/src/main/java/net/minecraft/client/enums/EnumGPUVendor.java
@@ -0,0 +1,20 @@
+package net.minecraft.client.enums;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Locale;
+
+public enum EnumGPUVendor {
+    NVIDIA,
+    AMD,
+    INTEL,
+    UNKNOWN;
+
+    public static @NotNull EnumGPUVendor getVendorFromString(final @NotNull String vendorString) {
+        final @NotNull String vendorStringLower = vendorString.toLowerCase(Locale.ROOT);
+        if (vendorStringLower.contains("nvidia corporation")) return NVIDIA;
+        if (vendorStringLower.contains("ati technologies")) return AMD;
+        if (vendorStringLower.contains("intel")) return INTEL;
+        return UNKNOWN;
+    }
+}
diff --git a/game/client/src/main/java/net/minecraft/client/gui/ScreenMainMenu.java b/game/client/src/main/java/net/minecraft/client/gui/ScreenMainMenu.java
index 19e56e934..e9d02a99d 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/ScreenMainMenu.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/ScreenMainMenu.java
@@ -28,7 +28,7 @@ import org.lwjgl.opengl.GL11;
 import org.lwjgl.util.glu.GLU;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.options.OptionsScreen;
+import net.minecraft.client.gui.options.ScreenOptions;
 import net.minecraft.client.gui.options.data.OptionsPages;
 import net.minecraft.client.render.RenderBlocks;
 import net.minecraft.core.block.Block;
@@ -194,7 +194,7 @@ public class ScreenMainMenu extends Screen
     {
         if(button.id == 0)
         {
-            mc.displayScreen(new OptionsScreen(this));
+            mc.displayScreen(new ScreenOptions(this));
         }
         if(button.id == 1)
         {
@@ -206,7 +206,7 @@ public class ScreenMainMenu extends Screen
         }
         if(button.id == 3)
         {
-            mc.displayScreen(new OptionsScreen(this, OptionsPages.TEXTURE_PACKS));
+            mc.displayScreen(new ScreenOptions(this, OptionsPages.TEXTURE_PACKS));
         }
         if(button.id == 4)
         {
@@ -218,10 +218,10 @@ public class ScreenMainMenu extends Screen
         }
         if(button.id == 9)
         {
-            mc.displayScreen(new OptionsScreen(this, OptionsPages.LANGUAGE));
+            mc.displayScreen(new ScreenOptions(this, OptionsPages.LANGUAGE));
         }
         if(button.id == 10){
-            mc.displayScreen(new OptionsScreen(this, OptionsPages.DEBUG));
+            mc.displayScreen(new ScreenOptions(this, OptionsPages.DEBUG));
         }
         Desktop desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null;
         if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE))
diff --git a/game/client/src/main/java/net/minecraft/client/gui/ScreenPause.java b/game/client/src/main/java/net/minecraft/client/gui/ScreenPause.java
index ea24a774d..5a0016ec0 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/ScreenPause.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/ScreenPause.java
@@ -4,7 +4,7 @@ import net.minecraft.client.gui.achievements.ScreenAchievements;
 import net.minecraft.client.gui.guidebook.GuidebookPageManager;
 import net.minecraft.client.gui.guidebook.ScreenGuidebook;
 import net.minecraft.client.gui.guidebook.search.GuidebookPageSearch;
-import net.minecraft.client.gui.options.OptionsScreen;
+import net.minecraft.client.gui.options.ScreenOptions;
 import net.minecraft.client.gui.options.data.OptionsPages;
 import net.minecraft.core.data.registry.Registries;
 import net.minecraft.core.data.registry.recipe.SearchQuery;
@@ -55,7 +55,7 @@ public class ScreenPause extends Screen
     {
         if(button.id == 0)
         {
-            mc.displayScreen(new OptionsScreen(this));
+            mc.displayScreen(new ScreenOptions(this));
         }
         if(button.id == 1)
         {
@@ -93,7 +93,7 @@ public class ScreenPause extends Screen
             mc.displayScreen(new ScreenPhotoMode());
         }
         if(button.id == 9){
-            mc.displayScreen(new OptionsScreen(this, OptionsPages.DEBUG));
+            mc.displayScreen(new ScreenOptions(this, OptionsPages.DEBUG));
         }
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/gui/ScreenPhotoMode.java b/game/client/src/main/java/net/minecraft/client/gui/ScreenPhotoMode.java
index 42e815470..db5c2933f 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/ScreenPhotoMode.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/ScreenPhotoMode.java
@@ -1,7 +1,9 @@
 package net.minecraft.client.gui;
 
 import net.minecraft.client.gui.modelviewer.elements.ListenerButtonElement;
+import net.minecraft.client.input.controller.ControllerInput;
 import net.minecraft.core.Global;
+import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.util.helper.Utils;
 import net.minecraft.core.world.season.Season;
 import net.minecraft.core.world.season.Seasons;
@@ -335,6 +337,21 @@ public class ScreenPhotoMode extends Screen
         GL11.glLoadIdentity();
         GL11.glTranslatef(0.0F, 0.0F, -2000F);
 
+        if (mc.controllerInput != null) {
+            if (mc.controllerInput.buttonLeftShoulder.isPressed()) {
+                float div = (float)Math.pow(2, iZoom) / 3;
+                iPanXGoal -= mc.controllerInput.joyRight.getX() / div;
+                iPanYGoal -= mc.controllerInput.joyRight.getY() / div;
+            } else if (mc.controllerInput.buttonLeftTrigger.isPressed()) {
+                iTiltGoal -= mc.controllerInput.joyRight.getY() / 2f;
+                iTiltGoal = MathHelper.clamp(iTiltGoal, 0.0f, 90.0f);
+                updateButtonsText();
+            } else {
+                iRotationGoal -= mc.controllerInput.joyRight.getX() / 64f;
+                iZoomGoal -= mc.controllerInput.joyRight.getY() / 128f;
+            }
+        }
+
         long currentTime = System.currentTimeMillis();
         if (currentTime > lastUpdateTime + 5)
         {
@@ -492,4 +509,9 @@ public class ScreenPhotoMode extends Screen
             iZoomGoal += 0.25f;
         }
     }
+
+    @Override
+    public void guiSpecificControllerInput(ControllerInput controller) {
+
+    }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/gui/ScrolledSelectionList.java b/game/client/src/main/java/net/minecraft/client/gui/ScrolledSelectionList.java
index 744dce911..46e4c9b7f 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/ScrolledSelectionList.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/ScrolledSelectionList.java
@@ -101,26 +101,31 @@ public abstract class ScrolledSelectionList {
     public void render(int x, int y, float partialTicks) {
         renderHoleBackground();
         int numItems = getItemCount();
-        int l = width / 2 + 124;
-        int i1 = l + 6;
+        int scrollbarLeft = width / 2 + 124;
+        int scrollbarRight = scrollbarLeft + 6;
+        if (minecraft.controllerInput != null) {
+            if (Math.abs(minecraft.controllerInput.joyRight.getY()) > 0.1f) {
+                amountScrolled += minecraft.controllerInput.joyRight.getY();
+            }
+        }
         if (Mouse.isButtonDown(0) || (minecraft.controllerInput != null && minecraft.controllerInput.buttonA.isPressed())) {
             if (yDrag == -1F) {
                 boolean flag = true;
                 if (y >= y0 && y <= y1) {
-                    int j1 = width / 2 - 110;
-                    int k1 = width / 2 + 110;
+                    int left = width / 2 - 110;
+                    int right = width / 2 + 110;
                     int i2 = ((y - y0 - headerHeight) + (int) amountScrolled) - 4;
                     int k2 = i2 / itemHeight;
-                    if (x >= j1 && x <= k1 && k2 >= 0 && i2 >= 0 && k2 < numItems) {
+                    if (x >= left && x <= right && k2 >= 0 && i2 >= 0 && k2 < numItems) {
                         boolean flag1 = k2 == selectedElement && System.currentTimeMillis() - lastClicked < 250L;
                         selectItem(k2, flag1);
                         selectedElement = k2;
                         lastClicked = System.currentTimeMillis();
-                    } else if (x >= j1 && x <= k1 && i2 < 0) {
-                        clickedHeader(x - j1, ((y - y0) + (int) amountScrolled) - 4);
+                    } else if (x >= left && x <= right && i2 < 0) {
+                        clickedHeader(x - left, ((y - y0) + (int) amountScrolled) - 4);
                         flag = false;
                     }
-                    if (x >= l && x <= i1) {
+                    if (x >= scrollbarLeft && x <= scrollbarRight) {
                         scrollMultiplier = -1F;
                         int i3 = getMaxPosition() - (y1 - y0 - 4);
                         if (i3 < 1) {
@@ -239,24 +244,24 @@ public abstract class ScrolledSelectionList {
             }
             tessellator.startDrawingQuads();
             tessellator.setColorRGBA_I(0, 255);
-            tessellator.addVertexWithUV(l, y1, 0.0D, 0.0D, 1.0D);
-            tessellator.addVertexWithUV(i1, y1, 0.0D, 1.0D, 1.0D);
-            tessellator.addVertexWithUV(i1, y0, 0.0D, 1.0D, 0.0D);
-            tessellator.addVertexWithUV(l, y0, 0.0D, 0.0D, 0.0D);
+            tessellator.addVertexWithUV(scrollbarLeft, y1, 0.0D, 0.0D, 1.0D);
+            tessellator.addVertexWithUV(scrollbarRight, y1, 0.0D, 1.0D, 1.0D);
+            tessellator.addVertexWithUV(scrollbarRight, y0, 0.0D, 1.0D, 0.0D);
+            tessellator.addVertexWithUV(scrollbarLeft, y0, 0.0D, 0.0D, 0.0D);
             tessellator.draw();
             tessellator.startDrawingQuads();
             tessellator.setColorRGBA_I(0x808080, 255);
-            tessellator.addVertexWithUV(l, l4 + j4, 0.0D, 0.0D, 1.0D);
-            tessellator.addVertexWithUV(i1, l4 + j4, 0.0D, 1.0D, 1.0D);
-            tessellator.addVertexWithUV(i1, l4, 0.0D, 1.0D, 0.0D);
-            tessellator.addVertexWithUV(l, l4, 0.0D, 0.0D, 0.0D);
+            tessellator.addVertexWithUV(scrollbarLeft, l4 + j4, 0.0D, 0.0D, 1.0D);
+            tessellator.addVertexWithUV(scrollbarRight, l4 + j4, 0.0D, 1.0D, 1.0D);
+            tessellator.addVertexWithUV(scrollbarRight, l4, 0.0D, 1.0D, 0.0D);
+            tessellator.addVertexWithUV(scrollbarLeft, l4, 0.0D, 0.0D, 0.0D);
             tessellator.draw();
             tessellator.startDrawingQuads();
             tessellator.setColorRGBA_I(0xc0c0c0, 255);
-            tessellator.addVertexWithUV(l, (l4 + j4) - 1, 0.0D, 0.0D, 1.0D);
-            tessellator.addVertexWithUV(i1 - 1, (l4 + j4) - 1, 0.0D, 1.0D, 1.0D);
-            tessellator.addVertexWithUV(i1 - 1, l4, 0.0D, 1.0D, 0.0D);
-            tessellator.addVertexWithUV(l, l4, 0.0D, 0.0D, 0.0D);
+            tessellator.addVertexWithUV(scrollbarLeft, (l4 + j4) - 1, 0.0D, 0.0D, 1.0D);
+            tessellator.addVertexWithUV(scrollbarRight - 1, (l4 + j4) - 1, 0.0D, 1.0D, 1.0D);
+            tessellator.addVertexWithUV(scrollbarRight - 1, l4, 0.0D, 1.0D, 0.0D);
+            tessellator.addVertexWithUV(scrollbarLeft, l4, 0.0D, 0.0D, 0.0D);
             tessellator.draw();
         }
         renderDecorations(x, y);
diff --git a/game/client/src/main/java/net/minecraft/client/gui/achievements/ScreenAchievements.java b/game/client/src/main/java/net/minecraft/client/gui/achievements/ScreenAchievements.java
index af531b6de..95fd2d77b 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/achievements/ScreenAchievements.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/achievements/ScreenAchievements.java
@@ -250,8 +250,22 @@ public class ScreenAchievements extends Screen
             }
             currentShiftX =  MathHelper.clamp(currentShiftX, shiftMinX, shiftMaxX);
             currentShiftY =  MathHelper.clamp(currentShiftY, shiftMinY, shiftMaxY);
-        } else
-        {
+        } else if (mc.controllerInput != null) {
+            targetShiftX += mc.controllerInput.joyRight.getX() / viewportZoom * 4;
+            targetShiftY += mc.controllerInput.joyRight.getY() / viewportZoom * 4;
+            currentShiftX = oldShiftX = targetShiftX;
+            currentShiftY = oldShiftY = targetShiftY;
+            currentShiftX =  MathHelper.clamp(currentShiftX, shiftMinX, shiftMaxX);
+            currentShiftY =  MathHelper.clamp(currentShiftY, shiftMinY, shiftMaxY);
+
+            if (mc.controllerInput.buttonLeftTrigger.isPressed()) {
+                viewportZoom -= 0.01d;
+            } else if (mc.controllerInput.buttonRightTrigger.isPressed()) {
+                viewportZoom += 0.01f;
+            }
+            viewportZoom = MathHelper.clamp(viewportZoom, 0.5d, 2d);
+
+        } else {
             clickX = clickY = null;
             oldPagesListScrollAmount = null;
             draggingViewport = false;
diff --git a/game/client/src/main/java/net/minecraft/client/gui/guidebook/ScreenGuidebook.java b/game/client/src/main/java/net/minecraft/client/gui/guidebook/ScreenGuidebook.java
index dabe6af17..bb352248b 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/guidebook/ScreenGuidebook.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/guidebook/ScreenGuidebook.java
@@ -347,7 +347,11 @@ public class ScreenGuidebook
                 updateTabList();
             }
         }
+        if (controller.buttonB.pressedThisFrame()) {
+            mc.displayScreen(getParentScreen());
+        }
     }
+
     private Tab getTab(GuidebookSection section, boolean searchForward){
         Tab tab = null;
         int index = -1;
diff --git a/game/client/src/main/java/net/minecraft/client/gui/hud/HudIngame.java b/game/client/src/main/java/net/minecraft/client/gui/hud/HudIngame.java
index b65691767..451f452ba 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/hud/HudIngame.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/hud/HudIngame.java
@@ -147,7 +147,7 @@ public class HudIngame extends Gui
         //Text Overlays
         if (mc.gameSettings.immersiveMode.drawOverlays())
         {
-            drawRecordPlayingOverlay(width, height, partialTicks);
+            drawRecordPlayingOverlay(width, height - sp, partialTicks);
 
             int tsp = 2 + sp;
             int line = 0;
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 352fa0f17..534729149 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
@@ -13,7 +13,7 @@ import net.minecraft.client.gui.modelviewer.elements.ListenerButtonElement;
 import net.minecraft.client.gui.modelviewer.elements.ListenerSliderElement;
 import net.minecraft.client.gui.modelviewer.elements.ListenerTextFieldElement;
 import net.minecraft.client.gui.modelviewer.elements.IListenerElement;
-import net.minecraft.client.gui.options.OptionsScreen;
+import net.minecraft.client.gui.options.ScreenOptions;
 import net.minecraft.client.gui.options.data.OptionsPages;
 import net.minecraft.client.render.BlockEntityRenderDispatcher;
 import net.minecraft.client.render.shader.PhotoModeRenderer;
@@ -401,7 +401,7 @@ public class ScreenModelViewer extends ScreenPhotoMode implements ListenerTextFi
     private void exitToMenu(){
         currentCategory.onClose();
         mc.changeWorld(null);
-        mc.displayScreen(new OptionsScreen(null, OptionsPages.DEBUG));
+        mc.displayScreen(new ScreenOptions(null, OptionsPages.DEBUG));
     }
     public static int cycleBlockId(int id, int idOff){
         int id2 = (id + Blocks.blocksList.length + idOff) % Blocks.blocksList.length;
diff --git a/game/client/src/main/java/net/minecraft/client/gui/options/OptionsScreen.java b/game/client/src/main/java/net/minecraft/client/gui/options/ScreenOptions.java
similarity index 94%
rename from game/client/src/main/java/net/minecraft/client/gui/options/OptionsScreen.java
rename to game/client/src/main/java/net/minecraft/client/gui/options/ScreenOptions.java
index 9b1e88ed6..65c9f64b6 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/options/OptionsScreen.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/options/ScreenOptions.java
@@ -9,6 +9,7 @@ import net.minecraft.client.gui.options.data.OptionsPage;
 import net.minecraft.client.gui.options.data.OptionsPages;
 import net.minecraft.client.input.InputDevice;
 import net.minecraft.client.gui.options.data.OptionsPageRegistry;
+import net.minecraft.client.input.controller.ControllerInput;
 import net.minecraft.client.option.KeyBinding;
 import net.minecraft.client.render.Scissor;
 import net.minecraft.client.render.tessellator.Tessellator;
@@ -20,7 +21,7 @@ import org.lwjgl.opengl.GL11;
 
 import static org.lwjgl.opengl.GL11.*;
 
-public class OptionsScreen
+public class ScreenOptions
     extends Screen
 {
     private static final int TOP_SPACING = 24;
@@ -47,12 +48,12 @@ public class OptionsScreen
     private boolean doOptionsScroll = true;
     private boolean doPagesListScroll = true;
 
-    public OptionsScreen(Screen parent)
+    public ScreenOptions(Screen parent)
     {
         this(parent, OptionsPages.GENERAL);
     }
 
-    public OptionsScreen(Screen parent, OptionsPage selectedPage)
+    public ScreenOptions(Screen parent, OptionsPage selectedPage)
     {
         super(parent);
         this.selectedPage = selectedPage;
@@ -153,8 +154,12 @@ public class OptionsScreen
 
     @Override
     public void removed() {
+        for (OptionsComponent component : selectedPage.getComponents()) {
+            component.onClose();
+        }
         super.removed();
         mc.gameSettings.saveOptions();
+        mc.texturePackList.refreshIfReady();
     }
 
     private void scrollOptions(float amount) {
@@ -219,6 +224,17 @@ public class OptionsScreen
             onScrollPagesList();
         }
 
+        if (pickingKeyBinding == null && pickingKeyBindingComponent == null && mc.controllerInput != null) {
+            final int xc = (int) mc.controllerInput.cursorX;
+            if (doOptionsScroll && xc > pagesListWidth + SEPARATOR_WIDTH + PADDING && xc < width) {
+                scrollOptions(mc.controllerInput.joyRight.getY() / 0.2f);
+                onScrollOptions();
+            } else if (doPagesListScroll && xc >= 0 && xc <= pagesListWidth) {
+                scrollPagesList(mc.controllerInput.joyRight.getY() / 0.2f);
+                onScrollPagesList();
+            }
+        }
+
         pagesListWidth = (int)(width * 0.25f);
         pageWidth = width - (pagesListWidth + SEPARATOR_WIDTH + (PADDING * 2));
         I18n i18n = I18n.getInstance();
@@ -425,6 +441,9 @@ public class OptionsScreen
             }
             for(OptionsPage page : OptionsPageRegistry.getInstance().getPages()) {
                 if (mx >= 0 && mx <= pagesListWidth && my >= pagesListY && my <= pagesListY + PAGE_BUTTON_HEIGHT) {
+                    for (OptionsComponent component : selectedPage.getComponents()) {
+                        component.onClose();
+                    }
                     optionsScrollAmount = 0;
                     selectedPage = page;
                     this.selectedPage.initComponents(mc);
@@ -515,4 +534,11 @@ public class OptionsScreen
             tessellator.draw();
         }
     }
+
+    @Override
+    public void guiSpecificControllerInput(ControllerInput controller) {
+        if (controller.buttonB.pressedThisFrame()) {
+            mc.displayScreen(getParentScreen());
+        }
+    }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/gui/options/components/KeyBindingComponent.java b/game/client/src/main/java/net/minecraft/client/gui/options/components/KeyBindingComponent.java
index defa9a0ff..fcdb14628 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/options/components/KeyBindingComponent.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/options/components/KeyBindingComponent.java
@@ -1,7 +1,7 @@
 package net.minecraft.client.gui.options.components;
 
 import net.minecraft.client.gui.ButtonElement;
-import net.minecraft.client.gui.options.OptionsScreen;
+import net.minecraft.client.gui.options.ScreenOptions;
 import net.minecraft.client.option.KeyBinding;
 
 public class KeyBindingComponent
@@ -26,8 +26,8 @@ public class KeyBindingComponent
             this.keyBinding.unbind();
             this.keyButton.displayString = this.keyBinding.getKeyName();
         } else {
-            OptionsScreen.pickingKeyBinding = keyBinding;
-            OptionsScreen.pickingKeyBindingComponent = this;
+            ScreenOptions.pickingKeyBinding = keyBinding;
+            ScreenOptions.pickingKeyBindingComponent = this;
         }
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/gui/options/components/OptionsCategory.java b/game/client/src/main/java/net/minecraft/client/gui/options/components/OptionsCategory.java
index 1514368bc..1768e5c0b 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/options/components/OptionsCategory.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/options/components/OptionsCategory.java
@@ -40,7 +40,9 @@ public class OptionsCategory
 
     public OptionsCategory withComponent(OptionsComponent component)
     {
-        components.add(component);
+        if (component != null) {
+            components.add(component);
+        }
         return this;
     }
 
@@ -160,6 +162,13 @@ public class OptionsCategory
         return category;
     }
 
+    @Override
+    public void onClose() {
+        for (OptionsComponent component : components) {
+            component.onClose();
+        }
+    }
+
     @Override
     public boolean matchesSearchTerm(String term)
     {
diff --git a/game/client/src/main/java/net/minecraft/client/gui/options/components/OptionsComponent.java b/game/client/src/main/java/net/minecraft/client/gui/options/components/OptionsComponent.java
index 573ca8c2a..642f206fa 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/options/components/OptionsComponent.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/options/components/OptionsComponent.java
@@ -20,5 +20,7 @@ public interface OptionsComponent
 
     void onKeyPress(int keyCode, char character);
 
+    default void onClose() { };
+
     boolean matchesSearchTerm(String term);
 }
diff --git a/game/client/src/main/java/net/minecraft/client/gui/options/components/SelectedTexturePackListComponent.java b/game/client/src/main/java/net/minecraft/client/gui/options/components/SelectedTexturePackListComponent.java
index 9dc0737ca..d70b966cb 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/options/components/SelectedTexturePackListComponent.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/options/components/SelectedTexturePackListComponent.java
@@ -115,6 +115,11 @@ public class SelectedTexturePackListComponent implements OptionsComponent {
     @Override
     public void onKeyPress(int keyCode, char character) { }
 
+    @Override
+    public void onClose() {
+        draggedButton = null;
+    }
+
     @Override
     public boolean matchesSearchTerm(String term) {
         return false;
diff --git a/game/client/src/main/java/net/minecraft/client/gui/options/data/OptionsPages.java b/game/client/src/main/java/net/minecraft/client/gui/options/data/OptionsPages.java
index 34dc65e05..22b038ce7 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/options/data/OptionsPages.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/options/data/OptionsPages.java
@@ -1,37 +1,29 @@
 package net.minecraft.client.gui.options.data;
 
+import net.betterthanadventure.utils.BiomeFinder;
 import net.betterthanadventure.utils.DataDumper;
 import net.minecraft.client.Minecraft;
+import net.minecraft.client.enums.EnumGPUVendor;
 import net.minecraft.client.gui.ScreenControllerSetup;
 import net.minecraft.client.gui.ScreenHudDesigner;
 import net.minecraft.client.gui.ScreenSoundTest;
 import net.minecraft.client.gui.ScreenTextureViewer;
 import net.minecraft.client.gui.achievements.ScreenAchievements;
 import net.minecraft.client.gui.modelviewer.ScreenModelViewer;
-import net.minecraft.client.gui.options.components.AvailableTexturePackListComponent;
-import net.minecraft.client.gui.options.components.BooleanOptionComponent;
-import net.minecraft.client.gui.options.components.DifficultyOptionComponent;
-import net.minecraft.client.gui.options.components.FloatOptionComponent;
-import net.minecraft.client.gui.options.components.FramerateOptionComponent;
-import net.minecraft.client.gui.options.components.IntegerOptionComponent;
-import net.minecraft.client.gui.options.components.KeyBindingComponent;
-import net.minecraft.client.gui.options.components.LanguagePackListComponent;
-import net.minecraft.client.gui.options.components.OptionsCategory;
-import net.minecraft.client.gui.options.components.SearchFieldComponent;
-import net.minecraft.client.gui.options.components.SelectedTexturePackListComponent;
-import net.minecraft.client.gui.options.components.ShortcutComponent;
-import net.minecraft.client.gui.options.components.ToggleableOptionComponent;
-import net.minecraft.client.gui.options.components.TooltipPickerComponent;
+import net.minecraft.client.gui.options.components.*;
 import net.minecraft.client.player.controller.PlayerControllerSP;
 import net.minecraft.client.sound.SoundEngine;
 import net.minecraft.client.world.WorldClient;
 import net.minecraft.core.Global;
 import net.minecraft.core.achievement.stat.Stat;
 import net.minecraft.core.achievement.stat.StatList;
+import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
+import net.minecraft.core.item.Item;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.item.Items;
 import net.minecraft.core.util.helper.Utils;
+import net.minecraft.core.world.World;
 import org.useless.seedviewer.SeedViewerMain;
 import paulscode.sound.SoundSystem;
 
@@ -42,304 +34,16 @@ import java.io.File;
 public abstract class OptionsPages
 {
     private static final Minecraft mc = Minecraft.getMinecraft();
-    public static final OptionsPage GENERAL = register(new OptionsPage("gui.options.page.general.title", new ItemStack(Blocks.GRASS_RETRO))
-        .withComponent(new OptionsCategory("gui.options.page.general.category.gameplay")
-            .withComponent(new FloatOptionComponent(mc.gameSettings.FoV))
-            .withComponent(new DifficultyOptionComponent(mc.gameSettings.difficulty))
-            .withComponent(new ToggleableOptionComponent<>(mc.gameSettings.placementMode))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.autoHit))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.easyBridge))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.viewBobbing))
-        )
-        .withComponent(new OptionsCategory("gui.options.page.general.category.user_interface")
-            .withComponent(new ShortcutComponent("gui.options.page.general.button.edit_hud", () -> mc.displayScreen(new ScreenHudDesigner(mc.currentScreen))))
-            .withComponent(new IntegerOptionComponent(mc.gameSettings.guiScale))
-            .withComponent(new FloatOptionComponent(mc.gameSettings.screenPadding))
-            .withComponent(new TooltipPickerComponent<>(mc.gameSettings.tooltipStyle))
-            .withComponent(new ToggleableOptionComponent<>(mc.gameSettings.chatVisibility))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.fpsInOverlay))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.versionInOverlay))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.foodHealthRegenOverlay))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.armorDurabilityOverlay))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.heldItemCountOverlay))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.heldItemTooltips))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.alwaysShowDescriptions))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.hideUndiscoveredItems))
-        )
-        .withComponent(new OptionsCategory("gui.options.page.general.category.miscellaneous")
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.discordRichPresence))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.enableItemClumping))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.forceUnicodeFont))
-            .withComponent(new FloatOptionComponent(mc.gameSettings.autosaveTimer))
-        )
-        .withComponent(new ShortcutComponent("gui.options.page.general.button.open_worlds_folder", () -> Utils.openDirectory(new File(mc.getMinecraftDir(), "saves"))))
-        .withComponent(new ShortcutComponent("gui.options.page.general.button.open_screenshots_folder", () -> {
-            File f = new File(mc.getMinecraftDir(), "screenshots");
-            f.mkdirs();
-            Utils.openDirectory(f);
-        }))
-    );
+    private static boolean hasInit = false;
+    public static OptionsPage GENERAL;
 
-    public static final OptionsPage AUDIO = register(new OptionsPage("gui.options.page.audio.title", new ItemStack(Items.RECORD_CAT))
-        .withComponent(new OptionsCategory("gui.options.page.audio.category.audio")
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.subtitles))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.muteOnLostFocus))
-            .withComponent(new FloatOptionComponent(mc.gameSettings.masterVolume))
-            .withComponent(new FloatOptionComponent(mc.gameSettings.musicVolume))
-            .withComponent(new FloatOptionComponent(mc.gameSettings.worldSoundsVolume))
-            .withComponent(new FloatOptionComponent(mc.gameSettings.weatherSoundsVolume))
-            .withComponent(new FloatOptionComponent(mc.gameSettings.entitySoundsVolume))
-            .withComponent(new FloatOptionComponent(mc.gameSettings.caveSoundsVolume))
-            .withComponent(new FloatOptionComponent(mc.gameSettings.guiSoundsVolume))
-        )
-    );
-    public static final OptionsPage VIDEO = register(new OptionsPage("gui.options.page.video.title", new ItemStack(Items.FLAG))
-        .withComponent(new OptionsCategory("gui.options.page.video.category.graphics")
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.fullscreen))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.borderlessFullscreen))
-            .withComponent(new ToggleableOptionComponent<>(mc.gameSettings.renderScale))
-            .withComponent(new ToggleableOptionComponent<>(mc.gameSettings.fancyGraphics))
-            .withComponent(new ToggleableOptionComponent<>(mc.gameSettings.renderDistance))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.ambientOcclusion))
-            .withComponent(new ToggleableOptionComponent<>(mc.gameSettings.mipmapLevels))
-            .withComponent(new ToggleableOptionComponent<>(mc.gameSettings.mipmapType))
-            .withComponent(new ToggleableOptionComponent<>(mc.gameSettings.colorblindnessFix))
-        )
-        .withComponent(new OptionsCategory("gui.options.page.video.category.performance")
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.enableVsync))
-            .withComponent(new FramerateOptionComponent(mc.gameSettings.customFpsLimit))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.advancedOpenGL))
-        )
-        .withComponent(new OptionsCategory("gui.options.page.video.category.post_processing")
-            .withComponent(new FloatOptionComponent(mc.gameSettings.gamma))
-            .withComponent(new FloatOptionComponent(mc.gameSettings.colorCorrection))
-            .withComponent(new FloatOptionComponent(mc.gameSettings.fxaa))
-            .withComponent(new ToggleableOptionComponent<>(mc.gameSettings.bloom))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.heatHaze))
-        )
-        .withComponent(new OptionsCategory("gui.options.page.video.category.visuals")
-            .withComponent(new ToggleableOptionComponent<>(mc.gameSettings.lightmapStyle))
-            .withComponent(new FloatOptionComponent(mc.gameSettings.brightness))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.fog))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.biomeWater))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.treeShadows))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.vignette))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.items3D))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.clouds))
-            .withComponent(new FloatOptionComponent(mc.gameSettings.cloudHeight))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.aurora))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.slimeParticles))
-            .withComponent(new FloatOptionComponent(mc.gameSettings.blockOutlineWidth))
-        )
-    );
-    public static final OptionsPage CONTROLS = register(new OptionsPage("gui.options.page.controls.title", new ItemStack(Items.BOAT))
-        .withComponent(new OptionsCategory("gui.options.page.controls.category.mouse")
-            .withComponent(new FloatOptionComponent(mc.gameSettings.mouseSensitivity))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.invertMouse))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.rawMouseInput))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.enableItemDragging))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.smoothCamera))
-            .withComponent(new FloatOptionComponent(mc.gameSettings.flightSmoothness))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.turnWithVehicle))
-        )
-        .withComponent(new OptionsCategory("gui.options.page.controls.category.keyboard")
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.sneakToggle))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.swapCraftingButtons))
-        )
-        .withComponent(new OptionsCategory("gui.options.page.controls.category.controller")
-            .withComponent(new ShortcutComponent("gui.options.page.controls.button.controller_setup", () -> mc.displayScreen(new ScreenControllerSetup(mc.currentScreen))))
-            .withComponent(new FloatOptionComponent(mc.gameSettings.controllerSensitivity))
-            .withComponent(new FloatOptionComponent(mc.gameSettings.controllerMenuSensitivity))
-            .withComponent(new FloatOptionComponent(mc.gameSettings.controllerDeadzoneLeft))
-            .withComponent(new FloatOptionComponent(mc.gameSettings.controllerDeadzoneRight))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.controllerSwapShoulderButtons))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.controllerSwapAB))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.controllerSwapXY))
-        )
-        .withComponent(new OptionsCategory("gui.options.page.controls.category.interactions")
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyAttack))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyInteract))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyPickBlock))
-        )
-        .withComponent(new OptionsCategory("gui.options.page.controls.category.movement")
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyForward))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyBack))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyLeft))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyRight))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyJump))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keySneak))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyFly))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyAutoWalk))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keySprint))
-        )
-        .withComponent(new OptionsCategory("gui.options.page.controls.category.user_interface")
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyInventory))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyChat))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyCommand))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyGuidebook))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyShowRecipe))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyShowUsage))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyOpenAchievements))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyOpenStatistics))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyPlayerList))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyHideGui))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyToggleDebug))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyToggleOverlay))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keySortInventory))
-        )
-        .withComponent(new OptionsCategory("gui.options.page.controls.category.hotbar")
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyHotBarLeft))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyHotBarRight))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyHotBarSwitch))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyDrop))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyHotBarSlot1))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyHotBarSlot2))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyHotBarSlot3))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyHotBarSlot4))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyHotBarSlot5))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyHotBarSlot6))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyHotBarSlot7))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyHotBarSlot8))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyHotBarSlot9))
-        )
-        .withComponent(new OptionsCategory("gui.options.page.controls.category.view")
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyLookLeft))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyLookRight))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyLookUp))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyLookDown))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyCenterView))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyZoom))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyCinematicCamera))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keySwitchPerspective))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyPhotoMode))
-        )
-        .withComponent(new OptionsCategory("gui.options.page.controls.category.miscellaneous")
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyToggleFog))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyToggleGamma))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyLockRotation))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyScreenshot))
-        )
-    );
-    public static final OptionsPage TEXTURE_PACKS = register(new OptionsPage("gui.options.page.texture_packs.title", new ItemStack(Items.PAINTING))
-        .withComponent(new ShortcutComponent("gui.options.page.texture_packs.button.open_folder", () -> Utils.openDirectory(new File(mc.getMinecraftDir(), "texturepacks"))))
-        .withComponent(new OptionsCategory("gui.options.page.texture_packs.category.textures")
-            .withComponent(new ToggleableOptionComponent<>(mc.gameSettings.animations))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.customAnimations))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.mobVariants))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.customLightmap))
-        )
-        .withComponent(new ShortcutComponent("gui.options.page.texture_packs.button.apply", () -> mc.texturePackList.refreshIfReady()))
-        .withComponent(new OptionsCategory("gui.options.page.texture_packs.category.texture_packs.selected")
-            .withComponent(new SelectedTexturePackListComponent())
-        )
-        .withComponent(new OptionsCategory("gui.options.page.texture_packs.category.texture_packs.available")
-            .withComponent(new AvailableTexturePackListComponent())
-        )
-    );
-    public static final OptionsPage LANGUAGE = register(new OptionsPage("gui.options.page.language_packs.title", new ItemStack(Items.BOOK))
-        .withComponent(new ShortcutComponent("gui.options.page.language_packs.button.open_folder", () -> Utils.openDirectory(new File(mc.getMinecraftDir(), "languages"))))
-        .withComponent(new OptionsCategory("gui.options.page.language_packs.category.language_packs")
-            .withComponent(new LanguagePackListComponent())
-        )
-    );
-    public static final OptionsPage SEARCH = register(new OptionsPage("gui.options.page.search.title", new ItemStack(Blocks.GLASS))
-        .withComponent(new SearchFieldComponent())
-    );
-    public static final OptionsPage DEBUG = new OptionsPage("gui.options.page.debug.title", Blocks.BEDROCK.getDefaultStack())
-        .withComponent(new OptionsCategory("gui.options.page.debug.category.controls")
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyToggleTextureAtlas))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyToggleDebug))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyShowShortcuts))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyReload))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keySwitchGamemode))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyDumpTextures))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyFullbright))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyLightmaps))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyCollisionBoxes))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyChunkBorders))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyClearChat))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyPauseLostFocus))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyToggleItemInfo))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyReloadChunks))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keySmoothLighting))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyReleaseCursor))
-            .withComponent(new KeyBindingComponent(mc.gameSettings.keyLoadChunksQuickly))
-        )
-        .withComponent(new OptionsCategory("gui.options.page.debug.category.settings")
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.alphaMenu))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.lockCamera))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.showDebugScreen))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.showFrameTimes))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.showChunkBorders))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.showCollisionBoxes))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.showItemDebugInfo))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.disableCrashHandler))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.startInFullscreen))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.disableShaders))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.loadAllSounds))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.allowSoundOverrides))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.downloadSoundfiles))
-            .withComponent(new BooleanOptionComponent(mc.gameSettings.enableDevResourceLoading))
-//            .withComponent(new BooleanOptionComponent(mc.gameSettings.enableMultiDrawRendering))
-        )
-        .withComponent(new OptionsCategory("gui.options.page.debug.category.utility")
-            .withComponent(new ShortcutComponent("gui.options.page.debug.button.open.model_viewer", () -> {
-                               mc.playerController = new PlayerControllerSP(mc);
-                               mc.changeWorld(new WorldClient(), "Loading Model Viewer");
-                               mc.displayScreen(new ScreenModelViewer());}) {
-                               @Override
-                               public void render(int x, int y, int width, int relativeMouseX, int relativeMouseY) {
-                                   button.enabled = mc.currentWorld == null;
-                                   super.render(x, y, width, relativeMouseX, relativeMouseY);
-                               }
-                           }
-            )
-            .withComponent(new ShortcutComponent("gui.options.page.debug.button.open.sound_test", () -> mc.displayScreen(new ScreenSoundTest(mc.currentScreen))))
-            .withComponent(new ShortcutComponent("gui.options.page.debug.button.open.texture_viewer", () -> mc.displayScreen(new ScreenTextureViewer(mc.currentScreen))))
-            .withComponent(new ShortcutComponent("gui.options.page.debug.button.open.biome_finder", () -> {
-                new Thread(() -> SeedViewerMain.main(new String[0])).start();
-                Global.accessor = mc;
-            }))
-            .withComponent(new ShortcutComponent("gui.options.page.debug.button.open.datadumper", () ->{
-                DataDumper.main(new String[0]);
-                Utils.openDirectory(new File(mc.getMinecraftDir(), "infodump"));
-                Global.accessor = mc;
-            }))
-            .withComponent(new ShortcutComponent("gui.options.page.debug.button.open.achievements", () -> mc.displayScreen(new ScreenAchievements(mc.currentScreen, mc.statsCounter))))
-        )
-        .withComponent(new OptionsCategory("gui.options.page.debug.category.test")
-            .withComponent(new ShortcutComponent("gui.options.page.debug.button.music.skip", () -> {
-                SoundSystem soundSystem = SoundEngine.getSoundSystem();
-                if (soundSystem != null) {
-                    soundSystem.stop(SoundEngine.BG_MUSIC);
-                }
-                mc.sndManager.ticksBeforeMusic = -1;
-                mc.sndManager.tick();
-            }))
-            .withComponent(new ShortcutComponent("gui.options.page.debug.button.cheat", () -> {
-                mc.currentWorld.getLevelData().setCheatsEnabled(true);
-            }) {
-                @Override
-                public void render(int x, int y, int width, int relativeMouseX, int relativeMouseY) {
-                    button.enabled = (mc.currentWorld != null && !mc.currentWorld.isClientSide);
-                    super.render(x, y, width, relativeMouseX, relativeMouseY);
-                }
-            })
-            .withComponent(new ShortcutComponent("gui.options.page.debug.button.wipestats", () -> {
-                mc.statsCounter.wipe("I want to delete all the saved stats");
-            }))
-            .withComponent(new ShortcutComponent("gui.options.page.debug.button.unlockedall", () -> {
-                for (Stat stat : StatList.getAllStats()){
-                    mc.thePlayer.addStat(stat, mc.thePlayer.getStat(stat) == 0 ? 1 : 0);
-                }
-            }))
-            .withComponent(new ShortcutComponent("gui.options.page.debug.button.crash.soft", () -> {
-                throw new RuntimeException("Test Soft Exception");
-            }))
-            .withComponent(new ShortcutComponent("gui.options.page.debug.button.crash.hard", () -> {
-                throw new RuntimeErrorException(new Error(), "Test Hard Exception");
-            }))
-        );
+    public static OptionsPage AUDIO;
+    public static OptionsPage VIDEO;
+    public static OptionsPage CONTROLS;
+    public static OptionsPage TEXTURE_PACKS;
+    public static OptionsPage LANGUAGE;
+    public static OptionsPage SEARCH;
+    public static OptionsPage DEBUG;
 
     public static OptionsPage register(OptionsPage page)
     {
@@ -347,8 +51,313 @@ public abstract class OptionsPages
         return page;
     }
 
-    static void init()
+    public static void init()
     {
-        // Just to make sure the class is loaded
+        if (hasInit) return;
+        hasInit = true;
+
+        GENERAL = register(new OptionsPage("gui.options.page.general.title", new ItemStack(Blocks.GRASS_RETRO))
+            .withComponent(new OptionsCategory("gui.options.page.general.category.gameplay")
+                .withComponent(new FloatOptionComponent(mc.gameSettings.FoV))
+                .withComponent(new DifficultyOptionComponent(mc.gameSettings.difficulty))
+                .withComponent(new ToggleableOptionComponent<>(mc.gameSettings.placementMode))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.autoHit))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.easyBridge))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.viewBobbing))
+            )
+            .withComponent(new OptionsCategory("gui.options.page.general.category.user_interface")
+                .withComponent(new ShortcutComponent("gui.options.page.general.button.edit_hud", () -> mc.displayScreen(new ScreenHudDesigner(mc.currentScreen))))
+                .withComponent(new IntegerOptionComponent(mc.gameSettings.guiScale))
+                .withComponent(new FloatOptionComponent(mc.gameSettings.screenPadding))
+                .withComponent(new TooltipPickerComponent<>(mc.gameSettings.tooltipStyle))
+                .withComponent(new ToggleableOptionComponent<>(mc.gameSettings.chatVisibility))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.fpsInOverlay))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.versionInOverlay))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.foodHealthRegenOverlay))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.armorDurabilityOverlay))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.heldItemCountOverlay))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.heldItemTooltips))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.alwaysShowDescriptions))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.hideUndiscoveredItems))
+            )
+            .withComponent(new OptionsCategory("gui.options.page.general.category.miscellaneous")
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.discordRichPresence))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.enableItemClumping))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.forceUnicodeFont))
+                .withComponent(new FloatOptionComponent(mc.gameSettings.autosaveTimer))
+            )
+            .withComponent(new ShortcutComponent("gui.options.page.general.button.open_worlds_folder", () -> Utils.openDirectory(new File(mc.getMinecraftDir(), "saves"))))
+            .withComponent(new ShortcutComponent("gui.options.page.general.button.open_screenshots_folder", () -> {
+                File f = new File(mc.getMinecraftDir(), "screenshots");
+                f.mkdirs();
+                Utils.openDirectory(f);
+            }))
+        );
+
+        AUDIO = register(new OptionsPage("gui.options.page.audio.title", new ItemStack(Items.RECORD_CAT))
+            .withComponent(new OptionsCategory("gui.options.page.audio.category.audio")
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.subtitles))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.muteOnLostFocus))
+                .withComponent(new FloatOptionComponent(mc.gameSettings.masterVolume))
+                .withComponent(new FloatOptionComponent(mc.gameSettings.musicVolume))
+                .withComponent(new FloatOptionComponent(mc.gameSettings.worldSoundsVolume))
+                .withComponent(new FloatOptionComponent(mc.gameSettings.weatherSoundsVolume))
+                .withComponent(new FloatOptionComponent(mc.gameSettings.entitySoundsVolume))
+                .withComponent(new FloatOptionComponent(mc.gameSettings.caveSoundsVolume))
+                .withComponent(new FloatOptionComponent(mc.gameSettings.guiSoundsVolume))
+            )
+        );
+
+        ToggleableOptionComponent<?> lightmapComponent = new ToggleableOptionComponent<>(mc.gameSettings.lightmapStyle);
+
+        VIDEO = register(new OptionsPage("gui.options.page.video.title", new ItemStack(Items.FLAG))
+            .withComponent(new OptionsCategory("gui.options.page.video.category.graphics")
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.fullscreen))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.borderlessFullscreen))
+                .withComponent(new ToggleableOptionComponent<>(mc.gameSettings.renderScale))
+                .withComponent(new ToggleableOptionComponent<>(mc.gameSettings.fancyGraphics))
+                .withComponent(new ToggleableOptionComponent<>(mc.gameSettings.renderDistance))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.ambientOcclusion))
+                .withComponent(new ToggleableOptionComponent<>(mc.gameSettings.mipmapLevels))
+                .withComponent(new ToggleableOptionComponent<>(mc.gameSettings.mipmapType))
+                .withComponent(new ToggleableOptionComponent<>(mc.gameSettings.colorblindnessFix))
+            )
+            .withComponent(new OptionsCategory("gui.options.page.video.category.performance")
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.enableVsync))
+                .withComponent(new FramerateOptionComponent(mc.gameSettings.customFpsLimit))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.advancedOpenGL))
+            )
+            .withComponent(new OptionsCategory("gui.options.page.video.category.post_processing")
+                .withComponent(new FloatOptionComponent(mc.gameSettings.gamma))
+                .withComponent(new FloatOptionComponent(mc.gameSettings.colorCorrection))
+                .withComponent(new FloatOptionComponent(mc.gameSettings.fxaa))
+                .withComponent(new ToggleableOptionComponent<>(mc.gameSettings.bloom))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.heatHaze))
+            )
+            .withComponent(new OptionsCategory("gui.options.page.video.category.visuals")
+                .withComponent(Minecraft.GPU_VENDOR == EnumGPUVendor.INTEL ? null : lightmapComponent)
+                .withComponent(new FloatOptionComponent(mc.gameSettings.brightness))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.fog))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.biomeWater))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.treeShadows))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.vignette))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.items3D))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.clouds))
+                .withComponent(new FloatOptionComponent(mc.gameSettings.cloudHeight))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.aurora))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.slimeParticles))
+                .withComponent(new FloatOptionComponent(mc.gameSettings.blockOutlineWidth))
+            )
+        );
+
+        CONTROLS = register(new OptionsPage("gui.options.page.controls.title", new ItemStack(Items.BOOK))
+            .withComponent(new OptionsCategory("gui.options.page.controls.category.mouse")
+                .withComponent(new FloatOptionComponent(mc.gameSettings.mouseSensitivity))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.invertMouse))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.rawMouseInput))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.enableItemDragging))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.smoothCamera))
+                .withComponent(new FloatOptionComponent(mc.gameSettings.flightSmoothness))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.turnWithVehicle))
+            )
+            .withComponent(new OptionsCategory("gui.options.page.controls.category.keyboard")
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.sneakToggle))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.swapCraftingButtons))
+            )
+            .withComponent(new OptionsCategory("gui.options.page.controls.category.controller")
+                .withComponent(new ShortcutComponent("gui.options.page.controls.button.controller_setup", () -> mc.displayScreen(new ScreenControllerSetup(mc.currentScreen))))
+                .withComponent(new FloatOptionComponent(mc.gameSettings.controllerSensitivity))
+                .withComponent(new FloatOptionComponent(mc.gameSettings.controllerMenuSensitivity))
+                .withComponent(new FloatOptionComponent(mc.gameSettings.controllerDeadzoneLeft))
+                .withComponent(new FloatOptionComponent(mc.gameSettings.controllerDeadzoneRight))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.controllerSwapShoulderButtons))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.controllerSwapAB))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.controllerSwapXY))
+            )
+            .withComponent(new OptionsCategory("gui.options.page.controls.category.interactions")
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyAttack))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyInteract))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyPickBlock))
+            )
+            .withComponent(new OptionsCategory("gui.options.page.controls.category.movement")
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyForward))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyBack))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyLeft))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyRight))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyJump))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keySneak))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyFly))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyAutoWalk))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keySprint))
+            )
+            .withComponent(new OptionsCategory("gui.options.page.controls.category.user_interface")
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyInventory))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyChat))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyCommand))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyGuidebook))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyShowRecipe))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyShowUsage))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyOpenAchievements))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyOpenStatistics))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyPlayerList))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyHideGui))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyToggleDebug))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyToggleOverlay))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keySortInventory))
+            )
+            .withComponent(new OptionsCategory("gui.options.page.controls.category.hotbar")
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyHotBarLeft))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyHotBarRight))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyHotBarSwitch))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyDrop))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyHotBarSlot1))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyHotBarSlot2))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyHotBarSlot3))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyHotBarSlot4))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyHotBarSlot5))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyHotBarSlot6))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyHotBarSlot7))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyHotBarSlot8))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyHotBarSlot9))
+            )
+            .withComponent(new OptionsCategory("gui.options.page.controls.category.view")
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyLookLeft))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyLookRight))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyLookUp))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyLookDown))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyCenterView))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyZoom))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyCinematicCamera))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keySwitchPerspective))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyPhotoMode))
+            )
+            .withComponent(new OptionsCategory("gui.options.page.controls.category.miscellaneous")
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyToggleFog))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyToggleGamma))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyLockRotation))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyScreenshot))
+            )
+        );
+        TEXTURE_PACKS = register(new OptionsPage("gui.options.page.texture_packs.title", new ItemStack(Items.PAINTING))
+            .withComponent(new ShortcutComponent("gui.options.page.texture_packs.button.open_folder", () -> Utils.openDirectory(new File(mc.getMinecraftDir(), "texturepacks"))))
+            .withComponent(new OptionsCategory("gui.options.page.texture_packs.category.textures")
+                .withComponent(new ToggleableOptionComponent<>(mc.gameSettings.animations))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.customAnimations))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.mobVariants))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.customLightmap))
+            )
+            .withComponent(new ShortcutComponent("gui.options.page.texture_packs.button.apply", () -> mc.texturePackList.refreshIfReady()))
+            .withComponent(new OptionsCategory("gui.options.page.texture_packs.category.texture_packs.selected")
+                .withComponent(new SelectedTexturePackListComponent())
+            )
+            .withComponent(new OptionsCategory("gui.options.page.texture_packs.category.texture_packs.available")
+                .withComponent(new AvailableTexturePackListComponent())
+            )
+        );
+        LANGUAGE = register(new OptionsPage("gui.options.page.language_packs.title", new ItemStack(Items.BOOK))
+            .withComponent(new ShortcutComponent("gui.options.page.language_packs.button.open_folder", () -> Utils.openDirectory(new File(mc.getMinecraftDir(), "languages"))))
+            .withComponent(new OptionsCategory("gui.options.page.language_packs.category.language_packs")
+                .withComponent(new LanguagePackListComponent())
+            )
+        );
+        SEARCH = register(new OptionsPage("gui.options.page.search.title", new ItemStack(Blocks.GLASS))
+            .withComponent(new SearchFieldComponent())
+        );
+        DEBUG = new OptionsPage("gui.options.page.debug.title", Blocks.BEDROCK.getDefaultStack())
+            .withComponent(new OptionsCategory("gui.options.page.debug.category.controls")
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyToggleTextureAtlas))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyToggleDebug))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyShowShortcuts))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyReload))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keySwitchGamemode))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyDumpTextures))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyFullbright))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyLightmaps))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyCollisionBoxes))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyChunkBorders))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyClearChat))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyPauseLostFocus))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyToggleItemInfo))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyReloadChunks))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keySmoothLighting))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyReleaseCursor))
+                .withComponent(new KeyBindingComponent(mc.gameSettings.keyLoadChunksQuickly))
+            )
+            .withComponent(new OptionsCategory("gui.options.page.debug.category.settings")
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.alphaMenu))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.lockCamera))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.showDebugScreen))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.showFrameTimes))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.showChunkBorders))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.showCollisionBoxes))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.showItemDebugInfo))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.disableCrashHandler))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.startInFullscreen))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.disableShaders))
+                .withComponent(Minecraft.GPU_VENDOR == EnumGPUVendor.INTEL ? lightmapComponent : null)
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.loadAllSounds))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.allowSoundOverrides))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.downloadSoundfiles))
+                .withComponent(new BooleanOptionComponent(mc.gameSettings.enableDevResourceLoading))
+//                .withComponent(new BooleanOptionComponent(mc.gameSettings.enableMultiDrawRendering))
+            )
+            .withComponent(new OptionsCategory("gui.options.page.debug.category.utility")
+                .withComponent(new ShortcutComponent("gui.options.page.debug.button.open.model_viewer", () -> {
+                                   mc.playerController = new PlayerControllerSP(mc);
+                                   mc.changeWorld(new WorldClient(), "Loading Model Viewer");
+                                   mc.displayScreen(new ScreenModelViewer());}) {
+                                   @Override
+                                   public void render(int x, int y, int width, int relativeMouseX, int relativeMouseY) {
+                                       button.enabled = mc.currentWorld == null;
+                                       super.render(x, y, width, relativeMouseX, relativeMouseY);
+                                   }
+                               }
+                )
+                .withComponent(new ShortcutComponent("gui.options.page.debug.button.open.sound_test", () -> mc.displayScreen(new ScreenSoundTest(mc.currentScreen))))
+                .withComponent(new ShortcutComponent("gui.options.page.debug.button.open.texture_viewer", () -> mc.displayScreen(new ScreenTextureViewer(mc.currentScreen))))
+                .withComponent(new ShortcutComponent("gui.options.page.debug.button.open.biome_finder", () -> {
+                    new Thread(() -> SeedViewerMain.main(new String[0])).start();
+                    Global.accessor = mc;
+                }))
+                .withComponent(new ShortcutComponent("gui.options.page.debug.button.open.datadumper", () ->{
+                    DataDumper.main(new String[0]);
+                    Utils.openDirectory(new File(mc.getMinecraftDir(), "infodump"));
+                    Global.accessor = mc;
+                }))
+                .withComponent(new ShortcutComponent("gui.options.page.debug.button.open.achievements", () -> mc.displayScreen(new ScreenAchievements(mc.currentScreen, mc.statsCounter))))
+            )
+            .withComponent(new OptionsCategory("gui.options.page.debug.category.test")
+                .withComponent(new ShortcutComponent("gui.options.page.debug.button.music.skip", () -> {
+                    SoundSystem soundSystem = SoundEngine.getSoundSystem();
+                    if (soundSystem != null) {
+                        soundSystem.stop(SoundEngine.BG_MUSIC);
+                    }
+                    mc.sndManager.ticksBeforeMusic = -1;
+                    mc.sndManager.tick();
+                }))
+                .withComponent(new ShortcutComponent("gui.options.page.debug.button.cheat", () -> {
+                    mc.currentWorld.getLevelData().setCheatsEnabled(true);
+                }) {
+                    @Override
+                    public void render(int x, int y, int width, int relativeMouseX, int relativeMouseY) {
+                        button.enabled = (mc.currentWorld != null && !mc.currentWorld.isClientSide);
+                        super.render(x, y, width, relativeMouseX, relativeMouseY);
+                    }
+                })
+                .withComponent(new ShortcutComponent("gui.options.page.debug.button.wipestats", () -> {
+                    mc.statsCounter.wipe("I want to delete all the saved stats");
+                }))
+                .withComponent(new ShortcutComponent("gui.options.page.debug.button.unlockedall", () -> {
+                    for (Stat stat : StatList.getAllStats()){
+                        mc.thePlayer.addStat(stat, mc.thePlayer.getStat(stat) == 0 ? 1 : 0);
+                    }
+                }))
+                .withComponent(new ShortcutComponent("gui.options.page.debug.button.crash.soft", () -> {
+                    throw new RuntimeException("Test Soft Exception");
+                }))
+                .withComponent(new ShortcutComponent("gui.options.page.debug.button.crash.hard", () -> {
+                    throw new RuntimeErrorException(new Error(), "Test Hard Exception");
+                }))
+            );
     }
-}
+}
\ No newline at end of file
diff --git a/game/client/src/main/java/net/minecraft/client/input/InputHandler.java b/game/client/src/main/java/net/minecraft/client/input/InputHandler.java
index 509228c55..fe1e9d415 100644
--- a/game/client/src/main/java/net/minecraft/client/input/InputHandler.java
+++ b/game/client/src/main/java/net/minecraft/client/input/InputHandler.java
@@ -38,6 +38,10 @@ public abstract class InputHandler {
 	}
 
 	public static void poll() {
+		if (!minecraft.gameWindow.isFocused()) {
+			return;
+		}
+
 		if (sdl2Initialized) {
 			SDL.SDL_GameControllerUpdate();
 			try {
diff --git a/game/client/src/main/java/net/minecraft/client/render/RenderGlobal.java b/game/client/src/main/java/net/minecraft/client/render/RenderGlobal.java
index 64ad44a13..fa11ffa94 100644
--- a/game/client/src/main/java/net/minecraft/client/render/RenderGlobal.java
+++ b/game/client/src/main/java/net/minecraft/client/render/RenderGlobal.java
@@ -1382,7 +1382,15 @@ public class RenderGlobal
             	tessellator.setLightmapCoord(LightmapHelper.getLightmapCoord(15, 0));
             }
             BlockModel.setRenderBlocks(globalRenderBlocks);
-            BlockModelDispatcher.getInstance().getDispatch(block).renderWithOverrideTexture(tessellator, hitResult.x, hitResult.y, hitResult.z, breakingAnimation[MathHelper.clamp((int)(damagePartialTime * 10F), 0, breakingAnimation.length)] );
+            BlockModelDispatcher.getInstance()
+                .getDispatch(block)
+                .renderWithOverrideTexture(
+                    tessellator,
+                    hitResult.x,
+                    hitResult.y,
+                    hitResult.z,
+                    breakingAnimation[MathHelper.clamp((int)(damagePartialTime * 10F), 0, breakingAnimation.length - 1)]
+                );
             tessellator.draw();
             tessellator.setTranslation(0.0D, 0.0D, 0.0D);
             GL11.glDisable(GL11.GL_ALPHA_TEST);
diff --git a/game/client/src/main/java/net/minecraft/client/render/window/GameWindowGLFW.java b/game/client/src/main/java/net/minecraft/client/render/window/GameWindowGLFW.java
index 3662b577b..ad24ed71f 100644
--- a/game/client/src/main/java/net/minecraft/client/render/window/GameWindowGLFW.java
+++ b/game/client/src/main/java/net/minecraft/client/render/window/GameWindowGLFW.java
@@ -32,348 +32,353 @@ import net.minecraft.client.render.PanelCrashReport;
 import net.minecraft.core.UnexpectedThrowable;
 
 public class GameWindowGLFW implements GameWindow {
-	public Minecraft mc;
-	
-	public long window;
-
-	private boolean wasResized = false;
-	private boolean isFullscreen = false;
-	private boolean hasFocus = true;
-	
-	private int windowPosX;
-	private int windowPosY;
-	private int windowWidth;
-	private int windowHeight;
-
-	private int widthScreenCoords;
-	private int heightScreenCoords;
-
-	private int widthPixels;
-	private int heightPixels;
-	
-	@Override
-	public void init(Minecraft minecraft, int width, int height) {
-		mc = minecraft;
-		
-		System.out.println("GLFW Init");
-		if(!glfwInit()) {
-			throw new RuntimeException("GLFW Init failed!");
-		}
-		
-		// Set window hints
-		glfwWindowHint(GLFW_RESIZABLE, 1);
-		glfwWindowHint(GLFW_VISIBLE, 0);
-		glfwWindowHint(GLFW_AUTO_ICONIFY, 1);
-		glfwWindowHint(GLFW_DECORATED, 1);
-		
-		// Create window
-		window = glfwCreateWindow(width, height, "Better than Adventure! " + Global.VERSION, 0, 0);
-
-		// Set widths and heights
-		int[] w = new int[1];
-		int[] h = new int[1];
-		glfwGetWindowSize(window, w, h);
-		this.widthScreenCoords = w[0];
-		this.heightScreenCoords = h[0];
-		glfwGetFramebufferSize(window, w, h);
-		this.widthPixels = w[0];
-		this.heightPixels = h[0];
-
-		// Center window
-		MonitorInfo monitor = new MonitorInfo(glfwGetPrimaryMonitor());
-		glfwSetWindowPos(window, (monitor.widthScreenCoords - widthScreenCoords) / 2, (monitor.heightScreenCoords - heightScreenCoords) / 2);
-		
-		// Setup callbacks
-		glfwSetWindowSizeCallback(window, (window, ww, hh) -> {
-			this.widthScreenCoords = Math.max(1, ww);
-			this.heightScreenCoords = Math.max(1, hh);
-			wasResized = true;
-		});
-
-		glfwSetFramebufferSizeCallback(window, (window, ww, hh) -> {
-			this.widthPixels = Math.max(1, ww);
-			this.heightPixels = Math.max(1, hh);
-			wasResized = true;
-		});
-
-		glfwSetWindowFocusCallback(window, (window, focused) -> {
-			this.hasFocus = focused;
-		});
-
-		// Setup Icon
-		iconLabel: {
-			int[] resolutions = new int[]{16, 32, 64, 128, 256};
-			GLFWImage.Buffer gb = GLFWImage.create(resolutions.length);
-			for (int i = 0; i < resolutions.length; i++) {
-				int res = resolutions[i];
-				ByteBuffer icon = getImageBuffer("/icon/" + res + ".png");
-				if (icon == null) {
-					System.err.println("Icon at resolution '" + res + "' is null! Skipping icons!");
-					gb.close();
-					break iconLabel;
-				}
-				GLFWImage iconGI = GLFWImage.create().set(res, res, icon);
-				gb.put(i, iconGI);
-			}
-			glfwSetWindowIcon(window, gb);
-		}
-
-		// Show window
-		glfwShowWindow(window);
-		
-		// OpenGL setup
-		glfwMakeContextCurrent(window);
-		GL.createCapabilities();
-
-		// Input setup
-		Display.setWindow(this);
-
-		
-		Method createKeyboard;
-		Method createMouse;
-		
-		try {
-			createKeyboard = Keyboard.class.getDeclaredMethod("create", InputImplementation.class);
-			createKeyboard.setAccessible(true);
-			
-			createMouse = Mouse.class.getDeclaredMethod("create", InputImplementation.class);
-			createMouse.setAccessible(true);
-			
-			GLFWKeyboardImplementation keyboardImplementation = new GLFWKeyboardImplementation();
-			GLFWMouseImplementation mouseImplementation = new GLFWMouseImplementation();
-			
-			CombinedInputImplementation inputImplementation = new CombinedInputImplementation(keyboardImplementation, mouseImplementation);
-			
-			createKeyboard.invoke(null, inputImplementation);
-			createMouse.invoke(null, inputImplementation);
-		}catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException e) {
-			// only catch reflection errors
-			throw new RuntimeException(e);
-		}
-		
-		// Set Vsync
-		setVsync(mc.gameSettings.enableVsync.value);
-	}
-
-	@Override
-	public void toggleFullscreen() {
-		mc.gameSettings.fullscreen.value = !mc.gameSettings.fullscreen.value;
-		
-		updateWindowState();
-	}
-
-	@Override
-	public void updateWindowState() {
-		if(!isFullscreen) {
-			int[] x = new int[1];
-			int[] y = new int[1];
-			glfwGetWindowPos(window, x, y);
-			
-			int[] w = new int[1];
-			int[] h = new int[1];
-			glfwGetWindowSize(window, w, h);
-			
-			this.windowPosX = x[0];
-			this.windowPosY = y[0];
-			this.windowWidth = w[0];
-			this.windowHeight = h[0];
-		}
-		
-		boolean fullscreen = mc.gameSettings.fullscreen.value;
-		boolean borderless = mc.gameSettings.borderlessFullscreen.value;
-		
-		glfwHideWindow(window);
-		
-		if(fullscreen && !borderless) {
-			System.out.println("Change to Fullscreen");
-			int x = windowPosX + windowWidth / 2;
-			int y = windowPosY + windowHeight / 2;
-			MonitorInfo monitor = getMonitorAt(x, y);
-			
-			// Enable GLFW Fullscreen
-			glfwSetWindowMonitor(window, monitor.handle, monitor.posX, monitor.posY, monitor.widthScreenCoords, monitor.heightScreenCoords, monitor.refreshRate);
-			isFullscreen = true;
-		}else {
-			// Disable GLFW Fullscreen
-			glfwSetWindowMonitor(window, 0, windowPosX, windowPosY, windowWidth, windowHeight, 0);
-			
-			if(fullscreen && borderless) {
-				System.out.println("Change to Borderless Fullscreen");
-				int x = windowPosX + windowWidth / 2;
-				int y = windowPosY + windowHeight / 2;
-				MonitorInfo monitor = getMonitorAt(x, y);
-				
-				glfwSetWindowAttrib(window, GLFW_DECORATED, 0);
-				glfwSetWindowPos(window, monitor.posX, monitor.posY);
-				glfwSetWindowSize(window, monitor.widthScreenCoords, monitor.heightScreenCoords);
-				isFullscreen = true;
-			}else {
-				System.out.println("Change to Windowed");
-				glfwSetWindowAttrib(window, GLFW_DECORATED, 1);
-				isFullscreen = false;
-			}
-		}
-		
-		glfwShowWindow(window);
-	}
-	
-	public MonitorInfo getMonitorAt(int x, int y) {
-		PointerBuffer monitorPointers = glfwGetMonitors();
-		
-		for(int i = monitorPointers.position(); i < monitorPointers.limit(); i++) {
-			long monitor = monitorPointers.get(i);
-			
-			MonitorInfo info = new MonitorInfo(monitor);
-			if(x >= info.posX && y >= info.posY && x < info.posX + info.widthScreenCoords && y < info.posY + info.heightScreenCoords) {
-				return info;
-			}
-		}
-		
-		return new MonitorInfo(glfwGetPrimaryMonitor());
-	}
-	
-	@Override
-	public void displayCrashReport(UnexpectedThrowable unexpectedThrowable, int cause) {
-		JFrame frame = new JFrame();
-		Panel panel = new PanelCrashReport(mc, unexpectedThrowable, cause);
-
-		panel.setPreferredSize(new java.awt.Dimension(1280, 720));
-
-		frame.add(panel);
-		frame.pack();
-		frame.setLocationRelativeTo(null);
-		frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
-		frame.setVisible(true);
-	}
-
-	@Override
-	public int getFrequency() {
-		GLFWVidMode vidMode = glfwGetVideoMode(window);
-		if (vidMode != null) {
-			return vidMode.refreshRate();
-		} else {
-			int x = windowPosX + windowWidth / 2;
-			int y = windowPosY + windowHeight / 2;
-			MonitorInfo monitor = getMonitorAt(x, y);
-			return monitor.refreshRate;
-		}
-	}
-	
-	@Override
-	public void update() {
-		glfwPollEvents();
-		
-		Keyboard.poll();
-		Mouse.poll();
-		
-		glfwSwapBuffers(window);
-	}
-
-	@Override
-	public boolean shouldClose() {
-		return glfwWindowShouldClose(window);
-	}
-
-	@Override
-	public int getWidthScreenCoords() {
-		return widthScreenCoords;
-	}
-
-	@Override
-	public int getHeightScreenCoords() {
-		return heightScreenCoords;
-	}
-
-	@Override
-	public int getWidthPixels() {
-		return widthPixels;
-	}
-
-	@Override
-	public int getHeightPixels() {
-		return heightPixels;
-	}
-
-	@Override
-	public boolean isFocused() {
-		return hasFocus;
-	}
-
-	@Override
-	public boolean wasResized() {
-		if(wasResized) {
-			wasResized = false;
-			return true;
-		}
-		return false;
-	}
-
-	@Override
-	public void setVsync(boolean vsync) {
-		if(vsync) {
-			glfwSwapInterval(1);	
-		}else {
-			glfwSwapInterval(0);
-		}
-	}
-	
-	public static class MonitorInfo {
-		
-		public final long handle;
-		public final int posX;
-		public final int posY;
-		public final int widthScreenCoords;
-		public final int heightScreenCoords;
-		public final int refreshRate;
-		
-		public MonitorInfo(long monitor) {
-			this.handle = monitor;
-			
-			GLFWVidMode vidmode = glfwGetVideoMode(monitor);
-			
-			int[] x = new int[1];
-			int[] y = new int[1];
-			glfwGetMonitorPos(monitor, x, y);
-			posX = x[0];
-			posY = y[0];
-			
-			widthScreenCoords = vidmode.width();
-			heightScreenCoords = vidmode.height();
-			refreshRate = vidmode.refreshRate();
-		}
-	}
-
-	/**
-	 * Reads the specified image resource and returns the raw data as a ByteBuffer.
-	 *
-	 * @param resource   the resource to read
-	 * @return the resource data
-	 *
+    public Minecraft mc;
+
+    public long window;
+
+    private boolean wasResized = false;
+    private boolean isFullscreen = false;
+    private boolean hasFocus = true;
+
+    private int windowPosX;
+    private int windowPosY;
+    private int windowWidth;
+    private int windowHeight;
+
+    private int widthScreenCoords;
+    private int heightScreenCoords;
+
+    private int widthPixels;
+    private int heightPixels;
+
+    @Override
+    public void init(Minecraft minecraft, int width, int height) {
+        mc = minecraft;
+
+        System.out.println("GLFW Init");
+        if (!glfwInit()) {
+            throw new RuntimeException("GLFW Init failed!");
+        }
+
+        // Set window hints
+        glfwWindowHint(GLFW_RESIZABLE, 1);
+        glfwWindowHint(GLFW_VISIBLE, 0);
+        glfwWindowHint(GLFW_AUTO_ICONIFY, 1);
+        glfwWindowHint(GLFW_DECORATED, 1);
+
+        // Create window
+        window = glfwCreateWindow(width, height, "Better than Adventure! " + Global.VERSION, 0, 0);
+
+        // Set widths and heights
+        int[] w = new int[1];
+        int[] h = new int[1];
+        glfwGetWindowSize(window, w, h);
+        this.widthScreenCoords = w[0];
+        this.heightScreenCoords = h[0];
+        glfwGetFramebufferSize(window, w, h);
+        this.widthPixels = w[0];
+        this.heightPixels = h[0];
+
+        // Center window
+        MonitorInfo monitor = new MonitorInfo(glfwGetPrimaryMonitor());
+        glfwSetWindowPos(window, (monitor.widthScreenCoords - widthScreenCoords) / 2, (monitor.heightScreenCoords - heightScreenCoords) / 2);
+
+        // Setup callbacks
+        glfwSetWindowSizeCallback(window, (window, ww, hh) -> {
+            this.widthScreenCoords = Math.max(1, ww);
+            this.heightScreenCoords = Math.max(1, hh);
+            wasResized = true;
+        });
+
+        glfwSetFramebufferSizeCallback(window, (window, ww, hh) -> {
+            this.widthPixels = Math.max(1, ww);
+            this.heightPixels = Math.max(1, hh);
+            wasResized = true;
+        });
+
+        glfwSetWindowFocusCallback(window, (window, focused) -> {
+            this.hasFocus = focused;
+            if (Mouse.isGrabbed() && !focused) {
+                Mouse.setGrabbed(false);
+            }
+        });
+
+        // Setup Icon
+        iconLabel:
+        {
+            int[] resolutions = new int[]{16, 32, 64, 128, 256};
+            GLFWImage.Buffer gb = GLFWImage.create(resolutions.length);
+            for (int i = 0; i < resolutions.length; i++) {
+                int res = resolutions[i];
+                ByteBuffer icon = getImageBuffer("/icon/" + res + ".png");
+                if (icon == null) {
+                    System.err.println("Icon at resolution '" + res + "' is null! Skipping icons!");
+                    gb.close();
+                    break iconLabel;
+                }
+                GLFWImage iconGI = GLFWImage.create().set(res, res, icon);
+                gb.put(i, iconGI);
+            }
+            glfwSetWindowIcon(window, gb);
+        }
+
+        // Show window
+        glfwShowWindow(window);
+
+        // OpenGL setup
+        glfwMakeContextCurrent(window);
+        GL.createCapabilities();
+
+        // Input setup
+        Display.setWindow(this);
+
+
+        Method createKeyboard;
+        Method createMouse;
+
+        try {
+            createKeyboard = Keyboard.class.getDeclaredMethod("create", InputImplementation.class);
+            createKeyboard.setAccessible(true);
+
+            createMouse = Mouse.class.getDeclaredMethod("create", InputImplementation.class);
+            createMouse.setAccessible(true);
+
+            GLFWKeyboardImplementation keyboardImplementation = new GLFWKeyboardImplementation();
+            GLFWMouseImplementation mouseImplementation = new GLFWMouseImplementation();
+
+            CombinedInputImplementation inputImplementation = new CombinedInputImplementation(keyboardImplementation, mouseImplementation);
+
+            createKeyboard.invoke(null, inputImplementation);
+            createMouse.invoke(null, inputImplementation);
+        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException |
+                 NoSuchMethodException e) {
+            // only catch reflection errors
+            throw new RuntimeException(e);
+        }
+
+        // Set Vsync
+        setVsync(mc.gameSettings.enableVsync.value);
+    }
+
+    @Override
+    public void toggleFullscreen() {
+        mc.gameSettings.fullscreen.value = !mc.gameSettings.fullscreen.value;
+
+        updateWindowState();
+    }
+
+    @Override
+    public void updateWindowState() {
+        if (!isFullscreen) {
+            int[] x = new int[1];
+            int[] y = new int[1];
+            glfwGetWindowPos(window, x, y);
+
+            int[] w = new int[1];
+            int[] h = new int[1];
+            glfwGetWindowSize(window, w, h);
+
+            this.windowPosX = x[0];
+            this.windowPosY = y[0];
+            this.windowWidth = w[0];
+            this.windowHeight = h[0];
+        }
+
+        boolean fullscreen = mc.gameSettings.fullscreen.value;
+        boolean borderless = mc.gameSettings.borderlessFullscreen.value;
+
+        glfwHideWindow(window);
+
+        if (fullscreen && !borderless) {
+            System.out.println("Change to Fullscreen");
+            int x = windowPosX + windowWidth / 2;
+            int y = windowPosY + windowHeight / 2;
+            MonitorInfo monitor = getMonitorAt(x, y);
+
+            // Enable GLFW Fullscreen
+            glfwSetWindowMonitor(window, monitor.handle, monitor.posX, monitor.posY, monitor.widthScreenCoords, monitor.heightScreenCoords, monitor.refreshRate);
+            isFullscreen = true;
+        } else {
+            // Disable GLFW Fullscreen
+            glfwSetWindowMonitor(window, 0, windowPosX, windowPosY, windowWidth, windowHeight, 0);
+
+            if (fullscreen && borderless) {
+                System.out.println("Change to Borderless Fullscreen");
+                int x = windowPosX + windowWidth / 2;
+                int y = windowPosY + windowHeight / 2;
+                MonitorInfo monitor = getMonitorAt(x, y);
+
+                glfwSetWindowAttrib(window, GLFW_DECORATED, 0);
+                glfwSetWindowPos(window, monitor.posX, monitor.posY);
+                glfwSetWindowSize(window, monitor.widthScreenCoords, monitor.heightScreenCoords);
+                isFullscreen = true;
+            } else {
+                System.out.println("Change to Windowed");
+                glfwSetWindowAttrib(window, GLFW_DECORATED, 1);
+                isFullscreen = false;
+            }
+        }
+
+        glfwShowWindow(window);
+    }
+
+    public MonitorInfo getMonitorAt(int x, int y) {
+        PointerBuffer monitorPointers = glfwGetMonitors();
+
+        for (int i = monitorPointers.position(); i < monitorPointers.limit(); i++) {
+            long monitor = monitorPointers.get(i);
+
+            MonitorInfo info = new MonitorInfo(monitor);
+            if (x >= info.posX && y >= info.posY && x < info.posX + info.widthScreenCoords && y < info.posY + info.heightScreenCoords) {
+                return info;
+            }
+        }
+
+        return new MonitorInfo(glfwGetPrimaryMonitor());
+    }
+
+    @Override
+    public void displayCrashReport(UnexpectedThrowable unexpectedThrowable, int cause) {
+        JFrame frame = new JFrame();
+        Panel panel = new PanelCrashReport(mc, unexpectedThrowable, cause);
+
+        panel.setPreferredSize(new java.awt.Dimension(1280, 720));
+
+        frame.add(panel);
+        frame.pack();
+        frame.setLocationRelativeTo(null);
+        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+        frame.setVisible(true);
+    }
+
+    @Override
+    public int getFrequency() {
+        GLFWVidMode vidMode = glfwGetVideoMode(window);
+        if (vidMode != null) {
+            return vidMode.refreshRate();
+        } else {
+            int x = windowPosX + windowWidth / 2;
+            int y = windowPosY + windowHeight / 2;
+            MonitorInfo monitor = getMonitorAt(x, y);
+            return monitor.refreshRate;
+        }
+    }
+
+    @Override
+    public void update() {
+        glfwPollEvents();
+
+        if (isFocused()) {
+            Keyboard.poll();
+        }
+        Mouse.poll();
+
+        glfwSwapBuffers(window);
+    }
+
+    @Override
+    public boolean shouldClose() {
+        return glfwWindowShouldClose(window);
+    }
+
+    @Override
+    public int getWidthScreenCoords() {
+        return widthScreenCoords;
+    }
+
+    @Override
+    public int getHeightScreenCoords() {
+        return heightScreenCoords;
+    }
+
+    @Override
+    public int getWidthPixels() {
+        return widthPixels;
+    }
+
+    @Override
+    public int getHeightPixels() {
+        return heightPixels;
+    }
+
+    @Override
+    public boolean isFocused() {
+        return hasFocus;
+    }
+
+    @Override
+    public boolean wasResized() {
+        if (wasResized) {
+            wasResized = false;
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void setVsync(boolean vsync) {
+        if (vsync) {
+            glfwSwapInterval(1);
+        } else {
+            glfwSwapInterval(0);
+        }
+    }
+
+    public static class MonitorInfo {
+
+        public final long handle;
+        public final int posX;
+        public final int posY;
+        public final int widthScreenCoords;
+        public final int heightScreenCoords;
+        public final int refreshRate;
+
+        public MonitorInfo(long monitor) {
+            this.handle = monitor;
+
+            GLFWVidMode vidmode = glfwGetVideoMode(monitor);
+
+            int[] x = new int[1];
+            int[] y = new int[1];
+            glfwGetMonitorPos(monitor, x, y);
+            posX = x[0];
+            posY = y[0];
+
+            widthScreenCoords = vidmode.width();
+            heightScreenCoords = vidmode.height();
+            refreshRate = vidmode.refreshRate();
+        }
+    }
+
+    /**
+     * Reads the specified image resource and returns the raw data as a ByteBuffer.
+     *
+     * @param resource the resource to read
+     * @return the resource data
      */
-	public static ByteBuffer getImageBuffer(String resource) {
-		try {
-			BufferedImage image = ImageIO.read(GameWindowGLFW.class.getResourceAsStream(resource));
-			ByteBuffer buf = createByteBuffer(image.getWidth() * image.getHeight() * 4);
-			// Manually filling out the damn buffer since I can't find any utility that actually does it properly
-			// I don't understand why icon loading for LWJGL3 is such a pain in the ass too
-			int index = 0;
-			for (int y = 0; y < image.getHeight(); y++) {
-				for (int x = 0; x < image.getWidth(); x++) {
-					int color = image.getRGB(x, y);
-					buf.put(index + 0, (byte) Color.redFromInt(color)); // Red
-					buf.put(index + 1, (byte) Color.greenFromInt(color)); // Green
-					buf.put(index + 2, (byte) Color.blueFromInt(color)); // Blue
-					buf.put(index + 3, (byte) Color.alphaFromInt(color)); // Alpha
-					index += 4;
-				}
-			}
-			buf.flip();
-			return buf;
-		}
-		catch (Exception e){
-			System.out.println("Couldn't open icon image...");
-			e.printStackTrace();
-			return null;
-		}
-	}
+    public static ByteBuffer getImageBuffer(String resource) {
+        try {
+            BufferedImage image = ImageIO.read(GameWindowGLFW.class.getResourceAsStream(resource));
+            ByteBuffer buf = createByteBuffer(image.getWidth() * image.getHeight() * 4);
+            // Manually filling out the damn buffer since I can't find any utility that actually does it properly
+            // I don't understand why icon loading for LWJGL3 is such a pain in the ass too
+            int index = 0;
+            for (int y = 0; y < image.getHeight(); y++) {
+                for (int x = 0; x < image.getWidth(); x++) {
+                    int color = image.getRGB(x, y);
+                    buf.put(index + 0, (byte) Color.redFromInt(color)); // Red
+                    buf.put(index + 1, (byte) Color.greenFromInt(color)); // Green
+                    buf.put(index + 2, (byte) Color.blueFromInt(color)); // Blue
+                    buf.put(index + 3, (byte) Color.alphaFromInt(color)); // Alpha
+                    index += 4;
+                }
+            }
+            buf.flip();
+            return buf;
+        } catch (Exception e) {
+            System.out.println("Couldn't open icon image...");
+            e.printStackTrace();
+            return null;
+        }
+    }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/world/WorldClientMP.java b/game/client/src/main/java/net/minecraft/client/world/WorldClientMP.java
index 74353919e..03c24ad2e 100644
--- a/game/client/src/main/java/net/minecraft/client/world/WorldClientMP.java
+++ b/game/client/src/main/java/net/minecraft/client/world/WorldClientMP.java
@@ -39,6 +39,9 @@ public class WorldClientMP extends WorldClient {
     @Override
 	public void tick()
     {
+        if (getGameRuleValue(GameRules.DO_DAY_CYCLE)) {
+            levelData.setWorldTime(levelData.getWorldTime() + 1L);
+        }
         for(int k = 0; k < 10 && !reEntries.isEmpty(); k++)
         {
             Entity entity = reEntries.iterator().next();
diff --git a/game/client/src/main/resources/bg/adamng047_0.png b/game/client/src/main/resources/bg/adamng047_0.png
new file mode 100644
index 000000000..0bf5348bf
Binary files /dev/null and b/game/client/src/main/resources/bg/adamng047_0.png differ
diff --git a/game/client/src/main/resources/bg/armandothethird_0.png b/game/client/src/main/resources/bg/armandothethird_0.png
new file mode 100644
index 000000000..13e83e4a4
Binary files /dev/null and b/game/client/src/main/resources/bg/armandothethird_0.png differ
diff --git a/game/client/src/main/resources/bg/armandothethird_1.png b/game/client/src/main/resources/bg/armandothethird_1.png
new file mode 100644
index 000000000..7755d7015
Binary files /dev/null and b/game/client/src/main/resources/bg/armandothethird_1.png differ
diff --git a/game/client/src/main/resources/bg/avix3212_0.png b/game/client/src/main/resources/bg/avix3212_0.png
new file mode 100644
index 000000000..7684018d5
Binary files /dev/null and b/game/client/src/main/resources/bg/avix3212_0.png differ
diff --git a/game/client/src/main/resources/bg/backgrounds.json b/game/client/src/main/resources/bg/backgrounds.json
index 7c5de691d..6917976fc 100644
--- a/game/client/src/main/resources/bg/backgrounds.json
+++ b/game/client/src/main/resources/bg/backgrounds.json
@@ -1,6 +1,23 @@
 {
 	"replace": false,
 	"backgrounds": [
+		"adamng047_0",
+		"armandothethird_0",
+		"armandothethird_1",
+		"avix3212_0",
+		"frazzelbones_0",
+		"hobblerox_0",
+		"itsifox_0",
+		"kristality_0",
+		"pyromancer___0",
+		"snek8611_0",
+		"sx22_0",
+		"t3ssed_0",
+		"t3ssed_1",
+		"t3ssed_2",
+		"timtams72_0",
+		"timtams72_1",
+		"wwolflesbian_0",
 		"default_0"
 	]
 }
\ No newline at end of file
diff --git a/game/client/src/main/resources/bg/frazzelbones_0.png b/game/client/src/main/resources/bg/frazzelbones_0.png
new file mode 100644
index 000000000..a1f2d3b28
Binary files /dev/null and b/game/client/src/main/resources/bg/frazzelbones_0.png differ
diff --git a/game/client/src/main/resources/bg/hobblerox_0.png b/game/client/src/main/resources/bg/hobblerox_0.png
new file mode 100644
index 000000000..ca8207b33
Binary files /dev/null and b/game/client/src/main/resources/bg/hobblerox_0.png differ
diff --git a/game/client/src/main/resources/bg/itsifox_0.png b/game/client/src/main/resources/bg/itsifox_0.png
new file mode 100644
index 000000000..e560eb5ae
Binary files /dev/null and b/game/client/src/main/resources/bg/itsifox_0.png differ
diff --git a/game/client/src/main/resources/bg/kristality_0.png b/game/client/src/main/resources/bg/kristality_0.png
new file mode 100644
index 000000000..6475415ca
Binary files /dev/null and b/game/client/src/main/resources/bg/kristality_0.png differ
diff --git a/game/client/src/main/resources/bg/pyromancer___0.png b/game/client/src/main/resources/bg/pyromancer___0.png
new file mode 100644
index 000000000..c6c59c8d6
Binary files /dev/null and b/game/client/src/main/resources/bg/pyromancer___0.png differ
diff --git a/game/client/src/main/resources/bg/snek8611_0.png b/game/client/src/main/resources/bg/snek8611_0.png
new file mode 100644
index 000000000..89df9f38c
Binary files /dev/null and b/game/client/src/main/resources/bg/snek8611_0.png differ
diff --git a/game/client/src/main/resources/bg/sx22_0.png b/game/client/src/main/resources/bg/sx22_0.png
new file mode 100644
index 000000000..ca28c8e6e
Binary files /dev/null and b/game/client/src/main/resources/bg/sx22_0.png differ
diff --git a/game/client/src/main/resources/bg/t3ssed_0.png b/game/client/src/main/resources/bg/t3ssed_0.png
new file mode 100644
index 000000000..50a0d601f
Binary files /dev/null and b/game/client/src/main/resources/bg/t3ssed_0.png differ
diff --git a/game/client/src/main/resources/bg/t3ssed_1.png b/game/client/src/main/resources/bg/t3ssed_1.png
new file mode 100644
index 000000000..03095417f
Binary files /dev/null and b/game/client/src/main/resources/bg/t3ssed_1.png differ
diff --git a/game/client/src/main/resources/bg/t3ssed_2.png b/game/client/src/main/resources/bg/t3ssed_2.png
new file mode 100644
index 000000000..83461ad0d
Binary files /dev/null and b/game/client/src/main/resources/bg/t3ssed_2.png differ
diff --git a/game/client/src/main/resources/bg/timtams72_0.png b/game/client/src/main/resources/bg/timtams72_0.png
new file mode 100644
index 000000000..bba3c7a82
Binary files /dev/null and b/game/client/src/main/resources/bg/timtams72_0.png differ
diff --git a/game/client/src/main/resources/bg/timtams72_1.png b/game/client/src/main/resources/bg/timtams72_1.png
new file mode 100644
index 000000000..09ca0e891
Binary files /dev/null and b/game/client/src/main/resources/bg/timtams72_1.png differ
diff --git a/game/client/src/main/resources/bg/wwolflesbian_0.png b/game/client/src/main/resources/bg/wwolflesbian_0.png
new file mode 100644
index 000000000..c0eee62bd
Binary files /dev/null and b/game/client/src/main/resources/bg/wwolflesbian_0.png differ
diff --git a/game/client/src/main/resources/credits.txt b/game/client/src/main/resources/credits.txt
index 90b048269..44cf2ff4a 100644
--- a/game/client/src/main/resources/credits.txt
+++ b/game/client/src/main/resources/credits.txt
@@ -6,31 +6,32 @@ jonkadelic
 Bestsoft100
 Bigjango
 Flamarine
-Martin (sunsetsatellite)
+Martin (@sunsetsatellite)
+MelonMojito (@watermelonmojito)
 NebulaBC
-Useless (uselessbullets)
+Useless (@uselessbullets)
 
 *Artists
-afk (away.from.keyboard)
+afk (@away.from.keyboard)
 thaboar
 
 *Community Moderators
 Cookie Cakes
 Jej Chainstar
-Orknarok_666
+Orknarok_666 (@derperu)
 
 *Special Thanks
-AndroidDr (Pedro270707)
+AndroidDr (@Pedro270707)
+bones (@frazzelbones)
 DirtPiper
-Doop (brokendoop)
+Doop (@brokendoop)
+H2_AIL
 LukeisStuff
+mzov4j
 Snowman64
 Tocinin
-Vivian (vivianfox.)
+Vivian (@vivianfox.)
 Zaraz7
-H2_AIL
-Bones
-Mzov4j
 
 !Thank you for playing
 !Better than Adventure!
\ No newline at end of file
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicFarmland.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFarmland.java
index c7e699f21..fee3177ac 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicFarmland.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFarmland.java
@@ -240,7 +240,7 @@ public class BlockLogicFarmland extends BlockLogic implements IBonemealable
 	@Override
 	public boolean onBonemealUsed(ItemStack itemstack, @Nullable Player player, World world, int blockX, int blockY, int blockZ, Side side, double xPlaced, double yPlaced) {
 		int data = world.getBlockMetadata(blockX, blockY, blockZ);
-		if (!isFertilized(data)) {
+		if (!isFertilized(data) && itemstack.consumeItem(player)) {
 			world.setBlockMetadataWithNotify(blockX, blockY, blockZ, setFertilized(data, true));
 			return true;
 		}
diff --git a/game/core/src/main/java/net/minecraft/core/entity/monster/MobSkeleton.java b/game/core/src/main/java/net/minecraft/core/entity/monster/MobSkeleton.java
index f3ae7a779..3ab47988e 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/monster/MobSkeleton.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/monster/MobSkeleton.java
@@ -60,7 +60,7 @@ public class MobSkeleton extends MobMonster
         {
             float f = getBrightness(1.0F);
             if(f > 0.5F && world.canBlockSeeTheSky(MathHelper.floor(x), MathHelper.floor(y), MathHelper.floor(z)) && random.nextFloat() * 30F < (f - 0.4F) * 2.0F
-             && (world.getCurrentWeather() != Weathers.OVERWORLD_FOG || world.weatherManager.getWeatherPower() < 0.75F))
+                && !world.getCurrentWeather().isDamp && (world.getCurrentWeather() != Weathers.OVERWORLD_FOG || world.weatherManager.getWeatherPower() < 0.75F))
             {
                 remainingFireTicks = 300;
             }
diff --git a/game/core/src/main/java/net/minecraft/core/entity/monster/MobZombie.java b/game/core/src/main/java/net/minecraft/core/entity/monster/MobZombie.java
index b15a864e2..6d34b806e 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/monster/MobZombie.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/monster/MobZombie.java
@@ -5,6 +5,7 @@ import net.minecraft.core.item.Items;
 import net.minecraft.core.util.collection.NamespaceID;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.world.World;
+import net.minecraft.core.world.weather.Weather;
 import net.minecraft.core.world.weather.Weathers;
 
 public class MobZombie extends MobMonster
@@ -25,9 +26,10 @@ public class MobZombie extends MobMonster
     {
         if(world.isDaytime())
         {
+            Weather currentWeather = world.getCurrentWeather();
             float f = getBrightness(1.0F);
             if(f > 0.5F && world.canBlockSeeTheSky(MathHelper.floor(x), MathHelper.floor(y), MathHelper.floor(z)) && random.nextFloat() * 30F < (f - 0.4F) * 2.0F
-                    && (world.getCurrentWeather() != Weathers.OVERWORLD_FOG || world.weatherManager.getWeatherPower() < 0.75F))
+                && !world.getCurrentWeather().isDamp && (world.getCurrentWeather() != Weathers.OVERWORLD_FOG || world.weatherManager.getWeatherPower() < 0.75F))
             {
                 remainingFireTicks = 300;
             }
diff --git a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlock.java b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlock.java
index f9921b073..081a74f21 100644
--- a/game/core/src/main/java/net/minecraft/core/item/block/ItemBlock.java
+++ b/game/core/src/main/java/net/minecraft/core/item/block/ItemBlock.java
@@ -47,10 +47,9 @@ public class ItemBlock<T extends BlockLogic> extends Item
 		if(y < 0 || y >= world.getHeightBlocks()) {
 			return false;
 		}
-		if(world.canBlockBePlacedAt(block.id(), x, y, z, false, side)) {
+		if(world.canBlockBePlacedAt(block.id(), x, y, z, false, side) && stack.consumeItem(player)) {
 			int meta = getPlacedBlockMetadata(player, stack, world, x, y, z, side, xPlaced, yPlaced);
 			if(world.setBlockAndMetadataWithNotify(x, y, z, block.id(), meta)) {
-				stack.consumeItem(player);
 				if (player == null) {
                     block.onBlockPlacedOnSide(world, x, y, z, side, xPlaced, yPlaced);
                 } else {
@@ -58,6 +57,8 @@ public class ItemBlock<T extends BlockLogic> extends Item
                 }
 				world.playBlockSoundEffect(player, x + 0.5F, y + 0.5F, z + 0.5F, block, EnumBlockSoundEffectType.PLACE);
 				return true;
+			} else if (player == null || player.getGamemode().consumeBlocks()) {
+                stack.stackSize += 1;
 			}
 		}
 		return false;
diff --git a/game/core/src/main/java/net/minecraft/core/world/weather/Weather.java b/game/core/src/main/java/net/minecraft/core/world/weather/Weather.java
index 47ce15638..97c6f6e9c 100644
--- a/game/core/src/main/java/net/minecraft/core/world/weather/Weather.java
+++ b/game/core/src/main/java/net/minecraft/core/world/weather/Weather.java
@@ -17,6 +17,7 @@ public abstract class Weather
 	public int precipitationType = 0;
 	public boolean spawnRainParticles = false;
 	public boolean doMobsSpawnInDaylight = false;
+	public boolean isDamp = false;
 	public float fogDistance = 1.0f;
 	
 	public Weather(int id)
@@ -74,6 +75,11 @@ public abstract class Weather
 		doMobsSpawnInDaylight = true;
 		return this;
 	}
+
+	public Weather setDamp() {
+		isDamp = true;
+		return this;
+	}
 	
 	public String getTranslatedName()
 	{
diff --git a/game/core/src/main/java/net/minecraft/core/world/weather/Weathers.java b/game/core/src/main/java/net/minecraft/core/world/weather/Weathers.java
index 49e438226..8bd03d6df 100644
--- a/game/core/src/main/java/net/minecraft/core/world/weather/Weathers.java
+++ b/game/core/src/main/java/net/minecraft/core/world/weather/Weathers.java
@@ -2,15 +2,49 @@ package net.minecraft.core.world.weather;
 
 public abstract class Weathers {
     public static final Weather[] WEATHERS = new Weather[16];
-    public static final Weather OVERWORLD_CLEAR = new WeatherClear(0).setLanguageKey("overworld.clear");
-    public static final Weather OVERWORLD_RAIN = new WeatherRain(1).setLanguageKey("overworld.rain").setPrecipitation("/assets/minecraft/textures/environment/rain.png", 0).setSubtractLightLevel(3).setSpawnRainParticles(true).setFogDistance(0.5f);
-    public static final Weather OVERWORLD_SNOW = new WeatherSnow(2).setLanguageKey("overworld.snow").setPrecipitation("/assets/minecraft/textures/environment/snow.png", 1).setSubtractLightLevel(1).setFogDistance(0.5f);
-    public static final Weather OVERWORLD_STORM = new WeatherStorm(3).setLanguageKey("overworld.storm").setPrecipitation("/assets/minecraft/textures/environment/rain.png", 0).setSubtractLightLevel(5).setSpawnRainParticles(true).setMobsSpawnInDaylight().setFogDistance(0.4f);
-    public static final Weather OVERWORLD_FOG = new WeatherClear(4).setLanguageKey("overworld.fog").setFogDistance(0.125f);
-    public static final Weather OVERWORLD_CLEAR_HELL = new WeatherClear(5).setLanguageKey("overworld.clear.hell").setSubtractLightLevel(7);
-    public static final Weather OVERWORLD_CLEAR_WOODS = new WeatherClear(6).setLanguageKey("overworld.clear.woods").setSubtractLightLevel(2);
-    public static final Weather OVERWORLD_WINTER_SNOW = new WeatherSnow(7).setLanguageKey("overworld.winter.snow").setPrecipitation("/assets/minecraft/textures/environment/snow.png", 1);
-    public static final Weather OVERWORLD_RAIN_BLOOD = new WeatherStorm(8).setLanguageKey("overworld.rain.blood").setPrecipitation("/assets/minecraft/textures/environment/rain_blood.png", 2).setSubtractLightLevel(5).setMobsSpawnInDaylight().setFogDistance(0.4f);
+    public static final Weather OVERWORLD_CLEAR = new WeatherClear(0)
+        .setLanguageKey("overworld.clear");
+    public static final Weather OVERWORLD_RAIN = new WeatherRain(1)
+        .setLanguageKey("overworld.rain")
+        .setPrecipitation("/assets/minecraft/textures/environment/rain.png", 0)
+        .setSubtractLightLevel(3)
+        .setSpawnRainParticles(true)
+        .setFogDistance(0.5f)
+        .setDamp();
+    public static final Weather OVERWORLD_SNOW = new WeatherSnow(2)
+        .setLanguageKey("overworld.snow")
+        .setPrecipitation("/assets/minecraft/textures/environment/snow.png", 1)
+        .setSubtractLightLevel(1)
+        .setFogDistance(0.5f)
+        .setDamp();
+    public static final Weather OVERWORLD_STORM = new WeatherStorm(3)
+        .setLanguageKey("overworld.storm")
+        .setPrecipitation("/assets/minecraft/textures/environment/rain.png", 0)
+        .setSubtractLightLevel(5)
+        .setSpawnRainParticles(true)
+        .setMobsSpawnInDaylight()
+        .setFogDistance(0.4f)
+        .setDamp();
+    public static final Weather OVERWORLD_FOG = new WeatherClear(4)
+        .setLanguageKey("overworld.fog")
+        .setFogDistance(0.125f);
+    public static final Weather OVERWORLD_CLEAR_HELL = new WeatherClear(5)
+        .setLanguageKey("overworld.clear.hell")
+        .setSubtractLightLevel(7);
+    public static final Weather OVERWORLD_CLEAR_WOODS = new WeatherClear(6)
+        .setLanguageKey("overworld.clear.woods")
+        .setSubtractLightLevel(2);
+    public static final Weather OVERWORLD_WINTER_SNOW = new WeatherSnow(7)
+        .setLanguageKey("overworld.winter.snow")
+        .setPrecipitation("/assets/minecraft/textures/environment/snow.png", 1)
+        .setDamp();
+    public static final Weather OVERWORLD_RAIN_BLOOD = new WeatherStorm(8)
+        .setLanguageKey("overworld.rain.blood")
+        .setPrecipitation("/assets/minecraft/textures/environment/rain_blood.png", 2)
+        .setSubtractLightLevel(5)
+        .setMobsSpawnInDaylight()
+        .setFogDistance(0.4f)
+        .setDamp();
 
     public static Weather getWeatherByLanguageKey(String string) {
         for(Weather weather : WEATHERS) {
diff --git a/game/server/src/main/java/net/minecraft/server/net/handler/PacketHandlerServer.java b/game/server/src/main/java/net/minecraft/server/net/handler/PacketHandlerServer.java
index 057e7aae6..1676e3720 100644
--- a/game/server/src/main/java/net/minecraft/server/net/handler/PacketHandlerServer.java
+++ b/game/server/src/main/java/net/minecraft/server/net/handler/PacketHandlerServer.java
@@ -172,7 +172,8 @@ public class PacketHandlerServer extends PacketHandler
             playerEntity.xd = xd;
             playerEntity.zd = zd;
             // TODO: Is this needing? It does allow for fast-tick exploits.
-            //worldserver.func_12017_b((Entity) playerEntity.vehicle, true);
+            // Update: Removing it breaks boats, so keep it for now
+            worldserver.updateEntityWithOptionalForce(((Entity) playerEntity.vehicle), false);
             playerEntity.vehicle.positionRider();
             return;
         }
@@ -538,6 +539,9 @@ public class PacketHandlerServer extends PacketHandler
         if (updatePlayerStatePacket.state == PacketUpdatePlayerState.STATE_SNEAK)
         {
             playerEntity.setSneaking(true);
+            if (playerEntity.vehicle != null) {
+                playerEntity.vehicle.ejectRider();
+            }
         }
         else if (updatePlayerStatePacket.state == PacketUpdatePlayerState.STATE_UN_SNEAK)
         {
@@ -552,8 +556,8 @@ public class PacketHandlerServer extends PacketHandler
     @Override
     public void handleBoatControl(PacketBoatControl boatControlPacket)
     {
-        if (!canInteract()) return;
-        if (playerEntity.vehicle != null && playerEntity.vehicle instanceof EntityBoat && !Double.isNaN(boatControlPacket.targetXD) && !Double.isNaN(boatControlPacket.targetZD)) {
+        if (!canInteract() || Double.isNaN(boatControlPacket.targetXD) || Double.isNaN(boatControlPacket.targetZD)) return;
+        if (playerEntity.vehicle != null && playerEntity.vehicle instanceof EntityBoat) {
             EntityBoat boat = (EntityBoat) playerEntity.vehicle;
             boat.handleControlDirect(boatControlPacket.targetXD, boatControlPacket.targetZD, boatControlPacket.targetYRot);
             boatControlPacket.entityId = boat.id;
diff --git a/game/server/src/main/java/net/minecraft/server/world/WorldServer.java b/game/server/src/main/java/net/minecraft/server/world/WorldServer.java
index 719c013b0..b1f1b84ca 100644
--- a/game/server/src/main/java/net/minecraft/server/world/WorldServer.java
+++ b/game/server/src/main/java/net/minecraft/server/world/WorldServer.java
@@ -29,15 +29,6 @@ public class WorldServer extends World
         mcServer = minecraftserver;
     }
 
-    @Override
-    public void updateEntityWithOptionalForce(Entity entity, boolean flag)
-    {
-        if(!(entity.passenger instanceof Player))
-        {
-            super.updateEntityWithOptionalForce(entity, flag);
-        }
-    }
-
     @Override
     protected IChunkProvider createChunkProvider()
     {
