diff --git a/game/client/src/main/java/net/minecraft/client/gui/ScreenTextureViewer.java b/game/client/src/main/java/net/minecraft/client/gui/ScreenTextureViewer.java
index 0aed5225e..f0c84f8b5 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/ScreenTextureViewer.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/ScreenTextureViewer.java
@@ -27,6 +27,7 @@ public class ScreenTextureViewer extends Screen {
     protected int bottom;
 
     protected ListenerButtonElement leftTexCycle;
+    protected SliderElement mipmapSlider;
 
     protected int texIndex = 0;
 
@@ -47,10 +48,10 @@ public class ScreenTextureViewer extends Screen {
         } else if (eventKey == Keyboard.KEY_ESCAPE) {
             this.mc.displayScreen(this.parentScreen);
         }
-        List<ButtonElement> _buttons = new ArrayList<>(this.buttons);
-        for (ButtonElement button : _buttons) {
-            if (button instanceof IListenerElement && button.isHovered(mx, my)) {
-                ((IListenerElement<?>) button).onKeyTyped(eventCharacter, eventKey);
+        List<ButtonElement> buttons = new ArrayList<>(this.buttons);
+        for (ButtonElement button : buttons) {
+            if (button instanceof IListenerElement<?> element && button.isHovered(mx, my)) {
+                element.onKeyTyped(eventCharacter, eventKey);
             }
         }
     }
@@ -59,8 +60,8 @@ public class ScreenTextureViewer extends Screen {
     public void tick() {
         List<ButtonElement> _buttons = new ArrayList<>(this.buttons);
         for (ButtonElement button : _buttons) {
-            if (button instanceof ListenerButtonElement) {
-                ((ListenerButtonElement) button).tick();
+            if (button instanceof ListenerButtonElement element) {
+                element.tick();
             }
         }
     }
@@ -94,6 +95,8 @@ public class ScreenTextureViewer extends Screen {
         add(new ListenerButtonElement(13, 60 + BUTTON_SPACING * 4, this.bottom - BUTTON_SPACING - 20, 20, 20, "T")
             .setActionListener(() -> this.drawText = !this.drawText)
         );
+
+        this.mipmapSlider = add(new SliderElement(14, BUTTON_SPACING, this.bottom - BUTTON_SPACING - 42, 20 * 4 + BUTTON_SPACING * 3, 20, "Mipmap", 0));
     }
 
     protected void buttonClicked(@NotNull ButtonElement button) {
@@ -109,6 +112,7 @@ public class ScreenTextureViewer extends Screen {
             this.texIndex += textureList.size();
         }
         this.texIndex = this.texIndex % textureList.size();
+        this.mipmapSlider.sliderValue = 0;
     }
 
     public void render(int mx, int my, float partialTick) {
@@ -118,7 +122,14 @@ public class ScreenTextureViewer extends Screen {
 
         IntList textureList = GLAllocation.textureNames;
         int id = this.texIndex % textureList.size();
+
         GL41.glBindTexture(GL41.GL_TEXTURE_2D, textureList.getInt(id));
+        int mipmaps = GL41.glGetTexParameteri(GL41.GL_TEXTURE_2D, GL41.GL_TEXTURE_MAX_LEVEL);
+        if (mipmaps == 1000) mipmaps = 0;
+        int curMip = (int) (mipmaps * this.mipmapSlider.sliderValue);
+        this.mipmapSlider.displayString = String.format("Mipmap: %s", curMip);
+        this.mipmapSlider.enabled = mipmaps != 0;
+        GL41.glTexParameteri(GL41.GL_TEXTURE_2D, GL41.GL_TEXTURE_BASE_LEVEL, curMip);
 
         Texture t = this.mc.textureManager.idToTextureMap.get(textureList.getInt(id));
 
@@ -168,6 +179,7 @@ public class ScreenTextureViewer extends Screen {
         }
 
         tessellator.draw();
+        GL41.glTexParameteri(GL41.GL_TEXTURE_2D, GL41.GL_TEXTURE_BASE_LEVEL, 0);
 
 //        int bw = (int) (250 + 100 * Math.sin(System.currentTimeMillis()/1000d));
 //        int bh = (int) (60 + 30 *  Math.cos(System.currentTimeMillis()/1000d));
@@ -185,6 +197,7 @@ public class ScreenTextureViewer extends Screen {
             drawStringShadow(this.fontRenderer, "Tex ID: " + id, 1, this.top + 1, 0xFFFFFF);
             drawStringShadow(this.fontRenderer, "Tex Width: " + texWidth, 1, this.top + 11, 0xFFFFFF);
             drawStringShadow(this.fontRenderer, "Tex Height: " + texHeight, 1, this.top + 21, 0xFFFFFF);
+            drawStringShadow(this.fontRenderer, "Mipmap: " + mipmaps, 1, this.top + 31, 0xFFFFFF);
 
             String s;
             if (t == null) {
@@ -193,7 +206,7 @@ public class ScreenTextureViewer extends Screen {
                 s = t.toString();
             }
             String[] lines = s.split("\n");
-            int yOff = this.top + 31;
+            int yOff = this.top + 41;
             for (String line : lines) {
                 drawStringShadow(this.fontRenderer, line, 1, yOff, 0xFFFFFF);
                 yOff += 10;
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 3cf6d1e24..964fcc095 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
@@ -1092,9 +1092,10 @@ public class RenderGlobal
 
         final int pendingChunkSize = this.dirtyChunks.size();
 
+        float nearCheck = camera instanceof EntityCamera entityCamera && entityCamera.mob.noPhysics ? 16 : 2048;
         for (int i = 0; i < pendingChunkSize; i++) {
             final ChunkRenderer renderer = this.dirtyChunks.get(i);
-            if (renderer.distanceToCameraSquared(camera) > 2048f) {
+            if (renderer.distanceToCameraSquared(camera) > nearCheck) {
                 int index = 0;
 
                 while (index < MAX_VISIBLE_REBUILDS_PER_FRAME && (this.toAdd[index] == null || this.dirtyChunkRendererSorter.compare(this.toAdd[index], renderer) <= 0)) {
diff --git a/game/core/src/main/java/net/minecraft/core/util/Option.java b/game/core/src/main/java/net/minecraft/core/util/Option.java
new file mode 100644
index 000000000..de1bd003a
--- /dev/null
+++ b/game/core/src/main/java/net/minecraft/core/util/Option.java
@@ -0,0 +1,417 @@
+package net.minecraft.core.util;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Objects;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+/**
+ * Optional values.
+ * <br>
+ * Type {@code Option<T>} represents an optional value: every {@code Option<T>} is either {@link Some Some} and
+ * contains a value, or {@link None None}, and does not. {@code Option<T>} types have a number of uses:
+ * <list>
+ *     <li>Initial values</li>
+ *     <li>Return values for functions that are not defined over their entire input range (partial functions)</li>
+ *     <li>Return value for otherwise reporting simple errors, where {@code None} is returned on error</li>
+ *     <li>Optional class fields</li>
+ *     <li>Optional function arguments</li>
+ *     <li>More intentional nullability</li>
+ * </list>
+ * <br>
+ * {@code Option<T>}s are commonly paired with pattern matching to query the presence of a value and take action,
+ * always accounting for the {@link None None} case.
+ */
+public abstract sealed class Option<T> {
+    /**
+     * No value.
+     */
+    public static final class None<T>
+        extends Option<@NotNull T> {
+        private None() { }
+
+        @Override
+        public boolean isSome() {
+            return false;
+        }
+
+        @Override
+        public boolean isSomeAnd(final @NotNull Function<@NotNull T, @NotNull Boolean> f) {
+            return false;
+        }
+
+        @Override
+        public boolean isNone() {
+            return true;
+        }
+
+        @Override
+        public boolean isNoneOr(final @NotNull Function<@NotNull T, @NotNull Boolean> f) {
+            return true;
+        }
+
+        @Override
+        public @NotNull T expect(final @NotNull String msg)
+            throws UnwrapError
+        {
+            throw new UnwrapError(msg);
+        }
+
+        @Override
+        public @NotNull T unwrap()
+            throws UnwrapError
+        {
+            throw new UnwrapError("Called `Option::unwrap()` on a `None` value");
+        }
+
+        @Override
+        public @NotNull T unwrapOr(final @NotNull T or) {
+            return or;
+        }
+
+        @Override
+        public @NotNull T unwrapOrElse(final @NotNull Supplier<@NotNull T> f) {
+            return f.get();
+        }
+
+        @Override
+        public <U> @NotNull Option<@NotNull U> map(final @NotNull Function<@NotNull T, @NotNull U> f) {
+            return Option.none();
+        }
+
+        @Override
+        public @NotNull Option<@NotNull T> inspect(final @NotNull Consumer<T> f) {
+            return this;
+        }
+
+        @Override
+        public <U> @NotNull U mapOr(final @NotNull U or, final @NotNull Function<@NotNull T, @NotNull U> f) {
+            return or;
+        }
+
+        @Override
+        public <U> @NotNull U mapOrElse(final @NotNull Supplier<@NotNull U> orElse, final @NotNull Function<@NotNull T, @NotNull U> f) {
+            return orElse.get();
+        }
+
+        @Override
+        public @NotNull <U> Option<@NotNull U> and(final @NotNull Option<@NotNull U> optb) {
+            return Option.none();
+        }
+
+        @Override
+        public @NotNull <U> Option<@NotNull U> andThen(final @NotNull Function<@NotNull T, @NotNull Option<@NotNull U>> f) {
+            return Option.none();
+        }
+
+        @Override
+        public @NotNull Option<@NotNull T> filter(final @NotNull Function<@NotNull T, @NotNull Boolean> predicate) {
+            return this;
+        }
+
+        @Override
+        public @NotNull Option<@NotNull T> or(final @NotNull Option<@NotNull T> optb) {
+            return optb;
+        }
+
+        @Override
+        public @NotNull Option<@NotNull T> orElse(final @NotNull Supplier<@NotNull Option<@NotNull T>> f) {
+            return f.get();
+        }
+
+        @Override
+        public @NotNull Option<@NotNull T> xor(final @NotNull Option<@NotNull T> optb) {
+            return optb;
+        }
+
+        @Override
+        public boolean equals(final @Nullable Object obj) {
+            return obj instanceof final @NotNull Option<?> opt && opt.isNone();
+        }
+
+        @Override
+        public @NotNull String toString() {
+            return "Option.None";
+        }
+    }
+
+    /**
+     * Some value of type {@code T}.
+     */
+    public static final class Some<T>
+        extends Option<@NotNull T> {
+        private final @NotNull T value;
+
+        private Some(final @NotNull T value) {
+            this.value = value;
+        }
+
+        public @NotNull T get() {
+            return this.value;
+        }
+
+        @Override
+        public boolean isSome() {
+            return true;
+        }
+
+        @Override
+        public boolean isSomeAnd(final @NotNull Function<@NotNull T, @NotNull Boolean> f) {
+            return f.apply(this.value);
+        }
+
+        @Override
+        public boolean isNone() {
+            return false;
+        }
+
+        @Override
+        public boolean isNoneOr(final @NotNull Function<@NotNull T, @NotNull Boolean> f) {
+            return f.apply(this.value);
+        }
+
+        @Override
+        public @NotNull T expect(final @NotNull String msg) {
+            return this.value;
+        }
+
+        @Override
+        public @NotNull T unwrap() {
+            return this.value;
+        }
+
+        @Override
+        public @NotNull T unwrapOr(@NotNull final T or) {
+            return this.value;
+        }
+
+        @Override
+        public @NotNull T unwrapOrElse(final @NotNull Supplier<@NotNull T> f) {
+            return this.value;
+        }
+
+        @Override
+        public @NotNull <U> Option<@NotNull U> map(final @NotNull Function<@NotNull T, @NotNull U> f) {
+            return Option.some(f.apply(this.value));
+        }
+
+        @Override
+        public @NotNull Option<@NotNull T> inspect(final @NotNull Consumer<T> f) {
+            f.accept(this.value);
+
+            return this;
+        }
+
+        @Override
+        public <U> @NotNull U mapOr(@NotNull final U or, final @NotNull Function<@NotNull T, @NotNull U> f) {
+            return f.apply(this.value);
+        }
+
+        @Override
+        public <U> @NotNull U mapOrElse(final @NotNull Supplier<@NotNull U> orElse, final @NotNull Function<@NotNull T, @NotNull U> f) {
+            return f.apply(this.value);
+        }
+
+        @Override
+        public @NotNull <U> Option<@NotNull U> and(final @NotNull Option<@NotNull U> optb) {
+            return optb;
+        }
+
+        @Override
+        public @NotNull <U> Option<@NotNull U> andThen(final @NotNull Function<@NotNull T, @NotNull Option<@NotNull U>> f) {
+            return f.apply(this.value);
+        }
+
+        @Override
+        public @NotNull Option<@NotNull T> filter(final @NotNull Function<@NotNull T, @NotNull Boolean> predicate) {
+            if (predicate.apply(this.value)) {
+                return this;
+            }
+
+            return Option.none();
+        }
+
+        @Override
+        public @NotNull Option<@NotNull T> or(final @NotNull Option<@NotNull T> optb) {
+            return this;
+        }
+
+        @Override
+        public @NotNull Option<@NotNull T> orElse(final @NotNull Supplier<@NotNull Option<@NotNull T>> f) {
+            return this;
+        }
+
+        @Override
+        public @NotNull Option<@NotNull T> xor(final @NotNull Option<@NotNull T> optb) {
+            if (optb.isSome()) {
+                return Option.none();
+            }
+
+            return this;
+        }
+
+        @Override
+        public boolean equals(final @Nullable Object obj) {
+            return obj instanceof final @NotNull Option.Some<?> opt && this.value.equals(opt.get());
+        }
+
+        @Override
+        public @NotNull String toString() {
+            return "Option.Some(" + this.value + ")";
+        }
+    }
+
+    /**
+     * Thrown when a {@link None None} value is unwrapped.
+     */
+    public static final class UnwrapError
+        extends Error
+    {
+        public UnwrapError(final @NotNull String msg) {
+            super(msg);
+        }
+    }
+
+    private static final Option.@NotNull None<?> NONE = Option.none();
+
+    /**
+     * Returns a {@link None None} value.
+     */
+    public static <T> Option.@NotNull None<@NotNull T> none() {
+        return (None<T>) NONE;
+    }
+
+    /**
+     * Returns a {@link Some Some} value wrapping the given {@code T}.
+     */
+    public static <T> Option.@NotNull Some<@NotNull T> some(final @NotNull T value) {
+        return new Some<>(Objects.requireNonNull(value));
+    }
+
+    /**
+     * Returns {@code true} if the option is a {@link Some Some} value.
+     */
+    public abstract boolean isSome();
+
+    /**
+     * Returns {@code true} if the option is a {@link Some Some} value and the value inside of it matches a predicate.
+     */
+    public abstract boolean isSomeAnd(final @NotNull Function<@NotNull T, @NotNull Boolean> f);
+
+    /**
+     * Returns {@code true} if the option is a {@link None None} value.
+     */
+    public abstract boolean isNone();
+
+    /**
+     * Returns {@code true} if the option is a {@link None None} value or the value inside of it matches a predicate.
+     */
+    public abstract boolean isNoneOr(final @NotNull Function<@NotNull T, @NotNull Boolean> f);
+
+    /**
+     * Returns the contained {@link Some Some} value.
+     * @throws UnwrapError if the value is a {@link None None} with a custom exception message provided by
+     * {@code msg}.
+     */
+    public abstract @NotNull T expect(final @NotNull String msg)
+        throws UnwrapError;
+
+    /**
+     * Returns the contained {@link Some Some} value.
+     * <br>
+     * Because this function throws an exception, its use is generally discouraged.
+     * <br>
+     * Instead, prefer to use pattern matching and handle the {@link None None} case explicitly, or call
+     * {@link #unwrapOr} or {@link #unwrapOrElse}.
+     * @throws UnwrapError if the self value equals {@link None None}.
+     */
+    public abstract @NotNull T unwrap()
+        throws UnwrapError;
+
+    /**
+     * Returns the contained {@link Some Some} value or a provided default.
+     * <br>
+     * Arguments passed to {@code unwrapOr} are eagerly evaluated; if you are passing the result of a function call,
+     * it is recommended to use {@link #unwrapOrElse}, which is lazily evaluated.
+     */
+    public abstract @NotNull T unwrapOr(final @NotNull T or);
+
+    /**
+     * Returns the contained {@link Some Some} value or computes it from a supplier.
+     */
+    public abstract @NotNull T unwrapOrElse(final @NotNull Supplier<@NotNull T> f);
+
+    /**
+     * Maps an {@code Option<T>} to {@code Option<U>} by applying a function to a contained value (if
+     * {@link Some Some}) or returns {@link None None} (if {@link None None}).
+     */
+    public abstract <U> @NotNull Option<@NotNull U> map(final @NotNull Function<@NotNull T, @NotNull U> f);
+
+    /**
+     * Calls a function with reference to the contained value if {@link Some Some}.
+     * @return the original option.
+     */
+    public abstract @NotNull Option<@NotNull T> inspect(final @NotNull Consumer<T> f);
+
+    /**
+     * Returns the provided default result (if {@link None None}) or applies a function to the contained value (if
+     * any).
+     * <br>
+     * Arguments passed to {@code mapOr} are eagerly evaluated; if you are passing the result of a function call, it is
+     * recommended to use {@link #mapOrElse}, which is lazily evaluated.
+     */
+    public abstract <U> @NotNull U mapOr(final @NotNull U or, final @NotNull Function<@NotNull T, @NotNull U> f);
+
+    /**
+     * Computes a default function result (if {@link None None}), or applies a different function to the contained
+     * value (if any).
+     */
+    public abstract <U> @NotNull U mapOrElse(final @NotNull Supplier<@NotNull U> orElse, final @NotNull Function<@NotNull T, @NotNull U> f);
+
+    /**
+     * Returns {@link None None} if the option is {@link None None}, otherwise returns {@code optb}.
+     */
+    public abstract <U> @NotNull Option<@NotNull U> and(final @NotNull Option<@NotNull U> optb);
+
+    /**
+     * Returns {@link None None} if the option is {@link None None}, otherwise calls {@code f} with the wrapped value
+     * and returns the result.
+     * <br>
+     * Some languages call this operation flatmap.
+     */
+    public abstract <U> @NotNull Option<@NotNull U> andThen(final @NotNull Function<@NotNull T, @NotNull Option<@NotNull U>> f);
+
+    /**
+     * Returns {@link None None} if the option is {@link None None}, otherwise calls {@code predicate} with the wrapped
+     * value and returns:
+     * <list>
+     *     <li>{@link Option#some Some(t)} if {@code predicate} returns {@code true} (where {@code t} is the wrapped
+     *     value), and
+     *     </li>
+     *     <li>{@link Option#none} if {@code predicate} returns {@code false}.</li>
+     * </list>
+     */
+    public abstract @NotNull Option<@NotNull T> filter(final @NotNull Function<@NotNull T, @NotNull Boolean> predicate);
+
+    /**
+     * Returns the option if it contains a value, otherwise returns {@code optb}.
+     * <br>
+     * Arguments passed to {@code or} are eagerly evaluated; if you are passing the result of a function call, it is
+     * recommended to use {@link #orElse}, which is lazily evaluated.
+     */
+    public abstract @NotNull Option<@NotNull T> or(final @NotNull Option<@NotNull T> optb);
+
+    /**
+     * Returns the option if it contains a value, otherwise calls {@code f} and returns the result.
+     */
+    public abstract @NotNull Option<@NotNull T> orElse(final @NotNull Supplier<@NotNull Option<@NotNull T>> f);
+
+    /**
+     * Returns {@link Some Some} if exactly one of {@code self}, {@code optb} is {@link Some Some}, otherwise returns
+     * {@link None None}.
+     */
+    public abstract @NotNull Option<@NotNull T> xor(final @NotNull Option<@NotNull T> optb);
+}
diff --git a/game/core/src/main/java/net/minecraft/core/world/World.java b/game/core/src/main/java/net/minecraft/core/world/World.java
index dc966a962..347b75b44 100644
--- a/game/core/src/main/java/net/minecraft/core/world/World.java
+++ b/game/core/src/main/java/net/minecraft/core/world/World.java
@@ -1521,8 +1521,8 @@ public class World implements MutableWorldSource {
         byte byte0 = 32;
         if (flag && !areBlocksLoaded(i - byte0, 0, j - byte0, i + byte0, getHeightBlocks() - 1, j + byte0)) {
             //try to despawn if entity wanders into nonexistant chunk
-            if (entity instanceof Mob) {
-                ((Mob) entity).tryToDespawn();
+            if (entity instanceof Mob mob) {
+                mob.tryToDespawn();
             }
             return;
         }
