diff --git a/patches/unapplied/api/Add-ThrownEggHatchEvent.patch b/patches/api/Add-ThrownEggHatchEvent.patch
similarity index 100%
rename from patches/unapplied/api/Add-ThrownEggHatchEvent.patch
rename to patches/api/Add-ThrownEggHatchEvent.patch
diff --git a/patches/unapplied/api/Entity-Jump-API.patch b/patches/api/Entity-Jump-API.patch
similarity index 100%
rename from patches/unapplied/api/Entity-Jump-API.patch
rename to patches/api/Entity-Jump-API.patch
diff --git a/patches/unapplied/api/add-hand-to-BlockMultiPlaceEvent.patch b/patches/api/add-hand-to-BlockMultiPlaceEvent.patch
similarity index 100%
rename from patches/unapplied/api/add-hand-to-BlockMultiPlaceEvent.patch
rename to patches/api/add-hand-to-BlockMultiPlaceEvent.patch
diff --git a/patches/unapplied/server/Add-ThrownEggHatchEvent.patch b/patches/server/Add-ThrownEggHatchEvent.patch
similarity index 100%
rename from patches/unapplied/server/Add-ThrownEggHatchEvent.patch
rename to patches/server/Add-ThrownEggHatchEvent.patch
diff --git a/patches/unapplied/server/Add-debug-for-sync-chunk-loads.patch b/patches/server/Add-debug-for-sync-chunk-loads.patch
similarity index 99%
rename from patches/unapplied/server/Add-debug-for-sync-chunk-loads.patch
rename to patches/server/Add-debug-for-sync-chunk-loads.patch
index 167d2a9e50..3c3ff8ee17 100644
--- a/patches/unapplied/server/Add-debug-for-sync-chunk-loads.patch
+++ b/patches/server/Add-debug-for-sync-chunk-loads.patch
@@ -314,7 +314,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                  // Paper end
 +                com.destroystokyo.paper.io.SyncLoadFinder.logSyncLoad(this.level, x1, z1); // Paper - sync load info
                  this.level.timings.syncChunkLoad.startTiming(); // Paper
-             chunkproviderserver_a.managedBlock(completablefuture::isDone);
+             chunkproviderserver_b.managedBlock(completablefuture::isDone);
                  com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug
 diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
diff --git a/patches/unapplied/server/Add-option-to-allow-iron-golems-to-spawn-in-air.patch b/patches/server/Add-option-to-allow-iron-golems-to-spawn-in-air.patch
similarity index 88%
rename from patches/unapplied/server/Add-option-to-allow-iron-golems-to-spawn-in-air.patch
rename to patches/server/Add-option-to-allow-iron-golems-to-spawn-in-air.patch
index b0277b9302..202843529c 100644
--- a/patches/unapplied/server/Add-option-to-allow-iron-golems-to-spawn-in-air.patch
+++ b/patches/server/Add-option-to-allow-iron-golems-to-spawn-in-air.patch
@@ -28,8 +28,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          BlockPos blockposition1 = blockposition.below();
          BlockState iblockdata = world.getBlockState(blockposition1);
  
--        if (!iblockdata.entityCanStandOn((BlockGetter) world, blockposition1, (Entity) this)) {
-+        if (!iblockdata.entityCanStandOn((BlockGetter) world, blockposition1, (Entity) this) && !level.paperConfig.ironGolemsCanSpawnInAir) { // Paper
+-        if (!iblockdata.entityCanStandOn(world, blockposition1, this)) {
++        if (!iblockdata.entityCanStandOn(world, blockposition1, this) && !level.paperConfig.ironGolemsCanSpawnInAir) { // Paper
              return false;
          } else {
              for (int i = 1; i < 3; ++i) {
diff --git a/patches/unapplied/server/Add-option-to-nerf-pigmen-from-nether-portals.patch b/patches/server/Add-option-to-nerf-pigmen-from-nether-portals.patch
similarity index 97%
rename from patches/unapplied/server/Add-option-to-nerf-pigmen-from-nether-portals.patch
rename to patches/server/Add-option-to-nerf-pigmen-from-nether-portals.patch
index 43be7ed3ae..84eff3e3ca 100644
--- a/patches/unapplied/server/Add-option-to-nerf-pigmen-from-nether-portals.patch
+++ b/patches/server/Add-option-to-nerf-pigmen-from-nether-portals.patch
@@ -24,7 +24,7 @@ diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/jav
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/world/entity/Entity.java
 +++ b/src/main/java/net/minecraft/world/entity/Entity.java
-@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
+@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, i
      public long activatedImmunityTick = Integer.MIN_VALUE; // Paper
      public boolean isTemporarilyActive = false; // Paper
      public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one
@@ -32,7 +32,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      protected int numCollisions = 0; // Paper
      public void inactiveTick() { }
      // Spigot end
-@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
+@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, i
              if (spawnedViaMobSpawner) {
                  nbt.putBoolean("Paper.FromMobSpawner", true);
              }
@@ -42,7 +42,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
              // Paper end
              return nbt;
          } catch (Throwable throwable) {
-@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
+@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, i
              }
  
              spawnedViaMobSpawner = nbt.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status
diff --git a/patches/unapplied/server/Allow-overriding-the-java-version-check.patch b/patches/server/Allow-overriding-the-java-version-check.patch
similarity index 100%
rename from patches/unapplied/server/Allow-overriding-the-java-version-check.patch
rename to patches/server/Allow-overriding-the-java-version-check.patch
diff --git a/patches/unapplied/server/Avoid-hopper-searches-if-there-are-no-items.patch b/patches/server/Avoid-hopper-searches-if-there-are-no-items.patch
similarity index 76%
rename from patches/unapplied/server/Avoid-hopper-searches-if-there-are-no-items.patch
rename to patches/server/Avoid-hopper-searches-if-there-are-no-items.patch
index f6733c95da..70f08e5db0 100644
--- a/patches/unapplied/server/Avoid-hopper-searches-if-there-are-no-items.patch
+++ b/patches/server/Avoid-hopper-searches-if-there-are-no-items.patch
@@ -30,7 +30,7 @@ diff --git a/src/main/java/net/minecraft/world/level/entity/EntitySection.java b
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/world/level/entity/EntitySection.java
 +++ b/src/main/java/net/minecraft/world/level/entity/EntitySection.java
-@@ -0,0 +0,0 @@ public class EntitySection<T> {
+@@ -0,0 +0,0 @@ public class EntitySection<T extends EntityAccess> {
      protected static final Logger LOGGER = LogManager.getLogger();
      private final ClassInstanceMultiMap<T> storage;
      private Visibility chunkStatus;
@@ -41,53 +41,44 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
      public EntitySection(Class<T> entityClass, Visibility status) {
          this.chunkStatus = status;
-@@ -0,0 +0,0 @@ public class EntitySection<T> {
+@@ -0,0 +0,0 @@ public class EntitySection<T extends EntityAccess> {
      }
  
-     public void add(T obj) {
+     public void add(T entityAccess) {
 +        // Paper start
-+        if (obj instanceof net.minecraft.world.entity.item.ItemEntity) {
++        if (entityAccess instanceof net.minecraft.world.entity.item.ItemEntity) {
 +            this.itemCount++;
-+        } else if (obj instanceof net.minecraft.world.Container) {
++        } else if (entityAccess instanceof net.minecraft.world.Container) {
 +            this.inventoryEntityCount++;
 +        }
 +        // Paper end
-         this.storage.add(obj);
+         this.storage.add(entityAccess);
      }
  
-     public boolean remove(T obj) {
+     public boolean remove(T entityAccess) {
 +        // Paper start
-+        if (obj instanceof net.minecraft.world.entity.item.ItemEntity) {
++        if (entityAccess instanceof net.minecraft.world.entity.item.ItemEntity) {
 +            this.itemCount--;
-+        } else if (obj instanceof net.minecraft.world.Container) {
++        } else if (entityAccess instanceof net.minecraft.world.Container) {
 +            this.inventoryEntityCount--;
 +        }
 +        // Paper end
-         return this.storage.remove(obj);
+         return this.storage.remove(entityAccess);
      }
  
-@@ -0,0 +0,0 @@ public class EntitySection<T> {
-         for(T object : this.storage.find(type.getBaseClass())) {
-             U object2 = (U)type.tryCast(object);
-             if (object2 != null && filter.test(object2)) {
--                action.accept((T)object2);
-+                action.accept(object2); // Paper - decompile fix
+@@ -0,0 +0,0 @@ public class EntitySection<T extends EntityAccess> {
+             for(T entityAccess : collection) {
+                 U entityAccess2 = (U)((EntityAccess)type.tryCast(entityAccess));
+                 if (entityAccess2 != null && entityAccess.getBoundingBox().intersects(aABB)) {
+-                    action.accept((T)entityAccess2);
++                    action.accept(entityAccess2); // Paper - decompile fixes
+                 }
              }
-         }
  
 diff --git a/src/main/java/net/minecraft/world/level/entity/EntitySectionStorage.java b/src/main/java/net/minecraft/world/level/entity/EntitySectionStorage.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/world/level/entity/EntitySectionStorage.java
 +++ b/src/main/java/net/minecraft/world/level/entity/EntitySectionStorage.java
-@@ -0,0 +0,0 @@ public class EntitySectionStorage<T extends EntityAccess> {
- 
-     public LongSet getAllChunksWithExistingSections() {
-         LongSet longSet = new LongOpenHashSet();
--        this.sections.keySet().forEach((sectionPos) -> {
-+        this.sections.keySet().forEach((java.util.function.LongConsumer) (sectionPos) -> { // Paper - decompile fix
-             longSet.add(getChunkKeyFromSectionKey(sectionPos));
-         });
-         return longSet;
 @@ -0,0 +0,0 @@ public class EntitySectionStorage<T extends EntityAccess> {
      }
  
@@ -97,16 +88,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    }
 +    public void getEntities(AABB box, Consumer<T> action, boolean isContainerSearch) {
 +        // Paper end
-         this.forEachAccessibleSection(box, (entitySection) -> {
+         this.forEachAccessibleNonEmptySection(box, (entitySection) -> {
 +            if (isContainerSearch && entitySection.inventoryEntityCount <= 0) return; // Paper
-             entitySection.getEntities(createBoundingBoxCheck(box), action);
+             entitySection.getEntities(box, action);
          });
      }
  
      public <U extends T> void getEntities(EntityTypeTest<T, U> filter, AABB box, Consumer<U> action) {
-         this.forEachAccessibleSection(box, (entitySection) -> {
+         this.forEachAccessibleNonEmptySection(box, (entitySection) -> {
 +            if (filter.getBaseClass() == net.minecraft.world.entity.item.ItemEntity.class && entitySection.itemCount <= 0) return; // Paper
-             entitySection.getEntities(filter, createBoundingBoxCheck(box), action);
+             entitySection.getEntities(filter, box, action);
          });
      }
 diff --git a/src/main/java/net/minecraft/world/level/entity/LevelEntityGetter.java b/src/main/java/net/minecraft/world/level/entity/LevelEntityGetter.java
diff --git a/patches/unapplied/server/Bees-get-gravity-in-void.-Fixes-MC-167279.patch b/patches/server/Bees-get-gravity-in-void.-Fixes-MC-167279.patch
similarity index 100%
rename from patches/unapplied/server/Bees-get-gravity-in-void.-Fixes-MC-167279.patch
rename to patches/server/Bees-get-gravity-in-void.-Fixes-MC-167279.patch
diff --git a/patches/unapplied/server/Configurable-chance-of-villager-zombie-infection.patch b/patches/server/Configurable-chance-of-villager-zombie-infection.patch
similarity index 100%
rename from patches/unapplied/server/Configurable-chance-of-villager-zombie-infection.patch
rename to patches/server/Configurable-chance-of-villager-zombie-infection.patch
diff --git a/patches/unapplied/server/Entity-Jump-API.patch b/patches/server/Entity-Jump-API.patch
similarity index 98%
rename from patches/unapplied/server/Entity-Jump-API.patch
rename to patches/server/Entity-Jump-API.patch
index 627a6f2289..c6afefff57 100644
--- a/patches/unapplied/server/Entity-Jump-API.patch
+++ b/patches/server/Entity-Jump-API.patch
@@ -10,7 +10,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
 @@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity {
              } else if (this.isInLava() && (!this.onGround || d7 > d8)) {
-                 this.jumpInLiquid((Tag) FluidTags.LAVA);
+                 this.jumpInLiquid(FluidTags.LAVA);
              } else if ((this.onGround || flag && d7 <= d8) && this.noJumpDelay == 0) {
 +                if (new com.destroystokyo.paper.event.entity.EntityJumpEvent(getBukkitLivingEntity()).callEvent()) { // Paper
                  this.jumpFromGround();
diff --git a/patches/unapplied/server/Fix-items-vanishing-through-end-portal.patch b/patches/server/Fix-items-vanishing-through-end-portal.patch
similarity index 97%
rename from patches/unapplied/server/Fix-items-vanishing-through-end-portal.patch
rename to patches/server/Fix-items-vanishing-through-end-portal.patch
index b9846d0dd7..d034930f5b 100644
--- a/patches/unapplied/server/Fix-items-vanishing-through-end-portal.patch
+++ b/patches/server/Fix-items-vanishing-through-end-portal.patch
@@ -16,7 +16,7 @@ diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/jav
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/world/entity/Entity.java
 +++ b/src/main/java/net/minecraft/world/entity/Entity.java
-@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
+@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, i
              BlockPos blockposition1;
  
              if (flag1) {
diff --git a/patches/unapplied/server/Implement-alternative-item-despawn-rate.patch b/patches/server/Implement-alternative-item-despawn-rate.patch
similarity index 96%
rename from patches/unapplied/server/Implement-alternative-item-despawn-rate.patch
rename to patches/server/Implement-alternative-item-despawn-rate.patch
index d5867037b3..9263fd299f 100644
--- a/patches/unapplied/server/Implement-alternative-item-despawn-rate.patch
+++ b/patches/server/Implement-alternative-item-despawn-rate.patch
@@ -9,8 +9,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
 +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
 @@ -0,0 +0,0 @@ public class PaperWorldConfig {
-         this.noTickViewDistance = this.getInt("viewdistances.no-tick-view-distance", -1);
+     private void lightQueueSize() {
+         lightQueueSize = getInt("light-queue-size", lightQueueSize);
      }
+-}
  
 +    public boolean altItemDespawnRateEnabled;
 +    public java.util.Map<org.bukkit.Material, Integer> altItemDespawnRateMap;
@@ -59,10 +61,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +            }
 +        }
 +    }
-+
-     public boolean antiXray;
-     public EngineMode engineMode;
-     public int maxBlockHeight;
++}
 diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
diff --git a/patches/unapplied/server/Make-the-GUI-graph-fancier.patch b/patches/server/Make-the-GUI-graph-fancier.patch
similarity index 100%
rename from patches/unapplied/server/Make-the-GUI-graph-fancier.patch
rename to patches/server/Make-the-GUI-graph-fancier.patch
diff --git a/patches/unapplied/server/Optimise-Chunk-getFluid.patch b/patches/server/Optimise-Chunk-getFluid.patch
similarity index 89%
rename from patches/unapplied/server/Optimise-Chunk-getFluid.patch
rename to patches/server/Optimise-Chunk-getFluid.patch
index 6e3f02463f..9d3540074b 100644
--- a/patches/unapplied/server/Optimise-Chunk-getFluid.patch
+++ b/patches/server/Optimise-Chunk-getFluid.patch
@@ -11,7 +11,7 @@ diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
 +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
-@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess {
+@@ -0,0 +0,0 @@ public class LevelChunk extends ChunkAccess {
      }
  
      public FluidState getFluidState(int x, int y, int z) {
@@ -20,19 +20,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -
 -            if (l >= 0 && l < this.sections.length) {
 -                LevelChunkSection chunksection = this.sections[l];
--
--                if (!LevelChunkSection.isEmpty(chunksection)) {
--                    return chunksection.getFluidState(x & 15, y & 15, z & 15);
 +        // try {  // Paper - remove try catch
 +        // Paper start - reduce the number of ops in this call
 +        int index = this.getSectionIndex(y);
 +            if (index >= 0 && index < this.sections.length) {
 +                LevelChunkSection chunksection = this.sections[index];
-+
-+                if (chunksection != null) {
+ 
+                 if (!chunksection.hasOnlyAir()) {
+-                    return chunksection.getFluidState(x & 15, y & 15, z & 15);
 +                    return chunksection.states.get((y & 15) << 8 | (z & 15) << 4 | x & 15).getFluidState();
++                    // Paper end
                  }
-+                // Paper end
              }
  
              return Fluids.EMPTY.defaultFluidState();
@@ -40,7 +38,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          } catch (Throwable throwable) {
              CrashReport crashreport = CrashReport.forThrowable(throwable, "Getting fluid state");
              CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block being got");
-@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess {
+@@ -0,0 +0,0 @@ public class LevelChunk extends ChunkAccess {
              });
              throw new ReportedException(crashreport);
          }
@@ -56,7 +54,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      }
  
      public FluidState getFluidState(int x, int y, int z) {
--        return this.states.get(x, y, z).getFluidState();
+-        return ((BlockState) this.states.get(x, y, z)).getFluidState();
 +        return this.states.get(x, y, z).getFluidState(); // Paper - diff on change - we expect this to be effectively just getType(x, y, z).getFluid(). If this changes we need to check other patches that use IBlockData#getFluid.
      }
  
diff --git a/patches/unapplied/server/Optimise-getChunkAt-calls-for-loaded-chunks.patch b/patches/server/Optimise-getChunkAt-calls-for-loaded-chunks.patch
similarity index 100%
rename from patches/unapplied/server/Optimise-getChunkAt-calls-for-loaded-chunks.patch
rename to patches/server/Optimise-getChunkAt-calls-for-loaded-chunks.patch
diff --git a/patches/unapplied/server/Prevent-teleporting-dead-entities.patch b/patches/server/Prevent-teleporting-dead-entities.patch
similarity index 100%
rename from patches/unapplied/server/Prevent-teleporting-dead-entities.patch
rename to patches/server/Prevent-teleporting-dead-entities.patch
diff --git a/patches/unapplied/server/Tracking-Range-Improvements.patch b/patches/server/Tracking-Range-Improvements.patch
similarity index 95%
rename from patches/unapplied/server/Tracking-Range-Improvements.patch
rename to patches/server/Tracking-Range-Improvements.patch
index 55d5e8e25b..51d846e7bb 100644
--- a/patches/unapplied/server/Tracking-Range-Improvements.patch
+++ b/patches/server/Tracking-Range-Improvements.patch
@@ -11,7 +11,7 @@ diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/j
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java
 +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
-@@ -0,0 +0,0 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
+@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
              while (iterator.hasNext()) {
                  Entity entity = (Entity) iterator.next();
                  int j = entity.getType().clientTrackingRange() * 16;
@@ -69,7 +69,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
              return config.miscTrackingRange;
          } else
          {
-+            if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon) return ((net.minecraft.server.level.ServerLevel)(entity.getCommandSenderWorld())).getChunkSource().chunkMap.getLoadViewDistance(); // Paper - enderdragon is exempt
++            if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon) return ((net.minecraft.server.level.ServerLevel)(entity.getCommandSenderWorld())).getChunkSource().chunkMap.getEffectiveViewDistance(); // Paper - enderdragon is exempt
              return config.otherTrackingRange;
          }
      }
diff --git a/patches/unapplied/server/Validate-tripwire-hook-placement-before-update.patch b/patches/server/Validate-tripwire-hook-placement-before-update.patch
similarity index 100%
rename from patches/unapplied/server/Validate-tripwire-hook-placement-before-update.patch
rename to patches/server/Validate-tripwire-hook-placement-before-update.patch
diff --git a/patches/unapplied/server/add-hand-to-BlockMultiPlaceEvent.patch b/patches/server/add-hand-to-BlockMultiPlaceEvent.patch
similarity index 100%
rename from patches/unapplied/server/add-hand-to-BlockMultiPlaceEvent.patch
rename to patches/server/add-hand-to-BlockMultiPlaceEvent.patch
diff --git a/patches/unapplied/server/implement-optional-per-player-mob-spawns.patch b/patches/server/implement-optional-per-player-mob-spawns.patch
similarity index 95%
rename from patches/unapplied/server/implement-optional-per-player-mob-spawns.patch
rename to patches/server/implement-optional-per-player-mob-spawns.patch
index 9420abfb21..6908a45ea8 100644
--- a/patches/unapplied/server/implement-optional-per-player-mob-spawns.patch
+++ b/patches/server/implement-optional-per-player-mob-spawns.patch
@@ -29,7 +29,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
 +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
 @@ -0,0 +0,0 @@ public class PaperWorldConfig {
-             Bukkit.getLogger().warning("You have enabled permission-based Anti-Xray checking - depending on your permission plugin, this may cause performance issues");
+             }
          }
      }
 +
@@ -41,7 +41,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        perPlayerMobSpawns = getBoolean("per-player-mob-spawns", true);
 +    }
  }
- 
 diff --git a/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java b/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java
 new file mode 100644
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
@@ -560,12 +559,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback()
      public final CallbackExecutor callbackExecutor = new CallbackExecutor();
 @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
-                 ChunkMap.this.updateChunkTracking(player, new ChunkPos(rangeX, rangeZ), null, true, false); // unloaded, loaded
-             });
-         // Paper end - no-tick view distance
+         this.dataRegionManager = new io.papermc.paper.chunk.SingleThreadChunkRegionManager(this.level, 2, (1.0 / 3.0), 1, 6, "Data", DataRegionData::new, DataRegionSectionData::new);
+         this.regionManagers.add(this.dataRegionManager);
+         // Paper end
 +        this.playerMobDistanceMap = this.level.paperConfig.perPlayerMobSpawns ? new com.destroystokyo.paper.util.PlayerMobDistanceMap() : null; // Paper
      }
  
+     protected ChunkGenerator generator() {
+@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+         });
+     }
+ 
 +    // Paper start
 +    public void updatePlayerMobTypeMap(Entity entity) {
 +        if (!this.level.paperConfig.perPlayerMobSpawns) {
@@ -593,10 +597,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
 +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
 @@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource {
-             this.level.getProfiler().push("naturalSpawnCount");
+             gameprofilerfiller.push("naturalSpawnCount");
              this.level.timings.countNaturalMobs.startTiming(); // Paper - timings
              int l = this.distanceManager.getNaturalSpawnChunkCount();
--            NaturalSpawner.SpawnState spawnercreature_d = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk);
+-            NaturalSpawner.SpawnState spawnercreature_d = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk, new LocalMobCapCalculator(this.chunkMap));
 +            // Paper start - per player mob spawning
 +            NaturalSpawner.SpawnState spawnercreature_d; // moved down
 +            if (this.chunkMap.playerMobDistanceMap != null) {
@@ -608,9 +612,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                for (ServerPlayer player : this.level.players) {
 +                    Arrays.fill(player.mobCounts, 0);
 +                }
-+                spawnercreature_d = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk, true);
++                spawnercreature_d = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk, new LocalMobCapCalculator(this.chunkMap), true);
 +            } else {
-+                spawnercreature_d = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk, false);
++                spawnercreature_d = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk, new LocalMobCapCalculator(this.chunkMap), false);
 +            }
 +            // Paper end
              this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings
@@ -644,24 +648,17 @@ diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/m
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java
 +++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
-@@ -0,0 +0,0 @@ import net.minecraft.core.Registry;
- import net.minecraft.core.SectionPos;
- import net.minecraft.nbt.CompoundTag;
- import net.minecraft.server.level.ServerLevel;
-+import net.minecraft.server.level.ServerPlayer;
- import net.minecraft.tags.BlockTags;
- import net.minecraft.tags.FluidTags;
- import net.minecraft.tags.Tag;
 @@ -0,0 +0,0 @@ public final class NaturalSpawner {
  
      private NaturalSpawner() {}
  
 +    // Paper start - add countMobs parameter
-     public static NaturalSpawner.SpawnState createState(int spawningChunkCount, Iterable<Entity> entities, NaturalSpawner.ChunkGetter chunkSource) {
-+        return createState(spawningChunkCount, entities, chunkSource, false);
+     public static NaturalSpawner.SpawnState createState(int spawningChunkCount, Iterable<Entity> entities, NaturalSpawner.ChunkGetter chunkSource, LocalMobCapCalculator localmobcapcalculator) {
++        return createState(spawningChunkCount, entities, chunkSource, localmobcapcalculator, false);
 +    }
-+    public static NaturalSpawner.SpawnState createState(int spawningChunkCount, Iterable<Entity> entities, NaturalSpawner.ChunkGetter chunkSource, boolean countMobs) {
-+    // Paper end - add countMobs parameter
++
++    public static NaturalSpawner.SpawnState createState(int spawningChunkCount, Iterable<Entity> entities, NaturalSpawner.ChunkGetter chunkSource, LocalMobCapCalculator localmobcapcalculator, boolean countMobs) {
++        // Paper end
          PotentialCalculator spawnercreatureprobabilities = new PotentialCalculator();
          Object2IntOpenHashMap<MobCategory> object2intopenhashmap = new Object2IntOpenHashMap();
          Iterator iterator = entities.iterator();
@@ -669,11 +666,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                      }
  
                      object2intopenhashmap.addTo(enumcreaturetype, 1);
-+                    // Paper start
 +                    if (countMobs) {
 +                        chunk.level.getChunkSource().chunkMap.updatePlayerMobTypeMap(entity);
 +                    }
-+                    // Paper end
                  });
              }
          }
@@ -681,7 +676,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                  continue;
              }
  
--            if ((spawnAnimals || !enumcreaturetype.isFriendly()) && (spawnMonsters || enumcreaturetype.isFriendly()) && (rareSpawn || !enumcreaturetype.isPersistent()) && info.canSpawnForCategory(enumcreaturetype, limit)) {
+-            if ((spawnAnimals || !enumcreaturetype.isFriendly()) && (spawnMonsters || enumcreaturetype.isFriendly()) && (rareSpawn || !enumcreaturetype.isPersistent()) && info.canSpawnForCategory(enumcreaturetype, chunk.getPos(), limit)) {
 +            // Paper start - only allow spawns upto the limit per chunk and update count afterwards
 +            int currEntityCount = info.mobCategoryCounts.getInt(enumcreaturetype);
 +            int k1 = limit * info.getSpawnableChunkCount() / NaturalSpawner.MAGIC_NUMBER;
@@ -689,25 +684,24 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +
 +            if (world.paperConfig.perPlayerMobSpawns) {
 +                int minDiff = Integer.MAX_VALUE;
-+                for (ServerPlayer entityplayer : world.getChunkSource().chunkMap.playerMobDistanceMap.getPlayersInRange(chunk.getPos())) {
++                for (net.minecraft.server.level.ServerPlayer entityplayer : world.getChunkSource().chunkMap.playerMobDistanceMap.getPlayersInRange(chunk.getPos())) {
 +                    minDiff = Math.min(limit - world.getChunkSource().chunkMap.getMobCountNear(entityplayer, enumcreaturetype), minDiff);
 +                }
 +                difference = (minDiff == Integer.MAX_VALUE) ? 0 : minDiff;
 +            }
-+            // Paper end
-+
-+            // Paper start - per player mob spawning
 +            if ((spawnAnimals || !enumcreaturetype.isFriendly()) && (spawnMonsters || enumcreaturetype.isFriendly()) && (rareSpawn || !enumcreaturetype.isPersistent()) && difference > 0) {
++                // Paper end
                  // CraftBukkit end
                  Objects.requireNonNull(info);
                  NaturalSpawner.SpawnPredicate spawnercreature_c = info::canSpawn;
  
                  Objects.requireNonNull(info);
 -                NaturalSpawner.spawnCategoryForChunk(enumcreaturetype, world, chunk, spawnercreature_c, info::afterSpawn);
++                // Paper start
 +                int spawnCount = NaturalSpawner.spawnCategoryForChunk(enumcreaturetype, world, chunk, spawnercreature_c, info::afterSpawn,
 +                    difference, world.paperConfig.perPlayerMobSpawns ? world.getChunkSource().chunkMap::updatePlayerMobTypeMap : null);
 +                info.mobCategoryCounts.mergeInt(enumcreaturetype, spawnCount, Integer::sum);
-+                // Paper end - per player mob spawning
++                // Paper end
              }
          }
  
@@ -724,10 +718,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          BlockPos blockposition = NaturalSpawner.getRandomPosWithin(world, chunk);
  
          if (blockposition.getY() >= world.getMinBuildHeight() + 1) {
--            NaturalSpawner.spawnCategoryForPosition(group, world, (ChunkAccess) chunk, blockposition, checker, runner);
-+            return NaturalSpawner.spawnCategoryForPosition(group, world, (ChunkAccess) chunk, blockposition, checker, runner, maxSpawns, trackEntity); // Paper
+-            NaturalSpawner.spawnCategoryForPosition(group, world, chunk, blockposition, checker, runner);
++            return NaturalSpawner.spawnCategoryForPosition(group, world, chunk, blockposition, checker, runner, maxSpawns, trackEntity); // Paper
          }
-+        return 0; // Paper
++        return 0; // paper
      }
  
      @VisibleForDebug
@@ -750,7 +744,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          if (iblockdata != null && !iblockdata.isRedstoneConductor(chunk, pos)) { // Paper - don't load chunks for mob spawn
              BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos();
 -            int j = 0;
-+            // Paper - moved up
++            //int j = 0; // Paper - moved up
              int k = 0;
  
              while (k < 3) {