diff --git a/patches/server/0991-Chunk-System-Starlight-from-Moonrise.patch b/patches/server/0991-Moonrise-optimisation-patches.patch
similarity index 97%
rename from patches/server/0991-Chunk-System-Starlight-from-Moonrise.patch
rename to patches/server/0991-Moonrise-optimisation-patches.patch
index 06bbfbfbce..de0997769f 100644
--- a/patches/server/0991-Chunk-System-Starlight-from-Moonrise.patch
+++ b/patches/server/0991-Moonrise-optimisation-patches.patch
@@ -1,7 +1,11 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Spottedleaf <Spottedleaf@users.noreply.github.com>
 Date: Fri, 14 Jun 2024 11:57:26 -0700
-Subject: [PATCH] Chunk System + Starlight from Moonrise
+Subject: [PATCH] Moonrise optimisation patches
+
+Currently includes:
+ - Starlight + Chunk System
+ - Entity tracker optimisations
 
 See https://github.com/Tuinity/Moonrise
 
@@ -2399,6 +2403,221 @@ index 0000000000000000000000000000000000000000..ab2fa1563d5e32a5313dfcc1da411cab
 +        }
 +    }
 +}
+diff --git a/src/main/java/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java b/src/main/java/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..fdde1f5f988d581db41945916635cdd826a10680
+--- /dev/null
++++ b/src/main/java/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java
+@@ -0,0 +1,209 @@
++package ca.spottedleaf.moonrise.common.misc;
++
++import ca.spottedleaf.moonrise.common.list.ReferenceList;
++import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
++import ca.spottedleaf.moonrise.common.util.MoonriseConstants;
++import ca.spottedleaf.moonrise.patches.chunk_system.ChunkSystem;
++import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap;
++import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap;
++import net.minecraft.core.BlockPos;
++import net.minecraft.server.level.ServerLevel;
++import net.minecraft.server.level.ServerPlayer;
++import net.minecraft.world.level.ChunkPos;
++
++public final class NearbyPlayers {
++
++    public static enum NearbyMapType {
++        GENERAL,
++        GENERAL_SMALL,
++        GENERAL_REALLY_SMALL,
++        TICK_VIEW_DISTANCE,
++        VIEW_DISTANCE,
++        SPAWN_RANGE,
++    }
++
++    private static final NearbyMapType[] MAP_TYPES = NearbyMapType.values();
++    public static final int TOTAL_MAP_TYPES = MAP_TYPES.length;
++
++    private static final int GENERAL_AREA_VIEW_DISTANCE = MoonriseConstants.MAX_VIEW_DISTANCE + 1;
++    private static final int GENERAL_SMALL_VIEW_DISTANCE = 10;
++    private static final int GENERAL_REALLY_SMALL_VIEW_DISTANCE = 3;
++
++    public static final int GENERAL_AREA_VIEW_DISTANCE_BLOCKS = (GENERAL_AREA_VIEW_DISTANCE << 4);
++    public static final int GENERAL_SMALL_AREA_VIEW_DISTANCE_BLOCKS = (GENERAL_SMALL_VIEW_DISTANCE << 4);
++    public static final int GENERAL_REALLY_SMALL_AREA_VIEW_DISTANCE_BLOCKS = (GENERAL_REALLY_SMALL_VIEW_DISTANCE << 4);
++
++    private final ServerLevel world;
++    private final Reference2ReferenceOpenHashMap<ServerPlayer, TrackedPlayer[]> players = new Reference2ReferenceOpenHashMap<>();
++    private final Long2ReferenceOpenHashMap<TrackedChunk> byChunk = new Long2ReferenceOpenHashMap<>();
++
++    public NearbyPlayers(final ServerLevel world) {
++        this.world = world;
++    }
++
++    public void addPlayer(final ServerPlayer player) {
++        final TrackedPlayer[] newTrackers = new TrackedPlayer[TOTAL_MAP_TYPES];
++        if (this.players.putIfAbsent(player, newTrackers) != null) {
++            throw new IllegalStateException("Already have player " + player);
++        }
++
++        final ChunkPos chunk = player.chunkPosition();
++
++        for (int i = 0; i < TOTAL_MAP_TYPES; ++i) {
++            // use 0 for default, will be updated by tickPlayer
++            (newTrackers[i] = new TrackedPlayer(player, MAP_TYPES[i])).add(chunk.x, chunk.z, 0);
++        }
++
++        // update view distances
++        this.tickPlayer(player);
++    }
++
++    public void removePlayer(final ServerPlayer player) {
++        final TrackedPlayer[] players = this.players.remove(player);
++        if (players == null) {
++            return; // May be called during teleportation before the player is actually placed
++        }
++
++        for (final TrackedPlayer tracker : players) {
++            tracker.remove();
++        }
++    }
++
++    public void tickPlayer(final ServerPlayer player) {
++        final TrackedPlayer[] players = this.players.get(player);
++        if (players == null) {
++            throw new IllegalStateException("Don't have player " + player);
++        }
++
++        final ChunkPos chunk = player.chunkPosition();
++
++        players[NearbyMapType.GENERAL.ordinal()].update(chunk.x, chunk.z, GENERAL_AREA_VIEW_DISTANCE);
++        players[NearbyMapType.GENERAL_SMALL.ordinal()].update(chunk.x, chunk.z, GENERAL_SMALL_VIEW_DISTANCE);
++        players[NearbyMapType.GENERAL_REALLY_SMALL.ordinal()].update(chunk.x, chunk.z, GENERAL_REALLY_SMALL_VIEW_DISTANCE);
++        players[NearbyMapType.TICK_VIEW_DISTANCE.ordinal()].update(chunk.x, chunk.z, ChunkSystem.getTickViewDistance(player));
++        players[NearbyMapType.VIEW_DISTANCE.ordinal()].update(chunk.x, chunk.z, ChunkSystem.getLoadViewDistance(player));
++    }
++
++    public TrackedChunk getChunk(final ChunkPos pos) {
++        return this.byChunk.get(CoordinateUtils.getChunkKey(pos));
++    }
++
++    public TrackedChunk getChunk(final BlockPos pos) {
++        return this.byChunk.get(CoordinateUtils.getChunkKey(pos));
++    }
++
++    public ReferenceList<ServerPlayer> getPlayers(final BlockPos pos, final NearbyMapType type) {
++        final TrackedChunk chunk = this.byChunk.get(CoordinateUtils.getChunkKey(pos));
++
++        return chunk == null ? null : chunk.players[type.ordinal()];
++    }
++
++    public ReferenceList<ServerPlayer> getPlayers(final ChunkPos pos, final NearbyMapType type) {
++        final TrackedChunk chunk = this.byChunk.get(CoordinateUtils.getChunkKey(pos));
++
++        return chunk == null ? null : chunk.players[type.ordinal()];
++    }
++
++    public ReferenceList<ServerPlayer> getPlayersByChunk(final int chunkX, final int chunkZ, final NearbyMapType type) {
++        final TrackedChunk chunk = this.byChunk.get(CoordinateUtils.getChunkKey(chunkX, chunkZ));
++
++        return chunk == null ? null : chunk.players[type.ordinal()];
++    }
++
++    public ReferenceList<ServerPlayer> getPlayersByBlock(final int blockX, final int blockZ, final NearbyMapType type) {
++        final TrackedChunk chunk = this.byChunk.get(CoordinateUtils.getChunkKey(blockX >> 4, blockZ >> 4));
++
++        return chunk == null ? null : chunk.players[type.ordinal()];
++    }
++
++    public static final class TrackedChunk {
++
++        private static final ServerPlayer[] EMPTY_PLAYERS_ARRAY = new ServerPlayer[0];
++
++        private final ReferenceList<ServerPlayer>[] players = new ReferenceList[TOTAL_MAP_TYPES];
++        private int nonEmptyLists;
++        private long updateCount;
++
++        public boolean isEmpty() {
++            return this.nonEmptyLists == 0;
++        }
++
++        public long getUpdateCount() {
++            return this.updateCount;
++        }
++
++        public ReferenceList<ServerPlayer> getPlayers(final NearbyMapType type) {
++            return this.players[type.ordinal()];
++        }
++
++        public void addPlayer(final ServerPlayer player, final NearbyMapType type) {
++            ++this.updateCount;
++
++            final int idx = type.ordinal();
++            final ReferenceList<ServerPlayer> list = this.players[idx];
++            if (list == null) {
++                ++this.nonEmptyLists;
++                (this.players[idx] = new ReferenceList<>(EMPTY_PLAYERS_ARRAY, 0)).add(player);
++                return;
++            }
++
++            if (!list.add(player)) {
++                throw new IllegalStateException("Already contains player " + player);
++            }
++        }
++
++        public void removePlayer(final ServerPlayer player, final NearbyMapType type) {
++            ++this.updateCount;
++
++            final int idx = type.ordinal();
++            final ReferenceList<ServerPlayer> list = this.players[idx];
++            if (list == null) {
++                throw new IllegalStateException("Does not contain player " + player);
++            }
++
++            if (!list.remove(player)) {
++                throw new IllegalStateException("Does not contain player " + player);
++            }
++
++            if (list.size() == 0) {
++                this.players[idx] = null;
++                --this.nonEmptyLists;
++            }
++        }
++    }
++
++    private final class TrackedPlayer extends SingleUserAreaMap<ServerPlayer> {
++
++        private final NearbyMapType type;
++
++        public TrackedPlayer(final ServerPlayer player, final NearbyMapType type) {
++            super(player);
++            this.type = type;
++        }
++
++        @Override
++        protected void addCallback(final ServerPlayer parameter, final int chunkX, final int chunkZ) {
++            final long chunkKey = CoordinateUtils.getChunkKey(chunkX, chunkZ);
++
++            NearbyPlayers.this.byChunk.computeIfAbsent(chunkKey, (final long keyInMap) -> {
++                return new TrackedChunk();
++            }).addPlayer(parameter, this.type);
++        }
++
++        @Override
++        protected void removeCallback(final ServerPlayer parameter, final int chunkX, final int chunkZ) {
++            final long chunkKey = CoordinateUtils.getChunkKey(chunkX, chunkZ);
++
++            final TrackedChunk chunk = NearbyPlayers.this.byChunk.get(chunkKey);
++            if (chunk == null) {
++                throw new IllegalStateException("Chunk should exist at " + new ChunkPos(chunkKey));
++            }
++
++            chunk.removePlayer(parameter, this.type);
++
++            if (chunk.isEmpty()) {
++                NearbyPlayers.this.byChunk.remove(chunkKey);
++            }
++        }
++    }
++}
 diff --git a/src/main/java/ca/spottedleaf/moonrise/common/misc/SingleUserAreaMap.java b/src/main/java/ca/spottedleaf/moonrise/common/misc/SingleUserAreaMap.java
 new file mode 100644
 index 0000000000000000000000000000000000000000..61f70247486fd15ed3ffc5b606582dc6a2dd81d3
@@ -4932,13 +5151,14 @@ index 0000000000000000000000000000000000000000..0b58701342d573fa43cdd06681534854
 +}
 diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/ChunkSystemServerLevel.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/ChunkSystemServerLevel.java
 new file mode 100644
-index 0000000000000000000000000000000000000000..6828a3ca7151692a41b5370f680f867958a214fc
+index 0000000000000000000000000000000000000000..1a06c2c139e930d2081e605b460ae5403de8c3ea
 --- /dev/null
 +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/ChunkSystemServerLevel.java
-@@ -0,0 +1,50 @@
+@@ -0,0 +1,53 @@
 +package ca.spottedleaf.moonrise.patches.chunk_system.level;
 +
 +import ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor;
++import ca.spottedleaf.moonrise.common.misc.NearbyPlayers;
 +import ca.spottedleaf.moonrise.patches.chunk_system.io.RegionFileIOThread;
 +import ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader;
 +import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkTaskScheduler;
@@ -4985,6 +5205,8 @@ index 0000000000000000000000000000000000000000..6828a3ca7151692a41b5370f680f8679
 +    public long moonrise$getLastMidTickFailure();
 +
 +    public void moonrise$setLastMidTickFailure(final long time);
++
++    public NearbyPlayers moonrise$getNearbyPlayers();
 +}
 diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/chunk/ChunkSystemChunkHolder.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/chunk/ChunkSystemChunkHolder.java
 new file mode 100644
@@ -5905,10 +6127,10 @@ index 0000000000000000000000000000000000000000..997b05167c19472acb98edac32d4548c
 +}
 diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/EntityLookup.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/EntityLookup.java
 new file mode 100644
-index 0000000000000000000000000000000000000000..f6a3eb3d1bb070bcc74133818682571d520d9894
+index 0000000000000000000000000000000000000000..a346435abac725b4e024acf4a1589a51caac8d69
 --- /dev/null
 +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/EntityLookup.java
-@@ -0,0 +1,1044 @@
+@@ -0,0 +1,1077 @@
 +package ca.spottedleaf.moonrise.patches.chunk_system.level.entity;
 +
 +import ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable;
@@ -5984,6 +6206,24 @@ index 0000000000000000000000000000000000000000..f6a3eb3d1bb070bcc74133818682571d
 +
 +    protected abstract void onEmptySlices(final int chunkX, final int chunkZ);
 +
++    protected abstract void entitySectionChangeCallback(
++            final Entity entity,
++            final int oldSectionX, final int oldSectionY, final int oldSectionZ,
++            final int newSectionX, final int newSectionY, final int newSectionZ
++    );
++
++    protected abstract void addEntityCallback(final Entity entity);
++
++    protected abstract void removeEntityCallback(final Entity entity);
++
++    protected abstract void entityStartLoaded(final Entity entity);
++
++    protected abstract void entityEndLoaded(final Entity entity);
++
++    protected abstract void entityStartTicking(final Entity entity);
++
++    protected abstract void entityEndTicking(final Entity entity);
++
 +    private static Entity maskNonAccessible(final Entity entity) {
 +        if (entity == null) {
 +            return null;
@@ -6162,6 +6402,7 @@ index 0000000000000000000000000000000000000000..f6a3eb3d1bb070bcc74133818682571d
 +                    if (newVisibility.ordinal() > oldVisibility.ordinal()) {
 +                        // status upgrade
 +                        if (!oldVisibility.isAccessible() && newVisibility.isAccessible()) {
++                            EntityLookup.this.entityStartLoaded(entity);
 +                            synchronized (this.accessibleEntities) {
 +                                this.accessibleEntities.add(entity);
 +                            }
@@ -6171,6 +6412,7 @@ index 0000000000000000000000000000000000000000..f6a3eb3d1bb070bcc74133818682571d
 +                        }
 +
 +                        if (!oldVisibility.isTicking() && newVisibility.isTicking()) {
++                            EntityLookup.this.entityStartTicking(entity);
 +                            if (EntityLookup.this.worldCallback != null) {
 +                                EntityLookup.this.worldCallback.onTickingStart(entity);
 +                            }
@@ -6178,12 +6420,14 @@ index 0000000000000000000000000000000000000000..f6a3eb3d1bb070bcc74133818682571d
 +                    } else {
 +                        // status downgrade
 +                        if (oldVisibility.isTicking() && !newVisibility.isTicking()) {
++                            EntityLookup.this.entityEndTicking(entity);
 +                            if (EntityLookup.this.worldCallback != null) {
 +                                EntityLookup.this.worldCallback.onTickingEnd(entity);
 +                            }
 +                        }
 +
 +                        if (oldVisibility.isAccessible() && !newVisibility.isAccessible()) {
++                            EntityLookup.this.entityEndLoaded(entity);
 +                            synchronized (this.accessibleEntities) {
 +                                this.accessibleEntities.remove(entity);
 +                            }
@@ -6325,6 +6569,8 @@ index 0000000000000000000000000000000000000000..f6a3eb3d1bb070bcc74133818682571d
 +
 +        entity.setLevelCallback(new EntityCallback(entity));
 +
++        this.addEntityCallback(entity);
++
 +        this.entityStatusChange(entity, slices, Visibility.HIDDEN, getEntityStatus(entity), false, !fromDisk, false);
 +
 +        return true;
@@ -6432,6 +6678,12 @@ index 0000000000000000000000000000000000000000..f6a3eb3d1bb070bcc74133818682571d
 +            this.onEmptySlices(sectionX, sectionZ);
 +        }
 +
++        this.entitySectionChangeCallback(
++                entity,
++                sectionX, sectionY, sectionZ,
++                newSectionX, newSectionY, newSectionZ
++        );
++
 +        return slices;
 +    }
 +
@@ -6923,6 +7175,7 @@ index 0000000000000000000000000000000000000000..f6a3eb3d1bb070bcc74133818682571d
 +                // no new section, so didn't change sections
 +                return;
 +            }
++
 +            final Visibility newVisibility = getEntityStatus(entity);
 +
 +            EntityLookup.this.entityStatusChange(entity, newSlices, oldVisibility, newVisibility, true, false, false);
@@ -6938,6 +7191,8 @@ index 0000000000000000000000000000000000000000..f6a3eb3d1bb070bcc74133818682571d
 +
 +            EntityLookup.this.entityStatusChange(entity, null, tickingState, Visibility.HIDDEN, false, false, reason.shouldDestroy());
 +
++            EntityLookup.this.removeEntityCallback(entity);
++
 +            this.entity.setLevelCallback(NoOpCallback.INSTANCE);
 +        }
 +    }
@@ -6956,10 +7211,10 @@ index 0000000000000000000000000000000000000000..f6a3eb3d1bb070bcc74133818682571d
 \ No newline at end of file
 diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/client/ClientEntityLookup.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/client/ClientEntityLookup.java
 new file mode 100644
-index 0000000000000000000000000000000000000000..fc4ea13aa4a21bd3d3f9377418a24b904868c401
+index 0000000000000000000000000000000000000000..77e81414d43826955da8af85ec1bd0009af4e1b9
 --- /dev/null
 +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/client/ClientEntityLookup.java
-@@ -0,0 +1,81 @@
+@@ -0,0 +1,118 @@
 +package ca.spottedleaf.moonrise.patches.chunk_system.level.entity.client;
 +
 +import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
@@ -7021,6 +7276,43 @@ index 0000000000000000000000000000000000000000..fc4ea13aa4a21bd3d3f9377418a24b90
 +        this.removeChunk(chunkX, chunkZ);
 +    }
 +
++    @Override
++    protected void entitySectionChangeCallback(final Entity entity,
++                                               final int oldSectionX, final int oldSectionY, final int oldSectionZ,
++                                               final int newSectionX, final int newSectionY, final int newSectionZ) {
++
++    }
++
++    @Override
++    protected void addEntityCallback(final Entity entity) {
++
++    }
++
++    @Override
++    protected void removeEntityCallback(final Entity entity) {
++
++    }
++
++    @Override
++    protected void entityStartLoaded(final Entity entity) {
++
++    }
++
++    @Override
++    protected void entityEndLoaded(final Entity entity) {
++
++    }
++
++    @Override
++    protected void entityStartTicking(final Entity entity) {
++
++    }
++
++    @Override
++    protected void entityEndTicking(final Entity entity) {
++
++    }
++
 +    public void markTicking(final long pos) {
 +        if (this.tickingChunks.add(pos)) {
 +            final int chunkX = CoordinateUtils.getChunkX(pos);
@@ -7043,10 +7335,10 @@ index 0000000000000000000000000000000000000000..fc4ea13aa4a21bd3d3f9377418a24b90
 +}
 diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/dfl/DefaultEntityLookup.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/dfl/DefaultEntityLookup.java
 new file mode 100644
-index 0000000000000000000000000000000000000000..a9b0e8e90f433e141f36e47a9331cbdcb9ac9817
+index 0000000000000000000000000000000000000000..4747499e84b05d499364622b0f750fdd66b737e0
 --- /dev/null
 +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/dfl/DefaultEntityLookup.java
-@@ -0,0 +1,72 @@
+@@ -0,0 +1,109 @@
 +package ca.spottedleaf.moonrise.patches.chunk_system.level.entity.dfl;
 +
 +import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
@@ -7095,6 +7387,43 @@ index 0000000000000000000000000000000000000000..a9b0e8e90f433e141f36e47a9331cbdc
 +        this.removeChunk(chunkX, chunkZ);
 +    }
 +
++    @Override
++    protected void entitySectionChangeCallback(final Entity entity,
++                                               final int oldSectionX, final int oldSectionY, final int oldSectionZ,
++                                               final int newSectionX, final int newSectionY, final int newSectionZ) {
++
++    }
++
++    @Override
++    protected void addEntityCallback(final Entity entity) {
++
++    }
++
++    @Override
++    protected void removeEntityCallback(final Entity entity) {
++
++    }
++
++    @Override
++    protected void entityStartLoaded(final Entity entity) {
++
++    }
++
++    @Override
++    protected void entityEndLoaded(final Entity entity) {
++
++    }
++
++    @Override
++    protected void entityStartTicking(final Entity entity) {
++
++    }
++
++    @Override
++    protected void entityEndTicking(final Entity entity) {
++
++    }
++
 +    protected static final class DefaultLevelCallback implements LevelCallback<Entity> {
 +
 +        @Override
@@ -7121,22 +7450,28 @@ index 0000000000000000000000000000000000000000..a9b0e8e90f433e141f36e47a9331cbdc
 +}
 diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/server/ServerEntityLookup.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/server/ServerEntityLookup.java
 new file mode 100644
-index 0000000000000000000000000000000000000000..5b68279cae5952bdb7bdef3668980385a3a643e0
+index 0000000000000000000000000000000000000000..eb1b0b3594ae6861a05010949ba94a60f73ecc8b
 --- /dev/null
 +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/server/ServerEntityLookup.java
-@@ -0,0 +1,50 @@
+@@ -0,0 +1,106 @@
 +package ca.spottedleaf.moonrise.patches.chunk_system.level.entity.server;
 +
++import ca.spottedleaf.moonrise.common.list.ReferenceList;
 +import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
 +import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.ChunkEntitySlices;
 +import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup;
 +import net.minecraft.server.level.ServerLevel;
++import net.minecraft.server.level.ServerPlayer;
 +import net.minecraft.world.entity.Entity;
 +import net.minecraft.world.level.entity.LevelCallback;
 +
 +public final class ServerEntityLookup extends EntityLookup {
 +
++    private static final Entity[] EMPTY_ENTITY_ARRAY = new Entity[0];
++
 +    private final ServerLevel serverWorld;
++    public final ReferenceList<Entity> trackerEntities = new ReferenceList<>(EMPTY_ENTITY_ARRAY, 0); // Moonrise - entity tracker
++    public final ReferenceList<Entity> trackerUnloadedEntities = new ReferenceList<>(EMPTY_ENTITY_ARRAY, 0); // Moonrise - entity tracker
 +
 +    public ServerEntityLookup(final ServerLevel world, final LevelCallback<Entity> worldCallback) {
 +        super(world, worldCallback);
@@ -7174,6 +7509,56 @@ index 0000000000000000000000000000000000000000..5b68279cae5952bdb7bdef3668980385
 +    protected void onEmptySlices(final int chunkX, final int chunkZ) {
 +        // entity slices unloading is managed by ticket levels in chunk system
 +    }
++
++    @Override
++    protected void entitySectionChangeCallback(final Entity entity,
++                                               final int oldSectionX, final int oldSectionY, final int oldSectionZ,
++                                               final int newSectionX, final int newSectionY, final int newSectionZ) {
++        if (entity instanceof ServerPlayer player) {
++            ((ChunkSystemServerLevel)this.serverWorld).moonrise$getNearbyPlayers().tickPlayer(player);
++        }
++    }
++
++    @Override
++    protected void addEntityCallback(final Entity entity) {
++        if (entity instanceof ServerPlayer player) {
++            ((ChunkSystemServerLevel)this.serverWorld).moonrise$getNearbyPlayers().addPlayer(player);
++        }
++    }
++
++    @Override
++    protected void removeEntityCallback(final Entity entity) {
++        if (entity instanceof ServerPlayer player) {
++            ((ChunkSystemServerLevel)this.serverWorld).moonrise$getNearbyPlayers().removePlayer(player);
++        }
++        this.trackerUnloadedEntities.remove(entity); // Moonrise - entity tracker
++    }
++
++    @Override
++    protected void entityStartLoaded(final Entity entity) {
++        // Moonrise start - entity tracker
++        this.trackerEntities.add(entity);
++        this.trackerUnloadedEntities.remove(entity);
++        // Moonrise end - entity tracker
++    }
++
++    @Override
++    protected void entityEndLoaded(final Entity entity) {
++        // Moonrise start - entity tracker
++        this.trackerEntities.remove(entity);
++        this.trackerUnloadedEntities.add(entity);
++        // Moonrise end - entity tracker
++    }
++
++    @Override
++    protected void entityStartTicking(final Entity entity) {
++
++    }
++
++    @Override
++    protected void entityEndTicking(final Entity entity) {
++
++    }
 +}
 diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/poi/ChunkSystemPoiManager.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/poi/ChunkSystemPoiManager.java
 new file mode 100644
@@ -7483,10 +7868,10 @@ index 0000000000000000000000000000000000000000..003a857e70ead858e8437e3c1bfaf22f
 +}
 diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
 new file mode 100644
-index 0000000000000000000000000000000000000000..82e8ce73b77accd6a4210f88c9fccb325ae367d4
+index 0000000000000000000000000000000000000000..f063ab3ff122b920bcc4aa4f5bf9a442a8eb32fd
 --- /dev/null
 +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
-@@ -0,0 +1,1074 @@
+@@ -0,0 +1,1076 @@
 +package ca.spottedleaf.moonrise.patches.chunk_system.player;
 +
 +import ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor;
@@ -7688,6 +8073,8 @@ index 0000000000000000000000000000000000000000..82e8ce73b77accd6a4210f88c9fccb32
 +        final PlayerChunkLoaderData loader = ((ChunkSystemServerPlayer)player).moonrise$getChunkLoader();
 +        if (loader != null) {
 +            loader.update();
++            // update view distances for nearby players
++            ((ChunkSystemServerLevel)loader.world).moonrise$getNearbyPlayers().tickPlayer(player);
 +        }
 +    }
 +
@@ -17879,6 +18266,42 @@ index 0000000000000000000000000000000000000000..4b9e2fa963c14f65f15407c1814c543c
 +    public LevelChunk moonrise$getFullChunkIfLoaded(final int chunkX, final int chunkZ);
 +
 +}
+diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/entity_tracker/EntityTrackerEntity.java b/src/main/java/ca/spottedleaf/moonrise/patches/entity_tracker/EntityTrackerEntity.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..5f5734c00ce8245a1ff69b2d4c3036579d5392e0
+--- /dev/null
++++ b/src/main/java/ca/spottedleaf/moonrise/patches/entity_tracker/EntityTrackerEntity.java
+@@ -0,0 +1,11 @@
++package ca.spottedleaf.moonrise.patches.entity_tracker;
++
++import net.minecraft.server.level.ChunkMap;
++
++public interface EntityTrackerEntity {
++
++    public ChunkMap.TrackedEntity moonrise$getTrackedEntity();
++
++    public void moonrise$setTrackedEntity(final ChunkMap.TrackedEntity trackedEntity);
++
++}
+diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/entity_tracker/EntityTrackerTrackedEntity.java b/src/main/java/ca/spottedleaf/moonrise/patches/entity_tracker/EntityTrackerTrackedEntity.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..1fa07bef57d82c6d5242aaaf66011f0913515231
+--- /dev/null
++++ b/src/main/java/ca/spottedleaf/moonrise/patches/entity_tracker/EntityTrackerTrackedEntity.java
+@@ -0,0 +1,13 @@
++package ca.spottedleaf.moonrise.patches.entity_tracker;
++
++import ca.spottedleaf.moonrise.common.misc.NearbyPlayers;
++
++public interface EntityTrackerTrackedEntity {
++
++    public void moonrise$tick(final NearbyPlayers.TrackedChunk chunk);
++
++    public void moonrise$removeNonTickThreadPlayers();
++
++    public void moonrise$clearPlayers();
++
++}
 diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/starlight/blockstate/StarlightAbstractBlockState.java b/src/main/java/ca/spottedleaf/moonrise/patches/starlight/blockstate/StarlightAbstractBlockState.java
 new file mode 100644
 index 0000000000000000000000000000000000000000..2bfdf3721db9a45e36538d71cbefcb1d339e6c58
@@ -23805,7 +24228,7 @@ index d9ad32acdf46a43a649334a3b736aeb7b3af21d1..fae17a075d7efaf24d916877dd5968eb
      public static final int RADIUS_AROUND_FULL_CHUNK = FULL_CHUNK_STEP.accumulatedDependencies().getRadius();
      public static final int MAX_LEVEL = 33 + RADIUS_AROUND_FULL_CHUNK;
 diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
-index a03385b1b0a2f9b98319137b87d917856d3c632c..1363dda031d1b541d76241812a957a12521cbc05 100644
+index a03385b1b0a2f9b98319137b87d917856d3c632c..d843bc04ae93d11d7820cab5ed18617193568f0d 100644
 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java
 +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
 @@ -122,10 +122,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -24538,8 +24961,8 @@ index a03385b1b0a2f9b98319137b87d917856d3c632c..1363dda031d1b541d76241812a957a12
      private static void dropChunk(ServerPlayer player, ChunkPos pos) {
 -        player.connection.chunkSender.dropChunk(player, pos);
 +        // Paper - rewrite chunk system
-+    }
-+
+     }
+ 
 +    // Paper start - rewrite chunk system
 +    @Override
 +    public CompletableFuture<Optional<CompoundTag>> read(final ChunkPos pos) {
@@ -24558,8 +24981,8 @@ index a03385b1b0a2f9b98319137b87d917856d3c632c..1363dda031d1b541d76241812a957a12
 +            }
 +        }
 +        return super.read(pos);
-     }
- 
++    }
++
 +    @Override
 +    public CompletableFuture<Void> write(final ChunkPos pos, final CompoundTag tag) {
 +        if (!ca.spottedleaf.moonrise.patches.chunk_system.io.RegionFileIOThread.isRegionFileThread()) {
@@ -24608,7 +25031,26 @@ index a03385b1b0a2f9b98319137b87d917856d3c632c..1363dda031d1b541d76241812a957a12
          }
  
      }
-@@ -1212,71 +822,31 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -1176,17 +786,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+     }
+ 
+     public void move(ServerPlayer player) {
+-        ObjectIterator objectiterator = this.entityMap.values().iterator();
+-
+-        while (objectiterator.hasNext()) {
+-            ChunkMap.TrackedEntity playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next();
+-
+-            if (playerchunkmap_entitytracker.entity == player) {
+-                playerchunkmap_entitytracker.updatePlayers(this.level.players());
+-            } else {
+-                playerchunkmap_entitytracker.updatePlayer(player);
+-            }
+-        }
++        // Paper - optimise entity tracker
+ 
+         SectionPos sectionposition = player.getLastSectionPos();
+         SectionPos sectionposition1 = SectionPos.of((EntityAccess) player);
+@@ -1212,71 +812,31 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
                  this.playerMap.unIgnorePlayer(player);
              }
  
@@ -24691,22 +25133,75 @@ index a03385b1b0a2f9b98319137b87d917856d3c632c..1363dda031d1b541d76241812a957a12
      }
  
      public void addEntity(Entity entity) {
-@@ -1347,13 +917,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -1304,6 +864,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+ 
+                     entity.tracker = playerchunkmap_entitytracker; // Paper - Fast access to tracker
+                     this.entityMap.put(entity.getId(), playerchunkmap_entitytracker);
++                    // Paper start - optimise entity tracker
++                    if (((ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity)entity).moonrise$getTrackedEntity() != null) {
++                        throw new IllegalStateException("Entity is already tracked");
++                    }
++                    ((ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity)entity).moonrise$setTrackedEntity(playerchunkmap_entitytracker);
++                    // Paper end - optimise entity tracker
+                     playerchunkmap_entitytracker.updatePlayers(this.level.players());
+                     if (entity instanceof ServerPlayer) {
+                         ServerPlayer entityplayer = (ServerPlayer) entity;
+@@ -1344,16 +910,49 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+             playerchunkmap_entitytracker1.broadcastRemoved();
+         }
+         entity.tracker = null; // Paper - We're no longer tracked
++        ((ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity)entity).moonrise$setTrackedEntity(null); // Paper - optimise entity tracker
      }
  
-     protected void tick() {
+-    protected void tick() {
 -        Iterator iterator = this.playerMap.getAllPlayers().iterator();
--
++    // Paper start - optimise entity tracker
++    private void newTrackerTick() {
++        final ca.spottedleaf.moonrise.common.misc.NearbyPlayers nearbyPlayers = ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getNearbyPlayers();
++        final ca.spottedleaf.moonrise.patches.chunk_system.level.entity.server.ServerEntityLookup entityLookup = (ca.spottedleaf.moonrise.patches.chunk_system.level.entity.server.ServerEntityLookup)((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getEntityLookup();;
+ 
 -        while (iterator.hasNext()) {
 -            ServerPlayer entityplayer = (ServerPlayer) iterator.next();
--
++        final ca.spottedleaf.moonrise.common.list.ReferenceList<net.minecraft.world.entity.Entity> trackerEntities = entityLookup.trackerEntities;
++        final Entity[] trackerEntitiesRaw = trackerEntities.getRawDataUnchecked();
++        for (int i = 0, len = trackerEntities.size(); i < len; ++i) {
++            final Entity entity = trackerEntitiesRaw[i];
++            final ChunkMap.TrackedEntity tracker = ((ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity)entity).moonrise$getTrackedEntity();
++            if (tracker == null) {
++                continue;
++            }
++            ((ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerTrackedEntity)tracker).moonrise$tick(nearbyPlayers.getChunk(entity.chunkPosition()));
++            tracker.serverEntity.sendChanges();
++        }
++
++        // process unloads
++        final ca.spottedleaf.moonrise.common.list.ReferenceList<net.minecraft.world.entity.Entity> unloadedEntities = entityLookup.trackerUnloadedEntities;
++        final Entity[] unloadedEntitiesRaw = java.util.Arrays.copyOf(unloadedEntities.getRawDataUnchecked(), unloadedEntities.size());
++        unloadedEntities.clear();
+ 
 -            this.updateChunkTracking(entityplayer);
--        }
++        for (final Entity entity : unloadedEntitiesRaw) {
++            final ChunkMap.TrackedEntity tracker = ((ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity)entity).moonrise$getTrackedEntity();
++            if (tracker == null) {
++                continue;
++            }
++            ((ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerTrackedEntity)tracker).moonrise$clearPlayers();
++        }
++    }
++    // Paper end - optimise entity tracker
++
++    protected void tick() {
++        // Paper start - optimise entity tracker
++        if (true) {
++            this.newTrackerTick();
++            return;
+         }
++        // Paper end - optimise entity tracker
 +        // Paper - rewrite chunk system
  
          List<ServerPlayer> list = Lists.newArrayList();
          List<ServerPlayer> list1 = this.level.players();
-@@ -1460,27 +1024,25 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -1460,27 +1059,25 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
      }
  
      public void waitForLightBeforeSending(ChunkPos centerPos, int radius) {
@@ -24744,6 +25239,100 @@ index a03385b1b0a2f9b98319137b87d917856d3c632c..1363dda031d1b541d76241812a957a12
          }
  
          @Nullable
+@@ -1496,7 +1093,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+         }
+     }
+ 
+-    public class TrackedEntity {
++    public class TrackedEntity implements ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerTrackedEntity { // Paper - optimise entity tracker
+ 
+         public final ServerEntity serverEntity;
+         final Entity entity;
+@@ -1504,6 +1101,84 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+         SectionPos lastSectionPos;
+         public final Set<ServerPlayerConnection> seenBy = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(); // Paper - Perf: optimise map impl
+ 
++        // Paper start - optimise entity tracker
++        private long lastChunkUpdate = -1L;
++        private ca.spottedleaf.moonrise.common.misc.NearbyPlayers.TrackedChunk lastTrackedChunk;
++
++        @Override
++        public final void moonrise$tick(final ca.spottedleaf.moonrise.common.misc.NearbyPlayers.TrackedChunk chunk) {
++            if (chunk == null) {
++                this.moonrise$clearPlayers();
++                return;
++            }
++
++            final ca.spottedleaf.moonrise.common.list.ReferenceList<ServerPlayer> players = chunk.getPlayers(ca.spottedleaf.moonrise.common.misc.NearbyPlayers.NearbyMapType.VIEW_DISTANCE);
++
++            if (players == null) {
++                this.moonrise$clearPlayers();
++                return;
++            }
++
++            final long lastChunkUpdate = this.lastChunkUpdate;
++            final long currChunkUpdate = chunk.getUpdateCount();
++            final ca.spottedleaf.moonrise.common.misc.NearbyPlayers.TrackedChunk lastTrackedChunk = this.lastTrackedChunk;
++            this.lastChunkUpdate = currChunkUpdate;
++            this.lastTrackedChunk = chunk;
++
++            final ServerPlayer[] playersRaw = players.getRawDataUnchecked();
++
++            for (int i = 0, len = players.size(); i < len; ++i) {
++                final ServerPlayer player = playersRaw[i];
++                this.updatePlayer(player);
++            }
++
++            if (lastChunkUpdate != currChunkUpdate || lastTrackedChunk != chunk) {
++                // need to purge any players possible not in the chunk list
++                for (final ServerPlayerConnection conn : new java.util.ArrayList<>(this.seenBy)) {
++                    final ServerPlayer player = conn.getPlayer();
++                    if (!players.contains(player)) {
++                        this.removePlayer(player);
++                    }
++                }
++            }
++        }
++
++        @Override
++        public final void moonrise$removeNonTickThreadPlayers() {
++            boolean foundToRemove = false;
++            for (final ServerPlayerConnection conn : this.seenBy) {
++                if (!io.papermc.paper.util.TickThread.isTickThreadFor(conn.getPlayer())) {
++                    foundToRemove = true;
++                    break;
++                }
++            }
++
++            if (!foundToRemove) {
++                return;
++            }
++
++            for (final ServerPlayerConnection conn : new java.util.ArrayList<>(this.seenBy)) {
++                ServerPlayer player = conn.getPlayer();
++                if (!io.papermc.paper.util.TickThread.isTickThreadFor(player)) {
++                    this.removePlayer(player);
++                }
++            }
++        }
++
++        @Override
++        public final void moonrise$clearPlayers() {
++            this.lastChunkUpdate = -1;
++            this.lastTrackedChunk = null;
++            if (this.seenBy.isEmpty()) {
++                return;
++            }
++            for (final ServerPlayerConnection conn : new java.util.ArrayList<>(this.seenBy)) {
++                ServerPlayer player = conn.getPlayer();
++                this.removePlayer(player);
++            }
++        }
++        // Paper end - optimise entity tracker
++
+         public TrackedEntity(final Entity entity, final int i, final int j, final boolean flag) {
+             this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, j, flag, this::broadcast, this.seenBy); // CraftBukkit
+             this.entity = entity;
 diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java
 index cbabbfbb9967ddf9a56f3be24a88e0fcd4415aa2..71abe25cfb73af3857cbc85980aa32d0201aab62 100644
 --- a/src/main/java/net/minecraft/server/level/DistanceManager.java
@@ -25887,7 +26476,7 @@ index be9604a0f267558c95125852d86761a2f175732a..67eb2fb32de3555b3afb4b4b7a3a47a1
          }
      }
 diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
-index 4d7e234d379a451c4bb53bc2fcdf22cb191f8d1a..cf33e22ae85cd30b4f5d526dbfececca87d4ee40 100644
+index 4d7e234d379a451c4bb53bc2fcdf22cb191f8d1a..e955bf0c9f76f6e90bd726342f204e999090fee1 100644
 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java
 +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
 @@ -184,7 +184,7 @@ import org.bukkit.event.weather.LightningStrikeEvent;
@@ -25908,7 +26497,7 @@ index 4d7e234d379a451c4bb53bc2fcdf22cb191f8d1a..cf33e22ae85cd30b4f5d526dbfececca
      private final GameEventDispatcher gameEventDispatcher;
      public boolean noSave;
      private final SleepStatus sleepStatus;
-@@ -339,6 +339,179 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -339,6 +339,185 @@ public class ServerLevel extends Level implements WorldGenLevel {
          return player != null && player.level() == this ? player : null;
      }
      // Paper end - optimise getPlayerByUUID
@@ -25922,6 +26511,7 @@ index 4d7e234d379a451c4bb53bc2fcdf22cb191f8d1a..cf33e22ae85cd30b4f5d526dbfececca
 +    private final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkTaskScheduler chunkTaskScheduler;
 +    private long lastMidTickFailure;
 +    private long tickedBlocksOrFluids;
++    private final ca.spottedleaf.moonrise.common.misc.NearbyPlayers nearbyPlayers = new ca.spottedleaf.moonrise.common.misc.NearbyPlayers((ServerLevel)(Object)this);
 +
 +    @Override
 +    public final LevelChunk moonrise$getFullChunkIfLoaded(final int chunkX, final int chunkZ) {
@@ -26084,11 +26674,16 @@ index 4d7e234d379a451c4bb53bc2fcdf22cb191f8d1a..cf33e22ae85cd30b4f5d526dbfececca
 +    public final void moonrise$setLastMidTickFailure(final long time) {
 +        this.lastMidTickFailure = time;
 +    }
++
++    @Override
++    public final ca.spottedleaf.moonrise.common.misc.NearbyPlayers moonrise$getNearbyPlayers() {
++        return this.nearbyPlayers;
++    }
 +    // Paper end - rewrite chunk system
  
      // Add env and gen to constructor, IWorldDataServer -> WorldDataServer
      public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PrimaryLevelData iworlddataserver, ResourceKey<Level> resourcekey, LevelStem worlddimension, ChunkProgressListener worldloadlistener, boolean flag, long i, List<CustomSpawner> list, boolean flag1, @Nullable RandomSequences randomsequences, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) {
-@@ -385,14 +558,13 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -385,14 +564,13 @@ public class ServerLevel extends Level implements WorldGenLevel {
          DataFixer datafixer = minecraftserver.getFixerUpper();
          EntityPersistentStorage<Entity> entitypersistentstorage = new EntityStorage(new SimpleRegionStorage(new RegionStorageInfo(convertable_conversionsession.getLevelId(), resourcekey, "entities"), convertable_conversionsession.getDimensionPath(resourcekey).resolve("entities"), datafixer, flag2, DataFixTypes.ENTITY_CHUNK), this, minecraftserver);
  
@@ -26106,7 +26701,7 @@ index 4d7e234d379a451c4bb53bc2fcdf22cb191f8d1a..cf33e22ae85cd30b4f5d526dbfececca
              return minecraftserver.overworld().getDataStorage();
          });
          this.chunkSource.getGeneratorState().ensureStructuresGenerated();
-@@ -420,6 +592,19 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -420,6 +598,19 @@ public class ServerLevel extends Level implements WorldGenLevel {
          this.randomSequences = (RandomSequences) Objects.requireNonNullElseGet(randomsequences, () -> {
              return (RandomSequences) this.getDataStorage().computeIfAbsent(RandomSequences.factory(l), "random_sequences");
          });
@@ -26126,7 +26721,7 @@ index 4d7e234d379a451c4bb53bc2fcdf22cb191f8d1a..cf33e22ae85cd30b4f5d526dbfececca
          this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit
      }
  
-@@ -553,7 +738,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -553,7 +744,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
                          gameprofilerfiller.push("checkDespawn");
                          entity.checkDespawn();
                          gameprofilerfiller.pop();
@@ -26135,7 +26730,7 @@ index 4d7e234d379a451c4bb53bc2fcdf22cb191f8d1a..cf33e22ae85cd30b4f5d526dbfececca
                              Entity entity1 = entity.getVehicle();
  
                              if (entity1 != null) {
-@@ -578,13 +763,16 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -578,13 +769,16 @@ public class ServerLevel extends Level implements WorldGenLevel {
          }
  
          gameprofilerfiller.push("entityManagement");
@@ -26154,7 +26749,7 @@ index 4d7e234d379a451c4bb53bc2fcdf22cb191f8d1a..cf33e22ae85cd30b4f5d526dbfececca
      }
  
      protected void tickTime() {
-@@ -976,6 +1164,11 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -976,6 +1170,11 @@ public class ServerLevel extends Level implements WorldGenLevel {
          if (fluid1.is(fluid)) {
              fluid1.tick(this, pos);
          }
@@ -26166,7 +26761,7 @@ index 4d7e234d379a451c4bb53bc2fcdf22cb191f8d1a..cf33e22ae85cd30b4f5d526dbfececca
  
      }
  
-@@ -985,6 +1178,11 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -985,6 +1184,11 @@ public class ServerLevel extends Level implements WorldGenLevel {
          if (iblockdata.is(block)) {
              iblockdata.tick(this, pos, this.random);
          }
@@ -26178,7 +26773,7 @@ index 4d7e234d379a451c4bb53bc2fcdf22cb191f8d1a..cf33e22ae85cd30b4f5d526dbfececca
  
      }
  
-@@ -1061,6 +1259,11 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -1061,6 +1265,11 @@ public class ServerLevel extends Level implements WorldGenLevel {
      }
  
      public void save(@Nullable ProgressListener progressListener, boolean flush, boolean savingDisabled) {
@@ -26190,7 +26785,7 @@ index 4d7e234d379a451c4bb53bc2fcdf22cb191f8d1a..cf33e22ae85cd30b4f5d526dbfececca
          ServerChunkCache chunkproviderserver = this.getChunkSource();
  
          if (!savingDisabled) {
-@@ -1076,16 +1279,21 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -1076,16 +1285,21 @@ public class ServerLevel extends Level implements WorldGenLevel {
              }
  
                  timings.worldSaveChunks.startTiming(); // Paper
@@ -26218,7 +26813,7 @@ index 4d7e234d379a451c4bb53bc2fcdf22cb191f8d1a..cf33e22ae85cd30b4f5d526dbfececca
  
          // CraftBukkit start - moved from MinecraftServer.saveChunks
          ServerLevel worldserver1 = this;
-@@ -1218,7 +1426,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -1218,7 +1432,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
              this.removePlayerImmediately((ServerPlayer) entity, Entity.RemovalReason.DISCARDED);
          }
  
@@ -26227,7 +26822,7 @@ index 4d7e234d379a451c4bb53bc2fcdf22cb191f8d1a..cf33e22ae85cd30b4f5d526dbfececca
      }
  
      // CraftBukkit start
-@@ -1249,7 +1457,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -1249,7 +1463,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
              }
              // CraftBukkit end
  
@@ -26236,7 +26831,7 @@ index 4d7e234d379a451c4bb53bc2fcdf22cb191f8d1a..cf33e22ae85cd30b4f5d526dbfececca
          }
      }
  
-@@ -1260,11 +1468,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -1260,11 +1474,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
  
      public boolean tryAddFreshEntityWithPassengers(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) {
          // CraftBukkit end
@@ -26249,7 +26844,7 @@ index 4d7e234d379a451c4bb53bc2fcdf22cb191f8d1a..cf33e22ae85cd30b4f5d526dbfececca
              return false;
          } else {
              this.addFreshEntityWithPassengers(entity, reason); // CraftBukkit
-@@ -1850,7 +2054,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -1850,7 +2060,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
                  }
              }
  
@@ -26258,7 +26853,7 @@ index 4d7e234d379a451c4bb53bc2fcdf22cb191f8d1a..cf33e22ae85cd30b4f5d526dbfececca
              bufferedwriter.write(String.format(Locale.ROOT, "block_entity_tickers: %d\n", this.blockEntityTickers.size()));
              bufferedwriter.write(String.format(Locale.ROOT, "block_ticks: %d\n", this.getBlockTicks().count()));
              bufferedwriter.write(String.format(Locale.ROOT, "fluid_ticks: %d\n", this.getFluidTicks().count()));
-@@ -1899,7 +2103,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -1899,7 +2109,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
          BufferedWriter bufferedwriter2 = Files.newBufferedWriter(path1);
  
          try {
@@ -26267,7 +26862,7 @@ index 4d7e234d379a451c4bb53bc2fcdf22cb191f8d1a..cf33e22ae85cd30b4f5d526dbfececca
          } catch (Throwable throwable4) {
              if (bufferedwriter2 != null) {
                  try {
-@@ -1920,7 +2124,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -1920,7 +2130,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
          BufferedWriter bufferedwriter3 = Files.newBufferedWriter(path2);
  
          try {
@@ -26276,7 +26871,7 @@ index 4d7e234d379a451c4bb53bc2fcdf22cb191f8d1a..cf33e22ae85cd30b4f5d526dbfececca
          } catch (Throwable throwable6) {
              if (bufferedwriter3 != null) {
                  try {
-@@ -2062,7 +2266,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -2062,7 +2272,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
  
      @VisibleForTesting
      public String getWatchdogStats() {
@@ -26285,7 +26880,7 @@ index 4d7e234d379a451c4bb53bc2fcdf22cb191f8d1a..cf33e22ae85cd30b4f5d526dbfececca
              return BuiltInRegistries.ENTITY_TYPE.getKey(entity.getType()).toString();
          }), this.blockEntityTickers.size(), ServerLevel.getTypeCount(this.blockEntityTickers, TickingBlockEntity::getType), this.getBlockTicks().count(), this.getFluidTicks().count(), this.gatherChunkSourceStats());
      }
-@@ -2092,15 +2296,25 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -2092,15 +2302,25 @@ public class ServerLevel extends Level implements WorldGenLevel {
      @Override
      public LevelEntityGetter<Entity> getEntities() {
          org.spigotmc.AsyncCatcher.catchOp("Chunk getEntities call"); // Spigot
@@ -26314,7 +26909,7 @@ index 4d7e234d379a451c4bb53bc2fcdf22cb191f8d1a..cf33e22ae85cd30b4f5d526dbfececca
      }
  
      public void startTickingChunk(LevelChunk chunk) {
-@@ -2120,34 +2334,47 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -2120,34 +2340,47 @@ public class ServerLevel extends Level implements WorldGenLevel {
      @Override
      public void close() throws IOException {
          super.close();
@@ -26369,7 +26964,7 @@ index 4d7e234d379a451c4bb53bc2fcdf22cb191f8d1a..cf33e22ae85cd30b4f5d526dbfececca
      }
  
      @Override
-@@ -2173,7 +2400,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -2173,7 +2406,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
          CrashReportCategory crashreportsystemdetails = super.fillReportDetails(report);
  
          crashreportsystemdetails.setDetail("Loaded entity count", () -> {
@@ -26970,7 +27565,7 @@ index ea72dcb064a35bc6245bc5c94d592efedd8faf41..87ee8e51dfa7657ed7d83fcbceef48bf
          this.comparator = comparator;
          if (initialCapacity < 0) {
 diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
-index 2e2101274f3afebbae783fa119f5cae8104de45d..a7deceb2b9caad47f7f641ba4302d622d7127651 100644
+index 2e2101274f3afebbae783fa119f5cae8104de45d..690d3f669092f0a0a39a93a401c2e8a1626650b4 100644
 --- a/src/main/java/net/minecraft/world/entity/Entity.java
 +++ b/src/main/java/net/minecraft/world/entity/Entity.java
 @@ -167,7 +167,7 @@ import org.bukkit.event.player.PlayerTeleportEvent;
@@ -26978,11 +27573,11 @@ index 2e2101274f3afebbae783fa119f5cae8104de45d..a7deceb2b9caad47f7f641ba4302d622
  // CraftBukkit end
  
 -public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess, CommandSource, ScoreHolder {
-+public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess, CommandSource, ScoreHolder, ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity { // Paper - rewrite chunk system
++public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess, CommandSource, ScoreHolder, ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity, ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity { // Paper - rewrite chunk system // Paper - optimise entity tracker
  
      // CraftBukkit start
      private static final int CURRENT_LEVEL = 2;
-@@ -456,6 +456,77 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+@@ -456,6 +456,97 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
          return this.dimensions.makeBoundingBox(x, y, z);
      }
      // Paper end
@@ -27057,10 +27652,55 @@ index 2e2101274f3afebbae783fa119f5cae8104de45d..a7deceb2b9caad47f7f641ba4302d622
 +        return this.getIndirectPassengersStream().anyMatch((entity) -> entity instanceof Player);
 +    }
 +    // Paper end - rewrite chunk system
++    // Paper start - optimise entity tracker
++    private net.minecraft.server.level.ChunkMap.TrackedEntity trackedEntity;
++
++    @Override
++    public final net.minecraft.server.level.ChunkMap.TrackedEntity moonrise$getTrackedEntity() {
++        return this.trackedEntity;
++    }
++
++    @Override
++    public final void moonrise$setTrackedEntity(final net.minecraft.server.level.ChunkMap.TrackedEntity trackedEntity) {
++        this.trackedEntity = trackedEntity;
++    }
++
++    private static void collectIndirectPassengers(final List<Entity> into, final List<Entity> from) {
++        for (final Entity passenger : from) {
++            into.add(passenger);
++            collectIndirectPassengers(into, ((Entity)(Object)passenger).passengers);
++        }
++    }
++    // Paper end - optimise entity tracker
  
      public Entity(EntityType<?> type, Level world) {
          this.id = Entity.ENTITY_COUNTER.incrementAndGet();
-@@ -4397,6 +4468,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+@@ -4025,14 +4116,17 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+     }
+ 
+     public Iterable<Entity> getIndirectPassengers() {
+-        // Paper start - Optimize indirect passenger iteration
+-        if (this.passengers.isEmpty()) { return ImmutableList.of(); }
+-        ImmutableList.Builder<Entity> indirectPassengers = ImmutableList.builder();
+-        for (Entity passenger : this.passengers) {
+-            indirectPassengers.add(passenger);
+-            indirectPassengers.addAll(passenger.getIndirectPassengers());
++        // Paper start - optimise entity tracker
++        final List<Entity> ret = new ArrayList<>();
++
++        if (this.passengers.isEmpty()) {
++            return ret;
+         }
+-        return indirectPassengers.build();
++
++        collectIndirectPassengers(ret, this.passengers);
++
++        return ret;
++        // Paper end - optimise entity tracker
+     }
+     private Iterable<Entity> getIndirectPassengers_old() {
+         // Paper end - Optimize indirect passenger iteration
+@@ -4397,6 +4491,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
          this.setPosRaw(x, y, z, false);
      }
      public final void setPosRaw(double x, double y, double z, boolean forceBoundingBoxUpdate) {
@@ -27076,7 +27716,7 @@ index 2e2101274f3afebbae783fa119f5cae8104de45d..a7deceb2b9caad47f7f641ba4302d622
          if (!checkPosition(this, x, y, z)) {
              return;
          }
-@@ -4528,6 +4608,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+@@ -4528,6 +4631,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
  
      @Override
      public final void setRemoved(Entity.RemovalReason entity_removalreason, EntityRemoveEvent.Cause cause) {
@@ -27089,7 +27729,7 @@ index 2e2101274f3afebbae783fa119f5cae8104de45d..a7deceb2b9caad47f7f641ba4302d622
          CraftEventFactory.callEntityRemoveEvent(this, cause);
          // CraftBukkit end
          final boolean alreadyRemoved = this.removalReason != null; // Paper - Folia schedulers
-@@ -4539,7 +4625,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+@@ -4539,7 +4648,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
              this.stopRiding();
          }
  
@@ -27098,7 +27738,7 @@ index 2e2101274f3afebbae783fa119f5cae8104de45d..a7deceb2b9caad47f7f641ba4302d622
          this.levelCallback.onRemove(entity_removalreason);
          // Paper start - Folia schedulers
          if (!(this instanceof ServerPlayer) && entity_removalreason != RemovalReason.CHANGED_DIMENSION && !alreadyRemoved) {
-@@ -4570,7 +4656,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+@@ -4570,7 +4679,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
  
      @Override
      public boolean shouldBeSaved() {
diff --git a/patches/server/0993-disable-forced-empty-world-ticks.patch b/patches/server/0993-disable-forced-empty-world-ticks.patch
index 5dc524cb7c..aa80568a5a 100644
--- a/patches/server/0993-disable-forced-empty-world-ticks.patch
+++ b/patches/server/0993-disable-forced-empty-world-ticks.patch
@@ -5,10 +5,10 @@ Subject: [PATCH] disable forced empty world ticks
 
 
 diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
-index cf33e22ae85cd30b4f5d526dbfececca87d4ee40..db30381b3aeab83bcd0d1a341e4056d7c36a6f11 100644
+index e955bf0c9f76f6e90bd726342f204e999090fee1..e5c44d2b02848aca5dcfc86006ab688598244f16 100644
 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java
 +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
-@@ -713,7 +713,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
+@@ -719,7 +719,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
  
          this.handlingTick = false;
          gameprofilerfiller.pop();
diff --git a/patches/server/0995-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch b/patches/server/0995-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch
index cb921d96da..5fac9b6575 100644
--- a/patches/server/0995-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch
+++ b/patches/server/0995-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch
@@ -13,10 +13,10 @@ custom renderers are in use, defaulting to the much simpler Vanilla system.
 Additionally, numerous issues to player position tracking on maps has been fixed.
 
 diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
-index db30381b3aeab83bcd0d1a341e4056d7c36a6f11..fc011c30628d77d55defe421db6ac194217e8def 100644
+index e5c44d2b02848aca5dcfc86006ab688598244f16..eee9aa0d82c7446f3d32a9655abceb5279ea5226 100644
 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java
 +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
-@@ -2492,6 +2492,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
+@@ -2498,6 +2498,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
                              {
                                  if ( iter.next().player == entity )
                                  {
diff --git a/patches/server/1000-Entity-Activation-Range-2.0.patch b/patches/server/1000-Entity-Activation-Range-2.0.patch
index 154d3a86cd..ddcaef5bad 100644
--- a/patches/server/1000-Entity-Activation-Range-2.0.patch
+++ b/patches/server/1000-Entity-Activation-Range-2.0.patch
@@ -17,7 +17,7 @@ Adds villagers as separate config
 public net.minecraft.world.entity.Entity isInsidePortal
 
 diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
-index fc011c30628d77d55defe421db6ac194217e8def..975174a2f20e1597ffd2f9d840c77eec3c353b88 100644
+index eee9aa0d82c7446f3d32a9655abceb5279ea5226..a12864921a35a1fb3b6081d72e6505820a6c64f1 100644
 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java
 +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
 @@ -2,7 +2,6 @@ package net.minecraft.server.level;
@@ -28,7 +28,7 @@ index fc011c30628d77d55defe421db6ac194217e8def..975174a2f20e1597ffd2f9d840c77eec
  import com.google.common.collect.Lists;
  import com.mojang.datafixers.DataFixer;
  import com.mojang.datafixers.util.Pair;
-@@ -1190,17 +1189,17 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
+@@ -1196,17 +1195,17 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
          ++TimingHistory.entityTicks; // Paper - timings
          // Spigot start
          co.aikar.timings.Timing timer; // Paper
@@ -50,7 +50,7 @@ index fc011c30628d77d55defe421db6ac194217e8def..975174a2f20e1597ffd2f9d840c77eec
          try {
          // Paper end - timings
          entity.setOldPosAndRot();
-@@ -1211,9 +1210,13 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
+@@ -1217,9 +1216,13 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
              return BuiltInRegistries.ENTITY_TYPE.getKey(entity.getType()).toString();
          });
          gameprofilerfiller.incrementCounter("tickNonPassenger");
@@ -64,7 +64,7 @@ index fc011c30628d77d55defe421db6ac194217e8def..975174a2f20e1597ffd2f9d840c77eec
          Iterator iterator = entity.getPassengers().iterator();
  
          while (iterator.hasNext()) {
-@@ -1221,13 +1224,18 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
+@@ -1227,13 +1230,18 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
  
              this.tickPassenger(entity, entity1);
          }
@@ -84,7 +84,7 @@ index fc011c30628d77d55defe421db6ac194217e8def..975174a2f20e1597ffd2f9d840c77eec
                  passenger.setOldPosAndRot();
                  ++passenger.tickCount;
                  ProfilerFiller gameprofilerfiller = this.getProfiler();
-@@ -1236,8 +1244,17 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
+@@ -1242,8 +1250,17 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
                      return BuiltInRegistries.ENTITY_TYPE.getKey(passenger.getType()).toString();
                  });
                  gameprofilerfiller.incrementCounter("tickPassenger");
@@ -102,7 +102,7 @@ index fc011c30628d77d55defe421db6ac194217e8def..975174a2f20e1597ffd2f9d840c77eec
                  gameprofilerfiller.pop();
                  Iterator iterator = passenger.getPassengers().iterator();
  
-@@ -1247,6 +1264,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
+@@ -1253,6 +1270,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
                      this.tickPassenger(passenger, entity2);
                  }
  
@@ -111,7 +111,7 @@ index fc011c30628d77d55defe421db6ac194217e8def..975174a2f20e1597ffd2f9d840c77eec
          } else {
              passenger.stopRiding();
 diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
-index a7deceb2b9caad47f7f641ba4302d622d7127651..5d7bc6470ab3818b0a189aab18ff26c0180e3912 100644
+index 690d3f669092f0a0a39a93a401c2e8a1626650b4..ffee1fd60e863d1453796ee498fc5a3b13d26de8 100644
 --- a/src/main/java/net/minecraft/world/entity/Entity.java
 +++ b/src/main/java/net/minecraft/world/entity/Entity.java
 @@ -419,6 +419,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -123,7 +123,7 @@ index a7deceb2b9caad47f7f641ba4302d622d7127651..5d7bc6470ab3818b0a189aab18ff26c0
      public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one
      // Paper start - Entity origin API
      @javax.annotation.Nullable
-@@ -1039,6 +1041,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+@@ -1059,6 +1061,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
          } else {
              this.wasOnFire = this.isOnFire();
              if (movementType == MoverType.PISTON) {
@@ -132,7 +132,7 @@ index a7deceb2b9caad47f7f641ba4302d622d7127651..5d7bc6470ab3818b0a189aab18ff26c0
                  movement = this.limitPistonMovement(movement);
                  if (movement.equals(Vec3.ZERO)) {
                      return;
-@@ -1051,6 +1055,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+@@ -1071,6 +1075,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
                  this.stuckSpeedMultiplier = Vec3.ZERO;
                  this.setDeltaMovement(Vec3.ZERO);
              }
diff --git a/patches/server/1002-Anti-Xray.patch b/patches/server/1002-Anti-Xray.patch
index ab9a10b557..400053becc 100644
--- a/patches/server/1002-Anti-Xray.patch
+++ b/patches/server/1002-Anti-Xray.patch
@@ -1104,10 +1104,10 @@ index 183b2191fa1c1b27adedf39593e1b5a223fb1279..8ead66c134688b11dca15f6509147e72
  
      private ClientboundLevelChunkWithLightPacket(RegistryFriendlyByteBuf buf) {
 diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
-index 975174a2f20e1597ffd2f9d840c77eec3c353b88..8daa490817367391cac5c9852e0755b280fb9054 100644
+index a12864921a35a1fb3b6081d72e6505820a6c64f1..8a3f58e6dfdb0af767be334087748f93c06ec797 100644
 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java
 +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
-@@ -518,7 +518,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
+@@ -524,7 +524,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
          // Holder holder = worlddimension.type(); // CraftBukkit - decompile error
  
          // Objects.requireNonNull(minecraftserver); // CraftBukkit - decompile error
@@ -1561,7 +1561,7 @@ index 977bebe8657abc5cb84ede8276d6781cde20e847..6d461849da76894244e6212a75da0c6e
      // CraftBukkit end
  
 diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
-index cce2fed2d4e9d6147ea1854321012c6950eb05cc..2d5c88b80c983eb067ef366c3d9344826fbb0938 100644
+index 33322b57b4c6922f4daad0f584733f0f24083911..45e262308aebafa377a2353661acdd122933b99e 100644
 --- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
 +++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
 @@ -56,7 +56,7 @@ public class CraftChunk implements Chunk {
diff --git a/patches/server/1004-Add-Alternate-Current-redstone-implementation.patch b/patches/server/1004-Add-Alternate-Current-redstone-implementation.patch
index 261590166f..6554a372c9 100644
--- a/patches/server/1004-Add-Alternate-Current-redstone-implementation.patch
+++ b/patches/server/1004-Add-Alternate-Current-redstone-implementation.patch
@@ -2009,7 +2009,7 @@ index 0000000000000000000000000000000000000000..33cd90c30c22200a4e1ae64f40a0bf78
 +    }
 +}
 diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
-index 8daa490817367391cac5c9852e0755b280fb9054..2d97ca1f3c625c0206d35b785c57d9587924ed0a 100644
+index 8a3f58e6dfdb0af767be334087748f93c06ec797..7ba34da235ea536b929e1c8bc2cc39e48b33f5aa 100644
 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java
 +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
 @@ -228,6 +228,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
@@ -2020,7 +2020,7 @@ index 8daa490817367391cac5c9852e0755b280fb9054..2d97ca1f3c625c0206d35b785c57d958
  
      public LevelChunk getChunkIfLoaded(int x, int z) {
          return this.chunkSource.getChunkAtIfLoadedImmediately(x, z); // Paper - Use getChunkIfLoadedImmediately
-@@ -2423,6 +2424,13 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
+@@ -2429,6 +2430,13 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
          return crashreportsystemdetails;
      }
  
diff --git a/patches/server/1018-API-for-checking-sent-chunks.patch b/patches/server/1018-API-for-checking-sent-chunks.patch
index 137772f487..5129c9a08a 100644
--- a/patches/server/1018-API-for-checking-sent-chunks.patch
+++ b/patches/server/1018-API-for-checking-sent-chunks.patch
@@ -5,10 +5,10 @@ Subject: [PATCH] API for checking sent chunks
 
 
 diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
-index 82e8ce73b77accd6a4210f88c9fccb325ae367d4..91c4219b2abf1b5be3dc35f7b8403884e1d36f8d 100644
+index f063ab3ff122b920bcc4aa4f5bf9a442a8eb32fd..95d2d4417591b921d1ddf73025565cff6aabddd7 100644
 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
 +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
-@@ -1070,5 +1070,10 @@ public final class RegionizedPlayerChunkLoader {
+@@ -1072,5 +1072,10 @@ public final class RegionizedPlayerChunkLoader {
  
              // now all tickets should be removed, which is all of our external state
          }
diff --git a/patches/server/1023-Properly-resend-entities.patch b/patches/server/1023-Properly-resend-entities.patch
index 49917da8c7..02512d7402 100644
--- a/patches/server/1023-Properly-resend-entities.patch
+++ b/patches/server/1023-Properly-resend-entities.patch
@@ -115,10 +115,10 @@ index 1aa8b914e79c0d48094cc22df60ee9750ec3ccd6..369b3485f452ac157b3ebf88b4f19706
          this.sendLevelInfo(player, worldserver1);
  
 diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
-index f1fb4e830c6720d09b22056e3d0b9a08fe2bd472..83f3ffdd8fa901b3de580d2359cdb5ead0d762cb 100644
+index d8a90d7c77536abac6fa5f505338b1b53ef986af..593f371c383d4310f4e8ed81200126b05f585ee6 100644
 --- a/src/main/java/net/minecraft/world/entity/Entity.java
 +++ b/src/main/java/net/minecraft/world/entity/Entity.java
-@@ -665,13 +665,44 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+@@ -685,13 +685,44 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
  
      // CraftBukkit start
      public void refreshEntityData(ServerPlayer to) {
@@ -166,7 +166,7 @@ index f1fb4e830c6720d09b22056e3d0b9a08fe2bd472..83f3ffdd8fa901b3de580d2359cdb5ea
      public boolean equals(Object object) {
          return object instanceof Entity ? ((Entity) object).id == this.id : false;
 diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
-index 6e5af47f5d2775c1afc4914342c3d0ea6569c792..c5ca9fa86b940c6b5a54b05ff1bb3d0a300d60b2 100644
+index c49f71ac5470e7b823af8339e5583e654bc907a0..945da6b82653f05625f054d64bbf605a4ec1cd05 100644
 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
 +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
 @@ -3879,6 +3879,11 @@ public abstract class LivingEntity extends Entity implements Attackable {
diff --git a/patches/server/1024-Optimise-random-block-ticking.patch b/patches/server/1024-Optimise-random-block-ticking.patch
index 774d250ea6..8f81d5dd83 100644
--- a/patches/server/1024-Optimise-random-block-ticking.patch
+++ b/patches/server/1024-Optimise-random-block-ticking.patch
@@ -90,10 +90,10 @@ index 0000000000000000000000000000000000000000..7d93652c1abbb6aee6eb7c26cf35d4d0
 +    }
 +}
 diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
-index 2d97ca1f3c625c0206d35b785c57d9587924ed0a..e079f4db4e4738f60a6fdbdbf5e4d1baf593a62f 100644
+index 7ba34da235ea536b929e1c8bc2cc39e48b33f5aa..2a752deb8cc44b49588be37198fe394a9c95683e 100644
 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java
 +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
-@@ -813,6 +813,10 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
+@@ -819,6 +819,10 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
              entityplayer.stopSleepInBed(false, false);
          });
      }
@@ -104,7 +104,7 @@ index 2d97ca1f3c625c0206d35b785c57d9587924ed0a..e079f4db4e4738f60a6fdbdbf5e4d1ba
  
      public void tickChunk(LevelChunk chunk, int randomTickSpeed) {
          ChunkPos chunkcoordintpair = chunk.getPos();
-@@ -822,8 +826,10 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
+@@ -828,8 +832,10 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
          ProfilerFiller gameprofilerfiller = this.getProfiler();
  
          gameprofilerfiller.push("thunder");
@@ -116,7 +116,7 @@ index 2d97ca1f3c625c0206d35b785c57d9587924ed0a..e079f4db4e4738f60a6fdbdbf5e4d1ba
  
              if (this.isRainingAt(blockposition)) {
                  DifficultyInstance difficultydamagescaler = this.getCurrentDifficultyAt(blockposition);
-@@ -855,7 +861,10 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
+@@ -861,7 +867,10 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
          if (!this.paperConfig().environment.disableIceAndSnow) { // Paper - Option to disable ice and snow
          for (int l = 0; l < randomTickSpeed; ++l) {
              if (this.random.nextInt(48) == 0) {
@@ -128,7 +128,7 @@ index 2d97ca1f3c625c0206d35b785c57d9587924ed0a..e079f4db4e4738f60a6fdbdbf5e4d1ba
              }
          }
          } // Paper - Option to disable ice and snow
-@@ -863,36 +872,37 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
+@@ -869,36 +878,37 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
          gameprofilerfiller.popPush("tickBlocks");
          timings.chunkTicksBlocks.startTiming(); // Paper
          if (randomTickSpeed > 0) {
@@ -190,7 +190,7 @@ index 2d97ca1f3c625c0206d35b785c57d9587924ed0a..e079f4db4e4738f60a6fdbdbf5e4d1ba
  
          timings.chunkTicksBlocks.stopTiming(); // Paper
          gameprofilerfiller.pop();
-@@ -900,17 +910,25 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
+@@ -906,17 +916,25 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
  
      @VisibleForTesting
      public void tickPrecipitation(BlockPos pos) {
@@ -220,7 +220,7 @@ index 2d97ca1f3c625c0206d35b785c57d9587924ed0a..e079f4db4e4738f60a6fdbdbf5e4d1ba
              if (i > 0 && biomebase.shouldSnow(this, blockposition1)) {
                  BlockState iblockdata = this.getBlockState(blockposition1);
  
-@@ -928,12 +946,13 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
+@@ -934,12 +952,13 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
                  }
              }
  
diff --git a/patches/server/1037-Fix-entity-tracker-desync-when-new-players-are-added.patch b/patches/server/1037-Fix-entity-tracker-desync-when-new-players-are-added.patch
index 576b74c10c..294794eaea 100644
--- a/patches/server/1037-Fix-entity-tracker-desync-when-new-players-are-added.patch
+++ b/patches/server/1037-Fix-entity-tracker-desync-when-new-players-are-added.patch
@@ -48,10 +48,10 @@ index 1a5e73fd97781f3903e5ef13aa0352c64fbc2cc1..4126d82e83810126eb4a41b4587dc993
              entityTrackerEntry.getLastSentYRot(),
              entity.getType(),
 diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
-index c96740a82eac9101f74edeb44edf4b64d1d633e0..8b6754525fafd1aaac3292cf69a855d6a42b9523 100644
+index 344966d3deb640eb99bc9c9e318e6e6780421907..6df79aab2f0a75bbe347dc92e9ed5d62ceec7983 100644
 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java
 +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
-@@ -1189,6 +1189,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -1302,6 +1302,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
                          this.serverEntity.addPairing(player);
                          }
                          // Paper end - entity tracking events