From cc98f4982e76128870a212f7700965ea745e4f19 Mon Sep 17 00:00:00 2001 From: Taiyou <77050201+Taiyou06@users.noreply.github.com> Date: Wed, 27 Aug 2025 20:00:46 +0200 Subject: [PATCH] backport 1.21.8 async mob spawn (#479) * backport: 1.21.8 async mob spawn * Move into patch * fix * fix build --------- Co-authored-by: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> Co-authored-by: hayanesuru --- .../features/0176-optimize-mob-spawning.patch | 260 +++++++++++++++++- .../features/0178-throttle-mob-spawning.patch | 4 +- .../features/0188-Paw-optimization.patch | 4 +- .../features/0189-optimize-random-tick.patch | 4 +- .../0190-count-all-chunks-for-ticking.patch | 4 +- ...004-Pufferfish-Optimize-mob-spawning.patch | 190 ------------- ...=> 0004-Purpur-Server-Paper-Changes.patch} | 0 ...5-Fix-Pufferfish-and-Purpur-patches.patch} | 0 ...imings.patch => 0006-Remove-Timings.patch} | 0 ...patch => 0007-KeYi-Player-Skull-API.patch} | 0 ...atch => 0008-Slice-Smooth-Teleports.patch} | 0 ....patch => 0009-Leaves-Protocol-Core.patch} | 0 ...patch => 0010-Leaves-Replay-Mod-API.patch} | 0 ... => 0011-Skip-event-if-no-listeners.patch} | 0 ...-EntityScheduler-s-executeTick-chec.patch} | 0 ...SparklyPaper-Optimize-canSee-checks.patch} | 0 ...atch => 0014-Including-5s-in-getTPS.patch} | 0 ...eption-on-missing-ResourceKey-value.patch} | 0 ...-Virtual-Thread-for-async-scheduler.patch} | 0 ...onfigurable-chat-message-signatures.patch} | 0 ...ed.patch => 0018-Matter-Secure-Seed.patch} | 0 ...tch => 0019-Faster-random-generator.patch} | 0 ...onfigurable-unknown-command-message.patch} | 0 ...world-map-with-optimized-collection.patch} | 0 ...ntityType-minecraftToBukkit-convert.patch} | 0 ...patch => 0023-Multithreaded-Tracker.patch} | 0 ....patch => 0024-Asynchronous-locator.patch} | 0 ...-snapshots-for-acquiring-blockstate.patch} | 0 ...CraftServer-getworlds-list-creation.patch} | 0 ...k-key.patch => 0027-Cache-chunk-key.patch} | 0 ... => 0028-Async-structure-locate-api.patch} | 0 ...> 0029-PlayerInventoryOverflowEvent.patch} | 0 ...SparklyPaper-Parallel-world-ticking.patch} | 0 ...r-PR-Throttle-failed-spawn-attempts.patch} | 0 ...tch => 0032-Async-playerdata-saving.patch} | 0 ...rPR-Fix-save-load-NaN-Entity-Motion.patch} | 0 ...erPR-Fix-unnecessary-map-data-saves.patch} | 0 ...send.patch => 0035-Async-chunk-send.patch} | 0 ...036-Optimise-player-movement-checks.patch} | 0 ...atch => 0037-optimise-ReferenceList.patch} | 0 ...tBiome.patch => 0038-cache-getBiome.patch} | 0 ...Optimise-CraftWorld-getLoadedChunks.patch} | 0 ...tWorld-getForceLoadedChunks-to-avoi.patch} | 0 ...hread.patch => 0041-dump-pwt-thread.patch} | 0 ...tion.patch => 0042-Paw-optimization.patch} | 0 ...ch => 0043-Toggleable-async-catcher.patch} | 0 ...ta.patch => 0044-cache-profile-data.patch} | 0 47 files changed, 256 insertions(+), 210 deletions(-) delete mode 100644 leaf-server/paper-patches/features/0004-Pufferfish-Optimize-mob-spawning.patch rename leaf-server/paper-patches/features/{0005-Purpur-Server-Paper-Changes.patch => 0004-Purpur-Server-Paper-Changes.patch} (100%) rename leaf-server/paper-patches/features/{0006-Fix-Pufferfish-and-Purpur-patches.patch => 0005-Fix-Pufferfish-and-Purpur-patches.patch} (100%) rename leaf-server/paper-patches/features/{0007-Remove-Timings.patch => 0006-Remove-Timings.patch} (100%) rename leaf-server/paper-patches/features/{0008-KeYi-Player-Skull-API.patch => 0007-KeYi-Player-Skull-API.patch} (100%) rename leaf-server/paper-patches/features/{0009-Slice-Smooth-Teleports.patch => 0008-Slice-Smooth-Teleports.patch} (100%) rename leaf-server/paper-patches/features/{0010-Leaves-Protocol-Core.patch => 0009-Leaves-Protocol-Core.patch} (100%) rename leaf-server/paper-patches/features/{0011-Leaves-Replay-Mod-API.patch => 0010-Leaves-Replay-Mod-API.patch} (100%) rename leaf-server/paper-patches/features/{0012-Skip-event-if-no-listeners.patch => 0011-Skip-event-if-no-listeners.patch} (100%) rename leaf-server/paper-patches/features/{0013-SparklyPaper-Skip-EntityScheduler-s-executeTick-chec.patch => 0012-SparklyPaper-Skip-EntityScheduler-s-executeTick-chec.patch} (100%) rename leaf-server/paper-patches/features/{0014-SparklyPaper-Optimize-canSee-checks.patch => 0013-SparklyPaper-Optimize-canSee-checks.patch} (100%) rename leaf-server/paper-patches/features/{0015-Including-5s-in-getTPS.patch => 0014-Including-5s-in-getTPS.patch} (100%) rename leaf-server/paper-patches/features/{0016-Don-t-throw-exception-on-missing-ResourceKey-value.patch => 0015-Don-t-throw-exception-on-missing-ResourceKey-value.patch} (100%) rename leaf-server/paper-patches/features/{0017-Virtual-Thread-for-async-scheduler.patch => 0016-Virtual-Thread-for-async-scheduler.patch} (100%) rename leaf-server/paper-patches/features/{0018-Mirai-Configurable-chat-message-signatures.patch => 0017-Mirai-Configurable-chat-message-signatures.patch} (100%) rename leaf-server/paper-patches/features/{0019-Matter-Secure-Seed.patch => 0018-Matter-Secure-Seed.patch} (100%) rename leaf-server/paper-patches/features/{0020-Faster-random-generator.patch => 0019-Faster-random-generator.patch} (100%) rename leaf-server/paper-patches/features/{0021-Configurable-unknown-command-message.patch => 0020-Configurable-unknown-command-message.patch} (100%) rename leaf-server/paper-patches/features/{0022-Replace-world-map-with-optimized-collection.patch => 0021-Replace-world-map-with-optimized-collection.patch} (100%) rename leaf-server/paper-patches/features/{0023-Cache-CraftEntityType-minecraftToBukkit-convert.patch => 0022-Cache-CraftEntityType-minecraftToBukkit-convert.patch} (100%) rename leaf-server/paper-patches/features/{0024-Multithreaded-Tracker.patch => 0023-Multithreaded-Tracker.patch} (100%) rename leaf-server/paper-patches/features/{0025-Asynchronous-locator.patch => 0024-Asynchronous-locator.patch} (100%) rename leaf-server/paper-patches/features/{0026-EMC-Don-t-use-snapshots-for-acquiring-blockstate.patch => 0025-EMC-Don-t-use-snapshots-for-acquiring-blockstate.patch} (100%) rename leaf-server/paper-patches/features/{0027-Faster-CraftServer-getworlds-list-creation.patch => 0026-Faster-CraftServer-getworlds-list-creation.patch} (100%) rename leaf-server/paper-patches/features/{0028-Cache-chunk-key.patch => 0027-Cache-chunk-key.patch} (100%) rename leaf-server/paper-patches/features/{0029-Async-structure-locate-api.patch => 0028-Async-structure-locate-api.patch} (100%) rename leaf-server/paper-patches/features/{0030-PlayerInventoryOverflowEvent.patch => 0029-PlayerInventoryOverflowEvent.patch} (100%) rename leaf-server/paper-patches/features/{0031-SparklyPaper-Parallel-world-ticking.patch => 0030-SparklyPaper-Parallel-world-ticking.patch} (100%) rename leaf-server/paper-patches/features/{0032-Paper-PR-Throttle-failed-spawn-attempts.patch => 0031-Paper-PR-Throttle-failed-spawn-attempts.patch} (100%) rename leaf-server/paper-patches/features/{0033-Async-playerdata-saving.patch => 0032-Async-playerdata-saving.patch} (100%) rename leaf-server/paper-patches/features/{0034-PaperPR-Fix-save-load-NaN-Entity-Motion.patch => 0033-PaperPR-Fix-save-load-NaN-Entity-Motion.patch} (100%) rename leaf-server/paper-patches/features/{0035-PaperPR-Fix-unnecessary-map-data-saves.patch => 0034-PaperPR-Fix-unnecessary-map-data-saves.patch} (100%) rename leaf-server/paper-patches/features/{0036-Async-chunk-send.patch => 0035-Async-chunk-send.patch} (100%) rename leaf-server/paper-patches/features/{0037-Optimise-player-movement-checks.patch => 0036-Optimise-player-movement-checks.patch} (100%) rename leaf-server/paper-patches/features/{0038-optimise-ReferenceList.patch => 0037-optimise-ReferenceList.patch} (100%) rename leaf-server/paper-patches/features/{0039-cache-getBiome.patch => 0038-cache-getBiome.patch} (100%) rename leaf-server/paper-patches/features/{0040-Paper-Optimise-CraftWorld-getLoadedChunks.patch => 0039-Paper-Optimise-CraftWorld-getLoadedChunks.patch} (100%) rename leaf-server/paper-patches/features/{0041-Paper-Update-CraftWorld-getForceLoadedChunks-to-avoi.patch => 0040-Paper-Update-CraftWorld-getForceLoadedChunks-to-avoi.patch} (100%) rename leaf-server/paper-patches/features/{0042-dump-pwt-thread.patch => 0041-dump-pwt-thread.patch} (100%) rename leaf-server/paper-patches/features/{0043-Paw-optimization.patch => 0042-Paw-optimization.patch} (100%) rename leaf-server/paper-patches/features/{0044-Toggleable-async-catcher.patch => 0043-Toggleable-async-catcher.patch} (100%) rename leaf-server/paper-patches/features/{0045-cache-profile-data.patch => 0044-cache-profile-data.patch} (100%) diff --git a/leaf-server/minecraft-patches/features/0176-optimize-mob-spawning.patch b/leaf-server/minecraft-patches/features/0176-optimize-mob-spawning.patch index f27988ec..9fcb8306 100644 --- a/leaf-server/minecraft-patches/features/0176-optimize-mob-spawning.patch +++ b/leaf-server/minecraft-patches/features/0176-optimize-mob-spawning.patch @@ -4,8 +4,20 @@ Date: Tue, 3 Jun 2025 15:20:59 +0900 Subject: [PATCH] optimize mob spawning +diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java +index f3be481a92b4f5403809c38d3b3431f4096d7a2e..2a5a2b6c28c61fe5cc3c89676472b9695fd3f188 100644 +--- a/net/minecraft/server/level/ChunkMap.java ++++ b/net/minecraft/server/level/ChunkMap.java +@@ -280,6 +280,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + // Paper end - per player mob count backoff + public int getMobCountNear(final ServerPlayer player, final net.minecraft.world.entity.MobCategory mobCategory) { ++ // Leaf - diff - async mob spawning - optimize mob spawning + return player.mobCounts[mobCategory.ordinal()] + player.mobBackoffCounts[mobCategory.ordinal()]; // Paper - per player mob count backoff + } + // Paper end - Optional per player mob spawns diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java -index 52a2b993bbd1ad4851b3273af6ecbc069beb5b84..05df09d5f586c90f3169ddf1fa73a1d3fd734b73 100644 +index 52a2b993bbd1ad4851b3273af6ecbc069beb5b84..f66f16332bd1af89a44b71bc015d52a2aeda09de 100644 --- a/net/minecraft/server/level/ServerChunkCache.java +++ b/net/minecraft/server/level/ServerChunkCache.java @@ -70,7 +70,9 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon @@ -19,7 +31,86 @@ index 52a2b993bbd1ad4851b3273af6ecbc069beb5b84..05df09d5f586c90f3169ddf1fa73a1d3 // Paper start public final ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable fullChunks = new ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable<>(); public int getFullChunksCount() { -@@ -658,13 +660,37 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon +@@ -496,6 +498,23 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + long gameTime = this.level.getGameTime(); + long l = gameTime - this.lastInhabitedUpdate; + this.lastInhabitedUpdate = gameTime; ++ // Leaf start - optimize mob spawning ++ if (org.dreeam.leaf.config.modules.async.AsyncMobSpawning.enabled && level.paperConfig().entities.spawning.perPlayerMobSpawns) { ++ for (ServerPlayer player : this.level.players) { ++ // Paper start - per player mob spawning backoff ++ for (int ii = 0; ii < ServerPlayer.MOBCATEGORY_TOTAL_ENUMS; ii++) { ++ player.mobCounts[ii] = 0; ++ ++ int newBackoff = player.mobBackoffCounts[ii] - 1; // TODO make configurable bleed // TODO use nonlinear algorithm? ++ if (newBackoff < 0) { ++ newBackoff = 0; ++ } ++ player.mobBackoffCounts[ii] = newBackoff; ++ } ++ // Paper end - per player mob spawning backoff ++ } ++ } ++ // Leaf end - optimize mob spawning + if (!this.level.isDebug()) { + this.level.resetIceAndSnowTick(); // Gale - Airplane - optimize random calls in chunk ticking - reset ice & snow tick random + if (this.level.tickRateManager().runsNormally()) { +@@ -518,8 +537,8 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + } + + // Pufferfish start - optimize mob spawning +- if (org.dreeam.leaf.config.modules.async.AsyncMobSpawning.enabled) { +- for (ServerPlayer player : this.level.players) { ++ if (org.dreeam.leaf.config.modules.async.AsyncMobSpawning.enabled && level.paperConfig().entities.spawning.perPlayerMobSpawns) { ++ /*for (ServerPlayer player : this.level.players) { + // Paper start - per player mob spawning backoff + for (int ii = 0; ii < ServerPlayer.MOBCATEGORY_TOTAL_ENUMS; ii++) { + player.mobCounts[ii] = 0; +@@ -531,34 +550,21 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + player.mobBackoffCounts[ii] = newBackoff; + } + // Paper end - per player mob spawning backoff +- } ++ }*/ + if (firstRunSpawnCounts) { + firstRunSpawnCounts = false; + _pufferfish_spawnCountsReady.set(true); + } + if (_pufferfish_spawnCountsReady.getAndSet(false)) { ++ final int mapped = distanceManager.getNaturalSpawnChunkCount(); ++ final Iterable entities = this.level.getAllEntities(); + net.minecraft.server.MinecraftServer.getServer().mobSpawnExecutor.submit(() -> { +- int mapped = distanceManager.getNaturalSpawnChunkCount(); +- ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet.Iterator objectiterator = +- level.entityTickList.entities.iterator(ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet.ITERATOR_FLAG_SEE_ADDITIONS); +- try { +- gg.pufferfish.pufferfish.util.IterableWrapper wrappedIterator = +- new gg.pufferfish.pufferfish.util.IterableWrapper<>(objectiterator); +- // Fix: Use proper mob cap calculator based on configuration +- LocalMobCapCalculator mobCapCalculator = !level.paperConfig().entities.spawning.perPlayerMobSpawns ? +- new LocalMobCapCalculator(chunkMap) : null; +- +- // This ensures the caps are properly enforced by using the correct calculator +- lastSpawnState = NaturalSpawner.createState( +- mapped, +- wrappedIterator, +- ServerChunkCache.this::getFullChunk, +- mobCapCalculator, // This is the key fix - was previously null +- level.paperConfig().entities.spawning.perPlayerMobSpawns +- ); +- } finally { +- objectiterator.finishedIterating(); +- } ++ lastSpawnState = NaturalSpawner.createState1( ++ mapped, ++ entities, ++ this.level ++ ); ++ // Leaf end - optimize mob spawning + _pufferfish_spawnCountsReady.set(true); + }); + } +@@ -658,13 +664,38 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon filteredSpawningCategories = List.of(); } @@ -30,7 +121,8 @@ index 52a2b993bbd1ad4851b3273af6ecbc069beb5b84..05df09d5f586c90f3169ddf1fa73a1d3 - NaturalSpawner.spawnForChunk(this.level, levelChunk, lastSpawnState, filteredSpawningCategories); // Pufferfish + // Leaf start - optimize mob spawning + var lastSpawnState1 = this.lastSpawnState; -+ if (lastSpawnState1 != null && (!org.dreeam.leaf.config.modules.async.AsyncMobSpawning.enabled || _pufferfish_spawnCountsReady.get())) { ++ if (lastSpawnState1 != null && (!org.dreeam.leaf.config.modules.async.AsyncMobSpawning.enabled || !level.paperConfig().entities.spawning.perPlayerMobSpawns || _pufferfish_spawnCountsReady.get())) { ++ lastSpawnState1.applyPerPlayerMobCount(level); // Leaf - optimize mob spawning + long sumTimeInhabited = timeInhabited + delayTimeInhabited; + long time = level.getGameTime(); + for (LevelChunk levelChunk : chunks) { @@ -39,7 +131,7 @@ index 52a2b993bbd1ad4851b3273af6ecbc069beb5b84..05df09d5f586c90f3169ddf1fa73a1d3 + if (!filteredSpawningCategories.isEmpty() && this.level.getWorldBorder().isWithinBounds(pos) && this.chunkMap.anyPlayerCloseEnoughForSpawning(pos, true)) { // Spigot + NaturalSpawner.spawnForChunk(this.level, levelChunk, lastSpawnState1, filteredSpawningCategories, time); // Pufferfish + } -+ } + } + if (delaySpawn != -1L) { + time = delaySpawn; + for (LevelChunk levelChunk : chunks) { @@ -48,7 +140,7 @@ index 52a2b993bbd1ad4851b3273af6ecbc069beb5b84..05df09d5f586c90f3169ddf1fa73a1d3 + NaturalSpawner.spawnForChunk(this.level, levelChunk, lastSpawnState1, filteredSpawningCategories, time); // Pufferfish + } + } - } ++ } + delaySpawn = -1L; + delayTimeInhabited = 0L; + } else { @@ -63,10 +155,85 @@ index 52a2b993bbd1ad4851b3273af6ecbc069beb5b84..05df09d5f586c90f3169ddf1fa73a1d3 this.level.tickChunk(levelChunk, _int); } diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java -index 9b37b763c6555705f3e256010f508b5a0c2cdb66..8f999b425bce52352a04ee3ca11b6854194dd665 100644 +index 9b37b763c6555705f3e256010f508b5a0c2cdb66..418fd9db5a06af5369da597762c0757453929f83 100644 --- a/net/minecraft/world/level/NaturalSpawner.java +++ b/net/minecraft/world/level/NaturalSpawner.java -@@ -155,7 +155,13 @@ public final class NaturalSpawner { +@@ -74,6 +74,7 @@ public final class NaturalSpawner { + return createState(spawnableChunkCount, entities, chunkGetter, calculator, false); + } + ++ @Deprecated // Leaf - optimize mob spawning + public static NaturalSpawner.SpawnState createState( + int spawnableChunkCount, Iterable entities, NaturalSpawner.ChunkGetter chunkGetter, LocalMobCapCalculator calculator, final boolean countMobs + ) { +@@ -114,9 +115,65 @@ public final class NaturalSpawner { + } + } + +- return new NaturalSpawner.SpawnState(spawnableChunkCount, map, potentialCalculator, calculator); ++ return new NaturalSpawner.SpawnState(spawnableChunkCount, map, potentialCalculator, calculator, new it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<>()); // Leaf - optimize mob spawning + } + ++ // Leaf start - optimize mob spawning ++ public static NaturalSpawner.SpawnState createState1( ++ int spawnableChunkCount, Iterable entities, ServerLevel level ++ ) { ++ // Paper end - Optional per player mob spawns ++ PotentialCalculator potentialCalculator = new PotentialCalculator(); ++ Object2IntOpenHashMap map = new Object2IntOpenHashMap<>(); ++ it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap chunkCap = new it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<>(); ++ boolean countAllMobsForSpawning = level.paperConfig().entities.spawning.countAllMobsForSpawning; ++ for (Entity entity : entities) { ++ if (!(entity instanceof Mob mob && (mob.isPersistenceRequired() || mob.requiresCustomPersistence()))) { ++ MobCategory category = entity.getType().getCategory(); ++ if (category != MobCategory.MISC) { ++ // Paper start - Only count natural spawns ++ if (!countAllMobsForSpawning && ++ !(entity.spawnReason == org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL || ++ entity.spawnReason == org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CHUNK_GEN)) { ++ continue; ++ } ++ // Paper end - Only count natural spawns ++ BlockPos blockPos = entity.blockPosition(); ++ LevelChunk chunk = level.getChunkSource().getChunkNow(blockPos.getX() >> 4, blockPos.getZ() >> 4); ++ if (chunk != null) { ++ MobSpawnSettings.MobSpawnCost mobSpawnCost = getRoughBiome(blockPos, chunk).getMobSettings().getMobSpawnCost(entity.getType()); ++ if (mobSpawnCost != null) { ++ potentialCalculator.addCharge(entity.blockPosition(), mobSpawnCost.charge()); ++ } ++ ++ map.addTo(category, 1); ++ // Paper start - Optional per player mob spawns ++ final int index = entity.getType().getCategory().ordinal(); ++ ++chunkCap.computeIfAbsent(chunk.getPos().toLong(), k -> new int[net.minecraft.server.level.ServerPlayer.MOBCATEGORY_TOTAL_ENUMS])[index]; ++ /* ++ final int index = entity.getType().getCategory().ordinal(); ++ final var inRange = level.moonrise$getNearbyPlayers().getPlayers(entity.chunkPosition(), NearbyPlayers.NearbyMapType.TICK_VIEW_DISTANCE); ++ if (inRange == null) { ++ continue; ++ } ++ ++ final net.minecraft.server.level.ServerPlayer[] backingSet = inRange.getRawDataUnchecked(); ++ for (int i = 0, len = inRange.size(); i < len; i++) { ++ final net.minecraft.server.level.ServerPlayer player = backingSet[i]; ++ if (player == null) continue; ++ ++playerCap.computeIfAbsent(player, k -> new int[net.minecraft.server.level.ServerPlayer.MOBCATEGORY_TOTAL_ENUMS])[index]; ++ } ++ */ ++ // Paper end - Optional per player mob spawns ++ } ++ } ++ } ++ } ++ ++ return new NaturalSpawner.SpawnState(spawnableChunkCount, map, potentialCalculator, null, chunkCap); ++ } ++ // Leaf end - optimize mob spawning ++ + static Biome getRoughBiome(BlockPos pos, ChunkAccess chunk) { + return chunk.getNoiseBiome(QuartPos.fromBlock(pos.getX()), QuartPos.fromBlock(pos.getY()), QuartPos.fromBlock(pos.getZ())).value(); + } +@@ -155,7 +212,13 @@ public final class NaturalSpawner { return list; } @@ -80,7 +247,7 @@ index 9b37b763c6555705f3e256010f508b5a0c2cdb66..8f999b425bce52352a04ee3ca11b6854 for (MobCategory mobCategory : categories) { // Paper start - Optional per player mob spawns final boolean canSpawn; -@@ -174,7 +180,7 @@ public final class NaturalSpawner { +@@ -174,7 +237,7 @@ public final class NaturalSpawner { } // Paper end - throttle failed spawn attempts if (CraftSpawnCategory.isValidForLimits(spawnCategory)) { @@ -89,7 +256,7 @@ index 9b37b763c6555705f3e256010f508b5a0c2cdb66..8f999b425bce52352a04ee3ca11b6854 limit = level.getWorld().getSpawnLimit(spawnCategory); } -@@ -238,12 +244,14 @@ public final class NaturalSpawner { +@@ -238,12 +301,14 @@ public final class NaturalSpawner { // Paper end - throttle failed spawn attempts ) { // Paper end - Optional per player mob spawns @@ -109,7 +276,7 @@ index 9b37b763c6555705f3e256010f508b5a0c2cdb66..8f999b425bce52352a04ee3ca11b6854 } @VisibleForDebug -@@ -275,31 +283,59 @@ public final class NaturalSpawner { +@@ -275,31 +340,59 @@ public final class NaturalSpawner { StructureManager structureManager = level.structureManager(); ChunkGenerator generator = level.getChunkSource().getGenerator(); int y = pos.getY(); @@ -177,7 +344,7 @@ index 9b37b763c6555705f3e256010f508b5a0c2cdb66..8f999b425bce52352a04ee3ca11b6854 if (spawnerData == null) { Optional randomSpawnMobAt = getRandomSpawnMobAt( level, structureManager, generator, category, level.random, mutableBlockPos -@@ -368,8 +404,8 @@ public final class NaturalSpawner { +@@ -368,8 +461,8 @@ public final class NaturalSpawner { private static boolean isRightDistanceToPlayerAndSpawnPoint(ServerLevel level, ChunkAccess chunk, BlockPos.MutableBlockPos pos, double distance) { return !(distance <= 576.0) @@ -188,7 +355,7 @@ index 9b37b763c6555705f3e256010f508b5a0c2cdb66..8f999b425bce52352a04ee3ca11b6854 } // Paper start - PreCreatureSpawnEvent -@@ -474,6 +510,17 @@ public final class NaturalSpawner { +@@ -474,6 +567,17 @@ public final class NaturalSpawner { } } @@ -206,3 +373,72 @@ index 9b37b763c6555705f3e256010f508b5a0c2cdb66..8f999b425bce52352a04ee3ca11b6854 private static BlockPos getRandomPosWithin(Level level, LevelChunk chunk) { ChunkPos pos = chunk.getPos(); int i = pos.getMinBlockX() + level.random.nextInt(16); +@@ -614,18 +718,21 @@ public final class NaturalSpawner { + @Nullable + private EntityType lastCheckedType; + private double lastCharge; ++ public final it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap chunkCap; // Leaf - optimize mob spawning + + SpawnState( + int spawnableChunkCount, + Object2IntOpenHashMap mobCategoryCounts, + PotentialCalculator spawnPotential, +- LocalMobCapCalculator localMobCapCalculator ++ LocalMobCapCalculator localMobCapCalculator, ++ it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap playerCap // Leaf - optimize mob spawning + ) { + this.spawnableChunkCount = spawnableChunkCount; + this.mobCategoryCounts = mobCategoryCounts; + this.spawnPotential = spawnPotential; + this.localMobCapCalculator = localMobCapCalculator; + this.unmodifiableMobCategoryCounts = Object2IntMaps.unmodifiable(mobCategoryCounts); ++ this.chunkCap = playerCap; // Leaf - optimize mob spawning + } + + private boolean canSpawn(EntityType entityType, BlockPos pos, ChunkAccess chunk) { +@@ -682,5 +789,32 @@ public final class NaturalSpawner { + boolean canSpawnForCategoryLocal(MobCategory category, ChunkPos chunkPos) { + return this.localMobCapCalculator.canSpawn(category, chunkPos); + } ++ ++ // Leaf start - optimize mob spawning ++ public void applyPerPlayerMobCount(ServerLevel level) { ++ if (chunkCap.isEmpty()) { ++ return; ++ } ++ final var iterator = chunkCap.long2ObjectEntrySet().fastIterator(); ++ final ca.spottedleaf.moonrise.common.misc.NearbyPlayers nearbyPlayers = level.moonrise$getNearbyPlayers(); ++ while (iterator.hasNext()) { ++ var entry = iterator.next(); ++ long chunk = entry.getLongKey(); ++ int[] cap = entry.getValue(); ++ ca.spottedleaf.moonrise.common.list.ReferenceList players = nearbyPlayers.getPlayersByChunk(net.minecraft.world.level.ChunkPos.getX(chunk), net.minecraft.world.level.ChunkPos.getZ(chunk), ca.spottedleaf.moonrise.common.misc.NearbyPlayers.NearbyMapType.TICK_VIEW_DISTANCE); ++ if (players == null) { ++ continue; ++ } ++ int playersSize = players.size(); ++ net.minecraft.server.level.ServerPlayer[] playersRawDataUnchecked = players.getRawDataUnchecked(); ++ for (int i = 0; i < playersSize; i++) { ++ int[] p = playersRawDataUnchecked[i].mobCounts; ++ for (int j = 0; j < net.minecraft.server.level.ServerPlayer.MOBCATEGORY_TOTAL_ENUMS; j++) { ++ p[j] += cap[j]; ++ } ++ } ++ } ++ } ++ // Leaf end - optimize mob spawning + } + } +diff --git a/net/minecraft/world/level/entity/EntityTickList.java b/net/minecraft/world/level/entity/EntityTickList.java +index 5a90b3bffeeb08a168b370e49d18c5f8b257a980..ba173bc1751c495e6fa497566b5ed3c7a9547364 100644 +--- a/net/minecraft/world/level/entity/EntityTickList.java ++++ b/net/minecraft/world/level/entity/EntityTickList.java +@@ -9,7 +9,7 @@ import javax.annotation.Nullable; + import net.minecraft.world.entity.Entity; + + public class EntityTickList { +- public final ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet entities = new ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet<>(org.dreeam.leaf.config.modules.async.AsyncMobSpawning.enabled); // Paper - rewrite chunk system // Pufferfish - private->public and do thread check ++ private final ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet entities = new ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet<>(); // Paper - rewrite chunk system + + // Leaf start - SparklyPaper - parallel world ticking mod + // preserve original constructor diff --git a/leaf-server/minecraft-patches/features/0178-throttle-mob-spawning.patch b/leaf-server/minecraft-patches/features/0178-throttle-mob-spawning.patch index 4eb97e17..c051ccf9 100644 --- a/leaf-server/minecraft-patches/features/0178-throttle-mob-spawning.patch +++ b/leaf-server/minecraft-patches/features/0178-throttle-mob-spawning.patch @@ -5,10 +5,10 @@ Subject: [PATCH] throttle mob spawning diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java -index 8f999b425bce52352a04ee3ca11b6854194dd665..48ab439560c6ba83d34163cc7402146e69e7c277 100644 +index 6e911df433013480c2688c086a7ff1de321001bc..7764fcca95cef9f0aa46683f41d3a6805507f80a 100644 --- a/net/minecraft/world/level/NaturalSpawner.java +++ b/net/minecraft/world/level/NaturalSpawner.java -@@ -166,6 +166,17 @@ public final class NaturalSpawner { +@@ -223,6 +223,17 @@ public final class NaturalSpawner { // Paper start - Optional per player mob spawns final boolean canSpawn; int maxSpawns = Integer.MAX_VALUE; diff --git a/leaf-server/minecraft-patches/features/0188-Paw-optimization.patch b/leaf-server/minecraft-patches/features/0188-Paw-optimization.patch index 53c9fdec..bbea9515 100644 --- a/leaf-server/minecraft-patches/features/0188-Paw-optimization.patch +++ b/leaf-server/minecraft-patches/features/0188-Paw-optimization.patch @@ -100,10 +100,10 @@ index 4535858701b2bb232b9d2feb2af6551526232ddc..e65c62dbe4c1560ae153e4c4344e9194 - // Paper end - detailed watchdog information } diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java -index 05df09d5f586c90f3169ddf1fa73a1d3fd734b73..fbcff9a0e4aa68375e7ebcc297ba4a7bf089c4f3 100644 +index f66f16332bd1af89a44b71bc015d52a2aeda09de..bb200d3f482c7f623a827d255a9633bb278637e9 100644 --- a/net/minecraft/server/level/ServerChunkCache.java +++ b/net/minecraft/server/level/ServerChunkCache.java -@@ -506,9 +506,10 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon +@@ -523,9 +523,10 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon try { this.collectTickingChunks(list); // Paper start - chunk tick iteration optimisation diff --git a/leaf-server/minecraft-patches/features/0189-optimize-random-tick.patch b/leaf-server/minecraft-patches/features/0189-optimize-random-tick.patch index 0f3e4703..369a0c38 100644 --- a/leaf-server/minecraft-patches/features/0189-optimize-random-tick.patch +++ b/leaf-server/minecraft-patches/features/0189-optimize-random-tick.patch @@ -5,10 +5,10 @@ Subject: [PATCH] optimize random tick diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java -index fbcff9a0e4aa68375e7ebcc297ba4a7bf089c4f3..e07fdd22e08cb4e30cf606c055e85b5946e8c046 100644 +index bb200d3f482c7f623a827d255a9633bb278637e9..7531e684e16bc038811fbf133caced9c7f5efe07 100644 --- a/net/minecraft/server/level/ServerChunkCache.java +++ b/net/minecraft/server/level/ServerChunkCache.java -@@ -696,6 +696,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon +@@ -701,6 +701,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon this.level.tickChunk(levelChunk, _int); } } diff --git a/leaf-server/minecraft-patches/features/0190-count-all-chunks-for-ticking.patch b/leaf-server/minecraft-patches/features/0190-count-all-chunks-for-ticking.patch index 412e9f5c..1241e833 100644 --- a/leaf-server/minecraft-patches/features/0190-count-all-chunks-for-ticking.patch +++ b/leaf-server/minecraft-patches/features/0190-count-all-chunks-for-ticking.patch @@ -5,10 +5,10 @@ Subject: [PATCH] count all chunks for ticking diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java -index e07fdd22e08cb4e30cf606c055e85b5946e8c046..432c98b582ab40f893835a7a24ef9bbdacc49bd7 100644 +index 7531e684e16bc038811fbf133caced9c7f5efe07..10fb9cc994ddc8820bed23d722b49b9f33e5fc09 100644 --- a/net/minecraft/server/level/ServerChunkCache.java +++ b/net/minecraft/server/level/ServerChunkCache.java -@@ -589,6 +589,14 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon +@@ -593,6 +593,14 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon final int size = tickingChunks.size(); final ChunkMap chunkMap = this.chunkMap; diff --git a/leaf-server/paper-patches/features/0004-Pufferfish-Optimize-mob-spawning.patch b/leaf-server/paper-patches/features/0004-Pufferfish-Optimize-mob-spawning.patch deleted file mode 100644 index 20aa36e0..00000000 --- a/leaf-server/paper-patches/features/0004-Pufferfish-Optimize-mob-spawning.patch +++ /dev/null @@ -1,190 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Kevin Raneri -Date: Wed, 10 Nov 2021 00:37:03 -0500 -Subject: [PATCH] Pufferfish: Optimize mob spawning - -Original license: GPL v3 -Original project: https://github.com/pufferfish-gg/Pufferfish - -Co-authored-by: booky10 -Co-authored-by: HaHaWTH <102713261+HaHaWTH@users.noreply.github.com> - -This patch aims to reduce the main-thread impact of mob spawning by -offloading as much work as possible to other threads. It is possible for -inconsistencies to come up, but when they happen they never interfere -with the server's operation (they don't produce errors), and side -effects are limited to more or less mobs being spawned in any particular -tick. - -It is possible to disable this optimization if it is not required or if -it interferes with any plugins. On servers with thousands of entities, -this can result in performance gains of up to 15%, which is significant -and, in my opinion, worth the low risk of minor mob-spawning-related -inconsistencies. - -diff --git a/src/main/java/ca/spottedleaf/moonrise/common/list/IteratorSafeOrderedReferenceSet.java b/src/main/java/ca/spottedleaf/moonrise/common/list/IteratorSafeOrderedReferenceSet.java -index c21e00812f1aaa1279834a0562d360d6b89e146c..bc06820e9e68e0ad2f8e4cb1a73d04aedf3f3e40 100644 ---- a/src/main/java/ca/spottedleaf/moonrise/common/list/IteratorSafeOrderedReferenceSet.java -+++ b/src/main/java/ca/spottedleaf/moonrise/common/list/IteratorSafeOrderedReferenceSet.java -@@ -10,7 +10,7 @@ public final class IteratorSafeOrderedReferenceSet { - public static final int ITERATOR_FLAG_SEE_ADDITIONS = 1 << 0; - - private final Reference2IntLinkedOpenHashMap indexMap; -- private int firstInvalidIndex = -1; -+ private final java.util.concurrent.atomic.AtomicInteger firstInvalidIndex = new java.util.concurrent.atomic.AtomicInteger(-1); // Leaf - Pufferfish - Async mob spawning - atomic - - /* list impl */ - private E[] listElements; -@@ -18,18 +18,32 @@ public final class IteratorSafeOrderedReferenceSet { - - private final double maxFragFactor; - -- private int iteratorCount; -+ private int iteratorCount; // Pufferfish - async mob spawning -+ -+ // Pufferfish start - async mob spawning -+ private final boolean threadRestricted; - - public IteratorSafeOrderedReferenceSet() { -- this(16, 0.75f, 16, 0.2); -+ this(16, 0.75f, 16, 0.2, false); -+ } -+ -+ public IteratorSafeOrderedReferenceSet(final boolean threadRestricted) { -+ this(16, 0.75f, 16, 0.2, threadRestricted); - } - - public IteratorSafeOrderedReferenceSet(final int setCapacity, final float setLoadFactor, final int arrayCapacity, - final double maxFragFactor) { -+ this(setCapacity, setLoadFactor, arrayCapacity, maxFragFactor, false); -+ } -+ -+ public IteratorSafeOrderedReferenceSet(final int setCapacity, final float setLoadFactor, final int arrayCapacity, -+ final double maxFragFactor, final boolean threadRestricted) { - this.indexMap = new Reference2IntLinkedOpenHashMap<>(setCapacity, setLoadFactor); - this.indexMap.defaultReturnValue(-1); - this.maxFragFactor = maxFragFactor; - this.listElements = (E[])new Object[arrayCapacity]; -+ this.threadRestricted = threadRestricted; -+ // Pufferfish end - async mob spawning - } - - /* -@@ -74,16 +88,24 @@ public final class IteratorSafeOrderedReferenceSet { - } - */ - -+ // Pufferfish start - async mob spawning -+ // Bring back allowSafeIteration from Paper 1.20.4 -+ // To defrag only on the main thread -+ private boolean allowSafeIteration() { -+ return !this.threadRestricted || ca.spottedleaf.moonrise.common.util.TickThread.isTickThread(); -+ } -+ // Pufferfish end - async mob spawning -+ - private double getFragFactor() { - return 1.0 - ((double)this.indexMap.size() / (double)this.listSize); - } - - public int createRawIterator() { -- ++this.iteratorCount; -+ if (this.allowSafeIteration()) this.iteratorCount++; // Pufferfish - async mob spawning - if (this.indexMap.isEmpty()) { - return -1; - } else { -- return this.firstInvalidIndex == 0 ? this.indexMap.getInt(this.indexMap.firstKey()) : 0; -+ return this.firstInvalidIndex.get() == 0 ? this.indexMap.getInt(this.indexMap.firstKey()) : 0; // Leaf - Pufferfish - Async mob spawning - } - } - -@@ -100,7 +122,7 @@ public final class IteratorSafeOrderedReferenceSet { - } - - public void finishRawIterator() { -- if (--this.iteratorCount == 0) { -+ if (--this.iteratorCount == 0) { // Pufferfish - async mob spawning - if (this.getFragFactor() >= this.maxFragFactor) { - this.defrag(); - } -@@ -110,14 +132,17 @@ public final class IteratorSafeOrderedReferenceSet { - public boolean remove(final E element) { - final int index = this.indexMap.removeInt(element); - if (index >= 0) { -- if (this.firstInvalidIndex < 0 || index < this.firstInvalidIndex) { -- this.firstInvalidIndex = index; -+ // Leaf start - Pufferfish - Async mob spawning -+ int firstInvalidIndex = this.firstInvalidIndex.get(); -+ if (firstInvalidIndex < 0 || index < firstInvalidIndex) { -+ this.firstInvalidIndex.set(index); - } -+ // Leaf end - Pufferfish - Async mob spawning - if (this.listElements[index] != element) { - throw new IllegalStateException(); - } - this.listElements[index] = null; -- if (this.iteratorCount == 0 && this.getFragFactor() >= this.maxFragFactor) { -+ if (this.allowSafeIteration() && this.iteratorCount == 0 && this.getFragFactor() >= this.maxFragFactor) { // Pufferfish - async mob spawning - this.defrag(); - } - //this.check(); -@@ -149,14 +174,17 @@ public final class IteratorSafeOrderedReferenceSet { - } - - private void defrag() { -- if (this.firstInvalidIndex < 0) { -+ // Leaf start - Pufferfish - Async mob spawning -+ int firstInvalidIndex = this.firstInvalidIndex.get(); -+ if (firstInvalidIndex < 0) { - return; // nothing to do - } -+ // Leaf end - Pufferfish - Async mob spawning - - if (this.indexMap.isEmpty()) { - Arrays.fill(this.listElements, 0, this.listSize, null); - this.listSize = 0; -- this.firstInvalidIndex = -1; -+ this.firstInvalidIndex.set(-1); // Leaf - Pufferfish - Async mob spawning - //this.check(); - return; - } -@@ -166,11 +194,11 @@ public final class IteratorSafeOrderedReferenceSet { - int lastValidIndex; - java.util.Iterator> iterator; - -- if (this.firstInvalidIndex == 0) { -+ if (firstInvalidIndex == 0) { // Leaf - Pufferfish - Async mob spawning - iterator = this.indexMap.reference2IntEntrySet().fastIterator(); - lastValidIndex = 0; - } else { -- lastValidIndex = this.firstInvalidIndex; -+ lastValidIndex = firstInvalidIndex; // Leaf - Pufferfish - Async mob spawning - final E key = backingArray[lastValidIndex - 1]; - iterator = this.indexMap.reference2IntEntrySet().fastIterator(new Reference2IntMap.Entry() { - @Override -@@ -201,7 +229,7 @@ public final class IteratorSafeOrderedReferenceSet { - // cleanup end - Arrays.fill(backingArray, lastValidIndex, this.listSize, null); - this.listSize = lastValidIndex; -- this.firstInvalidIndex = -1; -+ this.firstInvalidIndex.set(-1); // Leaf - Pufferfish - Async mob spawning - //this.check(); - } - -@@ -219,7 +247,7 @@ public final class IteratorSafeOrderedReferenceSet { - } - - public IteratorSafeOrderedReferenceSet.Iterator iterator(final int flags) { -- ++this.iteratorCount; -+ if (this.allowSafeIteration()) ++this.iteratorCount; // Pufferfish - async mob spawning - return new BaseIterator<>(this, true, (flags & ITERATOR_FLAG_SEE_ADDITIONS) != 0 ? Integer.MAX_VALUE : this.listSize); - } - -@@ -306,7 +334,7 @@ public final class IteratorSafeOrderedReferenceSet { - } - this.lastReturned = null; - this.finished = true; -- this.set.finishRawIterator(); -+ if (this.set.allowSafeIteration()) this.set.finishRawIterator(); // Pufferfish - async mob spawning - diff on change - } - } - } diff --git a/leaf-server/paper-patches/features/0005-Purpur-Server-Paper-Changes.patch b/leaf-server/paper-patches/features/0004-Purpur-Server-Paper-Changes.patch similarity index 100% rename from leaf-server/paper-patches/features/0005-Purpur-Server-Paper-Changes.patch rename to leaf-server/paper-patches/features/0004-Purpur-Server-Paper-Changes.patch diff --git a/leaf-server/paper-patches/features/0006-Fix-Pufferfish-and-Purpur-patches.patch b/leaf-server/paper-patches/features/0005-Fix-Pufferfish-and-Purpur-patches.patch similarity index 100% rename from leaf-server/paper-patches/features/0006-Fix-Pufferfish-and-Purpur-patches.patch rename to leaf-server/paper-patches/features/0005-Fix-Pufferfish-and-Purpur-patches.patch diff --git a/leaf-server/paper-patches/features/0007-Remove-Timings.patch b/leaf-server/paper-patches/features/0006-Remove-Timings.patch similarity index 100% rename from leaf-server/paper-patches/features/0007-Remove-Timings.patch rename to leaf-server/paper-patches/features/0006-Remove-Timings.patch diff --git a/leaf-server/paper-patches/features/0008-KeYi-Player-Skull-API.patch b/leaf-server/paper-patches/features/0007-KeYi-Player-Skull-API.patch similarity index 100% rename from leaf-server/paper-patches/features/0008-KeYi-Player-Skull-API.patch rename to leaf-server/paper-patches/features/0007-KeYi-Player-Skull-API.patch diff --git a/leaf-server/paper-patches/features/0009-Slice-Smooth-Teleports.patch b/leaf-server/paper-patches/features/0008-Slice-Smooth-Teleports.patch similarity index 100% rename from leaf-server/paper-patches/features/0009-Slice-Smooth-Teleports.patch rename to leaf-server/paper-patches/features/0008-Slice-Smooth-Teleports.patch diff --git a/leaf-server/paper-patches/features/0010-Leaves-Protocol-Core.patch b/leaf-server/paper-patches/features/0009-Leaves-Protocol-Core.patch similarity index 100% rename from leaf-server/paper-patches/features/0010-Leaves-Protocol-Core.patch rename to leaf-server/paper-patches/features/0009-Leaves-Protocol-Core.patch diff --git a/leaf-server/paper-patches/features/0011-Leaves-Replay-Mod-API.patch b/leaf-server/paper-patches/features/0010-Leaves-Replay-Mod-API.patch similarity index 100% rename from leaf-server/paper-patches/features/0011-Leaves-Replay-Mod-API.patch rename to leaf-server/paper-patches/features/0010-Leaves-Replay-Mod-API.patch diff --git a/leaf-server/paper-patches/features/0012-Skip-event-if-no-listeners.patch b/leaf-server/paper-patches/features/0011-Skip-event-if-no-listeners.patch similarity index 100% rename from leaf-server/paper-patches/features/0012-Skip-event-if-no-listeners.patch rename to leaf-server/paper-patches/features/0011-Skip-event-if-no-listeners.patch diff --git a/leaf-server/paper-patches/features/0013-SparklyPaper-Skip-EntityScheduler-s-executeTick-chec.patch b/leaf-server/paper-patches/features/0012-SparklyPaper-Skip-EntityScheduler-s-executeTick-chec.patch similarity index 100% rename from leaf-server/paper-patches/features/0013-SparklyPaper-Skip-EntityScheduler-s-executeTick-chec.patch rename to leaf-server/paper-patches/features/0012-SparklyPaper-Skip-EntityScheduler-s-executeTick-chec.patch diff --git a/leaf-server/paper-patches/features/0014-SparklyPaper-Optimize-canSee-checks.patch b/leaf-server/paper-patches/features/0013-SparklyPaper-Optimize-canSee-checks.patch similarity index 100% rename from leaf-server/paper-patches/features/0014-SparklyPaper-Optimize-canSee-checks.patch rename to leaf-server/paper-patches/features/0013-SparklyPaper-Optimize-canSee-checks.patch diff --git a/leaf-server/paper-patches/features/0015-Including-5s-in-getTPS.patch b/leaf-server/paper-patches/features/0014-Including-5s-in-getTPS.patch similarity index 100% rename from leaf-server/paper-patches/features/0015-Including-5s-in-getTPS.patch rename to leaf-server/paper-patches/features/0014-Including-5s-in-getTPS.patch diff --git a/leaf-server/paper-patches/features/0016-Don-t-throw-exception-on-missing-ResourceKey-value.patch b/leaf-server/paper-patches/features/0015-Don-t-throw-exception-on-missing-ResourceKey-value.patch similarity index 100% rename from leaf-server/paper-patches/features/0016-Don-t-throw-exception-on-missing-ResourceKey-value.patch rename to leaf-server/paper-patches/features/0015-Don-t-throw-exception-on-missing-ResourceKey-value.patch diff --git a/leaf-server/paper-patches/features/0017-Virtual-Thread-for-async-scheduler.patch b/leaf-server/paper-patches/features/0016-Virtual-Thread-for-async-scheduler.patch similarity index 100% rename from leaf-server/paper-patches/features/0017-Virtual-Thread-for-async-scheduler.patch rename to leaf-server/paper-patches/features/0016-Virtual-Thread-for-async-scheduler.patch diff --git a/leaf-server/paper-patches/features/0018-Mirai-Configurable-chat-message-signatures.patch b/leaf-server/paper-patches/features/0017-Mirai-Configurable-chat-message-signatures.patch similarity index 100% rename from leaf-server/paper-patches/features/0018-Mirai-Configurable-chat-message-signatures.patch rename to leaf-server/paper-patches/features/0017-Mirai-Configurable-chat-message-signatures.patch diff --git a/leaf-server/paper-patches/features/0019-Matter-Secure-Seed.patch b/leaf-server/paper-patches/features/0018-Matter-Secure-Seed.patch similarity index 100% rename from leaf-server/paper-patches/features/0019-Matter-Secure-Seed.patch rename to leaf-server/paper-patches/features/0018-Matter-Secure-Seed.patch diff --git a/leaf-server/paper-patches/features/0020-Faster-random-generator.patch b/leaf-server/paper-patches/features/0019-Faster-random-generator.patch similarity index 100% rename from leaf-server/paper-patches/features/0020-Faster-random-generator.patch rename to leaf-server/paper-patches/features/0019-Faster-random-generator.patch diff --git a/leaf-server/paper-patches/features/0021-Configurable-unknown-command-message.patch b/leaf-server/paper-patches/features/0020-Configurable-unknown-command-message.patch similarity index 100% rename from leaf-server/paper-patches/features/0021-Configurable-unknown-command-message.patch rename to leaf-server/paper-patches/features/0020-Configurable-unknown-command-message.patch diff --git a/leaf-server/paper-patches/features/0022-Replace-world-map-with-optimized-collection.patch b/leaf-server/paper-patches/features/0021-Replace-world-map-with-optimized-collection.patch similarity index 100% rename from leaf-server/paper-patches/features/0022-Replace-world-map-with-optimized-collection.patch rename to leaf-server/paper-patches/features/0021-Replace-world-map-with-optimized-collection.patch diff --git a/leaf-server/paper-patches/features/0023-Cache-CraftEntityType-minecraftToBukkit-convert.patch b/leaf-server/paper-patches/features/0022-Cache-CraftEntityType-minecraftToBukkit-convert.patch similarity index 100% rename from leaf-server/paper-patches/features/0023-Cache-CraftEntityType-minecraftToBukkit-convert.patch rename to leaf-server/paper-patches/features/0022-Cache-CraftEntityType-minecraftToBukkit-convert.patch diff --git a/leaf-server/paper-patches/features/0024-Multithreaded-Tracker.patch b/leaf-server/paper-patches/features/0023-Multithreaded-Tracker.patch similarity index 100% rename from leaf-server/paper-patches/features/0024-Multithreaded-Tracker.patch rename to leaf-server/paper-patches/features/0023-Multithreaded-Tracker.patch diff --git a/leaf-server/paper-patches/features/0025-Asynchronous-locator.patch b/leaf-server/paper-patches/features/0024-Asynchronous-locator.patch similarity index 100% rename from leaf-server/paper-patches/features/0025-Asynchronous-locator.patch rename to leaf-server/paper-patches/features/0024-Asynchronous-locator.patch diff --git a/leaf-server/paper-patches/features/0026-EMC-Don-t-use-snapshots-for-acquiring-blockstate.patch b/leaf-server/paper-patches/features/0025-EMC-Don-t-use-snapshots-for-acquiring-blockstate.patch similarity index 100% rename from leaf-server/paper-patches/features/0026-EMC-Don-t-use-snapshots-for-acquiring-blockstate.patch rename to leaf-server/paper-patches/features/0025-EMC-Don-t-use-snapshots-for-acquiring-blockstate.patch diff --git a/leaf-server/paper-patches/features/0027-Faster-CraftServer-getworlds-list-creation.patch b/leaf-server/paper-patches/features/0026-Faster-CraftServer-getworlds-list-creation.patch similarity index 100% rename from leaf-server/paper-patches/features/0027-Faster-CraftServer-getworlds-list-creation.patch rename to leaf-server/paper-patches/features/0026-Faster-CraftServer-getworlds-list-creation.patch diff --git a/leaf-server/paper-patches/features/0028-Cache-chunk-key.patch b/leaf-server/paper-patches/features/0027-Cache-chunk-key.patch similarity index 100% rename from leaf-server/paper-patches/features/0028-Cache-chunk-key.patch rename to leaf-server/paper-patches/features/0027-Cache-chunk-key.patch diff --git a/leaf-server/paper-patches/features/0029-Async-structure-locate-api.patch b/leaf-server/paper-patches/features/0028-Async-structure-locate-api.patch similarity index 100% rename from leaf-server/paper-patches/features/0029-Async-structure-locate-api.patch rename to leaf-server/paper-patches/features/0028-Async-structure-locate-api.patch diff --git a/leaf-server/paper-patches/features/0030-PlayerInventoryOverflowEvent.patch b/leaf-server/paper-patches/features/0029-PlayerInventoryOverflowEvent.patch similarity index 100% rename from leaf-server/paper-patches/features/0030-PlayerInventoryOverflowEvent.patch rename to leaf-server/paper-patches/features/0029-PlayerInventoryOverflowEvent.patch diff --git a/leaf-server/paper-patches/features/0031-SparklyPaper-Parallel-world-ticking.patch b/leaf-server/paper-patches/features/0030-SparklyPaper-Parallel-world-ticking.patch similarity index 100% rename from leaf-server/paper-patches/features/0031-SparklyPaper-Parallel-world-ticking.patch rename to leaf-server/paper-patches/features/0030-SparklyPaper-Parallel-world-ticking.patch diff --git a/leaf-server/paper-patches/features/0032-Paper-PR-Throttle-failed-spawn-attempts.patch b/leaf-server/paper-patches/features/0031-Paper-PR-Throttle-failed-spawn-attempts.patch similarity index 100% rename from leaf-server/paper-patches/features/0032-Paper-PR-Throttle-failed-spawn-attempts.patch rename to leaf-server/paper-patches/features/0031-Paper-PR-Throttle-failed-spawn-attempts.patch diff --git a/leaf-server/paper-patches/features/0033-Async-playerdata-saving.patch b/leaf-server/paper-patches/features/0032-Async-playerdata-saving.patch similarity index 100% rename from leaf-server/paper-patches/features/0033-Async-playerdata-saving.patch rename to leaf-server/paper-patches/features/0032-Async-playerdata-saving.patch diff --git a/leaf-server/paper-patches/features/0034-PaperPR-Fix-save-load-NaN-Entity-Motion.patch b/leaf-server/paper-patches/features/0033-PaperPR-Fix-save-load-NaN-Entity-Motion.patch similarity index 100% rename from leaf-server/paper-patches/features/0034-PaperPR-Fix-save-load-NaN-Entity-Motion.patch rename to leaf-server/paper-patches/features/0033-PaperPR-Fix-save-load-NaN-Entity-Motion.patch diff --git a/leaf-server/paper-patches/features/0035-PaperPR-Fix-unnecessary-map-data-saves.patch b/leaf-server/paper-patches/features/0034-PaperPR-Fix-unnecessary-map-data-saves.patch similarity index 100% rename from leaf-server/paper-patches/features/0035-PaperPR-Fix-unnecessary-map-data-saves.patch rename to leaf-server/paper-patches/features/0034-PaperPR-Fix-unnecessary-map-data-saves.patch diff --git a/leaf-server/paper-patches/features/0036-Async-chunk-send.patch b/leaf-server/paper-patches/features/0035-Async-chunk-send.patch similarity index 100% rename from leaf-server/paper-patches/features/0036-Async-chunk-send.patch rename to leaf-server/paper-patches/features/0035-Async-chunk-send.patch diff --git a/leaf-server/paper-patches/features/0037-Optimise-player-movement-checks.patch b/leaf-server/paper-patches/features/0036-Optimise-player-movement-checks.patch similarity index 100% rename from leaf-server/paper-patches/features/0037-Optimise-player-movement-checks.patch rename to leaf-server/paper-patches/features/0036-Optimise-player-movement-checks.patch diff --git a/leaf-server/paper-patches/features/0038-optimise-ReferenceList.patch b/leaf-server/paper-patches/features/0037-optimise-ReferenceList.patch similarity index 100% rename from leaf-server/paper-patches/features/0038-optimise-ReferenceList.patch rename to leaf-server/paper-patches/features/0037-optimise-ReferenceList.patch diff --git a/leaf-server/paper-patches/features/0039-cache-getBiome.patch b/leaf-server/paper-patches/features/0038-cache-getBiome.patch similarity index 100% rename from leaf-server/paper-patches/features/0039-cache-getBiome.patch rename to leaf-server/paper-patches/features/0038-cache-getBiome.patch diff --git a/leaf-server/paper-patches/features/0040-Paper-Optimise-CraftWorld-getLoadedChunks.patch b/leaf-server/paper-patches/features/0039-Paper-Optimise-CraftWorld-getLoadedChunks.patch similarity index 100% rename from leaf-server/paper-patches/features/0040-Paper-Optimise-CraftWorld-getLoadedChunks.patch rename to leaf-server/paper-patches/features/0039-Paper-Optimise-CraftWorld-getLoadedChunks.patch diff --git a/leaf-server/paper-patches/features/0041-Paper-Update-CraftWorld-getForceLoadedChunks-to-avoi.patch b/leaf-server/paper-patches/features/0040-Paper-Update-CraftWorld-getForceLoadedChunks-to-avoi.patch similarity index 100% rename from leaf-server/paper-patches/features/0041-Paper-Update-CraftWorld-getForceLoadedChunks-to-avoi.patch rename to leaf-server/paper-patches/features/0040-Paper-Update-CraftWorld-getForceLoadedChunks-to-avoi.patch diff --git a/leaf-server/paper-patches/features/0042-dump-pwt-thread.patch b/leaf-server/paper-patches/features/0041-dump-pwt-thread.patch similarity index 100% rename from leaf-server/paper-patches/features/0042-dump-pwt-thread.patch rename to leaf-server/paper-patches/features/0041-dump-pwt-thread.patch diff --git a/leaf-server/paper-patches/features/0043-Paw-optimization.patch b/leaf-server/paper-patches/features/0042-Paw-optimization.patch similarity index 100% rename from leaf-server/paper-patches/features/0043-Paw-optimization.patch rename to leaf-server/paper-patches/features/0042-Paw-optimization.patch diff --git a/leaf-server/paper-patches/features/0044-Toggleable-async-catcher.patch b/leaf-server/paper-patches/features/0043-Toggleable-async-catcher.patch similarity index 100% rename from leaf-server/paper-patches/features/0044-Toggleable-async-catcher.patch rename to leaf-server/paper-patches/features/0043-Toggleable-async-catcher.patch diff --git a/leaf-server/paper-patches/features/0045-cache-profile-data.patch b/leaf-server/paper-patches/features/0044-cache-profile-data.patch similarity index 100% rename from leaf-server/paper-patches/features/0045-cache-profile-data.patch rename to leaf-server/paper-patches/features/0044-cache-profile-data.patch