diff --git a/paper-server/patches/unapplied/0016-Fix-entity-tracker-desync-when-new-players-are-added.patch b/paper-server/patches/features/0016-Fix-entity-tracker-desync-when-new-players-are-added.patch similarity index 86% rename from paper-server/patches/unapplied/0016-Fix-entity-tracker-desync-when-new-players-are-added.patch rename to paper-server/patches/features/0016-Fix-entity-tracker-desync-when-new-players-are-added.patch index 4a6adb3c0a..6b36acef61 100644 --- a/paper-server/patches/unapplied/0016-Fix-entity-tracker-desync-when-new-players-are-added.patch +++ b/paper-server/patches/features/0016-Fix-entity-tracker-desync-when-new-players-are-added.patch @@ -48,10 +48,10 @@ index db31989ebe3d7021cfd2311439e9a00f819b0841..1373977b339405ef59bb3ea03d195285 serverEntity.getLastSentYRot(), entity.getType(), diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java -index 1463c31ba980ab0eb2174e3e891d1423a505e9dc..886340232b58afd59caa6df29e211589a7781070 100644 +index 52d05c6b0fbb7719aaa67748050cb2d88dcbf41b..86ba02916c4a1c1311eeca5b1fb10a46626ba9ab 100644 --- a/net/minecraft/server/level/ChunkMap.java +++ b/net/minecraft/server/level/ChunkMap.java -@@ -1278,6 +1278,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1275,6 +1275,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider this.serverEntity.addPairing(player); } // Paper end - entity tracking events @@ -60,7 +60,7 @@ index 1463c31ba980ab0eb2174e3e891d1423a505e9dc..886340232b58afd59caa6df29e211589 } else if (this.seenBy.remove(player.connection)) { this.serverEntity.removePairing(player); diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java -index a1ae77b70f69852d9e4332bf1cb3409c33b21de0..b118e91f1e0b5a8b8c0b2a4a32faabc5a34a5954 100644 +index 3d5a8163a7dd78a195b77c4aaebdee2dc3dee64b..e96d4dee14c05f2fa329bfb1588ec795d4e3d730 100644 --- a/net/minecraft/server/level/ServerEntity.java +++ b/net/minecraft/server/level/ServerEntity.java @@ -103,6 +103,13 @@ public class ServerEntity { @@ -90,12 +90,12 @@ index a1ae77b70f69852d9e4332bf1cb3409c33b21de0..b118e91f1e0b5a8b8c0b2a4a32faabc5 long l1 = this.positionCodec.encodeY(vec3); long l2 = this.positionCodec.encodeZ(vec3); boolean flag5 = l < -32768L || l > 32767L || l1 < -32768L || l1 > 32767L || l2 < -32768L || l2 > 32767L; -- if (flag5 || this.teleportDelay > 400 || this.wasRiding || this.wasOnGround != this.entity.onGround()) { -+ if (this.forceStateResync || flag5 || this.teleportDelay > 400 || this.wasRiding || this.wasOnGround != this.entity.onGround()) { // Paper - fix desync when a player is added to the tracker - this.wasOnGround = this.entity.onGround(); - this.teleportDelay = 0; - packet = ClientboundEntityPositionSyncPacket.of(this.entity); -@@ -241,6 +248,7 @@ public class ServerEntity { +- if (this.entity.getRequiresPrecisePosition() ++ if (this.forceStateResync || this.entity.getRequiresPrecisePosition() // Paper - fix desync when a player is added to the tracker + || flag5 + || this.teleportDelay > 400 + || this.wasRiding +@@ -245,6 +252,7 @@ public class ServerEntity { } this.entity.hasImpulse = false; diff --git a/paper-server/patches/unapplied/0017-Eigencraft-redstone-implementation.patch b/paper-server/patches/features/0017-Eigencraft-redstone-implementation.patch similarity index 100% rename from paper-server/patches/unapplied/0017-Eigencraft-redstone-implementation.patch rename to paper-server/patches/features/0017-Eigencraft-redstone-implementation.patch diff --git a/paper-server/patches/unapplied/0018-Add-Alternate-Current-redstone-implementation.patch b/paper-server/patches/features/0018-Add-Alternate-Current-redstone-implementation.patch similarity index 99% rename from paper-server/patches/unapplied/0018-Add-Alternate-Current-redstone-implementation.patch rename to paper-server/patches/features/0018-Add-Alternate-Current-redstone-implementation.patch index c505fb79b8..55dac96773 100644 --- a/paper-server/patches/unapplied/0018-Add-Alternate-Current-redstone-implementation.patch +++ b/paper-server/patches/features/0018-Add-Alternate-Current-redstone-implementation.patch @@ -2326,10 +2326,10 @@ index 0000000000000000000000000000000000000000..298076a0db4e6ee6e4775ac43bf749d9 + } +} diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index 8afe96bfdc37e57129f1bb4af5b6d5cc22c11aee..32db2b9e375c12cbf7abab69cc01e8ac2c7c3b6e 100644 +index 4ff31ae3af6840fbce2f76f5db075d0a2e9535d8..cb8f47ec146d45ed223094e5ee9237cdc5a183be 100644 --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java -@@ -210,6 +210,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -213,6 +213,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe public final java.util.UUID uuid; public boolean hasPhysicsEvent = true; // Paper - BlockPhysicsEvent public boolean hasEntityMoveEvent; // Paper - Add EntityMoveEvent @@ -2337,7 +2337,7 @@ index 8afe96bfdc37e57129f1bb4af5b6d5cc22c11aee..32db2b9e375c12cbf7abab69cc01e8ac @Override public @Nullable LevelChunk getChunkIfLoaded(int x, int z) { -@@ -2552,6 +2553,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -2592,6 +2593,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe return this.chunkSource.getGenerator().getSeaLevel(); } @@ -2352,10 +2352,10 @@ index 8afe96bfdc37e57129f1bb4af5b6d5cc22c11aee..32db2b9e375c12cbf7abab69cc01e8ac @Override public void onCreated(Entity entity) { diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java -index eb4d03cfdb34243901cfba832d35559d5be9e876..013ed7dbe2309f562f63e66203179a90566e8115 100644 +index b799d9cc54c45920a7c48d5302454c9cec3ab7c2..e4b9a564aad3d9b673808caa18265b06592ceab8 100644 --- a/net/minecraft/world/level/Level.java +++ b/net/minecraft/world/level/Level.java -@@ -2096,6 +2096,17 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl +@@ -2100,6 +2100,17 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl return 0; } diff --git a/paper-server/patches/unapplied/0019-Improve-exact-choice-recipe-ingredients.patch b/paper-server/patches/features/0019-Improve-exact-choice-recipe-ingredients.patch similarity index 99% rename from paper-server/patches/unapplied/0019-Improve-exact-choice-recipe-ingredients.patch rename to paper-server/patches/features/0019-Improve-exact-choice-recipe-ingredients.patch index 733a8ab4db..d78ceed249 100644 --- a/paper-server/patches/unapplied/0019-Improve-exact-choice-recipe-ingredients.patch +++ b/paper-server/patches/features/0019-Improve-exact-choice-recipe-ingredients.patch @@ -204,10 +204,10 @@ index 6d3e3ec045d5b15a435f7217369968b33e082724..b7a3758af337270737041f84d10eb437 int i = this.inventory.findSlotMatchingCraftingIngredient(item, item1); if (i == -1) { diff --git a/net/minecraft/world/entity/player/Inventory.java b/net/minecraft/world/entity/player/Inventory.java -index e25e0bd410f8822cb9a1118b39a786f44aabef7b..d9cb4f0ed0c4f63362c837aeef3c4194911455c9 100644 +index 46408ccee787b45e7957c12bfe426cb391f6e173..a6bb436dc80daf6901dc027a6011ead4b3ed27e2 100644 --- a/net/minecraft/world/entity/player/Inventory.java +++ b/net/minecraft/world/entity/player/Inventory.java -@@ -234,12 +234,12 @@ public class Inventory implements Container, Nameable { +@@ -251,12 +251,12 @@ public class Inventory implements Container, Nameable { return !stack.isDamaged() && !stack.isEnchanted() && !stack.has(DataComponents.CUSTOM_NAME); } diff --git a/paper-server/patches/unapplied/0020-Only-write-chunk-data-to-disk-if-it-serializes-witho.patch b/paper-server/patches/features/0020-Only-write-chunk-data-to-disk-if-it-serializes-witho.patch similarity index 100% rename from paper-server/patches/unapplied/0020-Only-write-chunk-data-to-disk-if-it-serializes-witho.patch rename to paper-server/patches/features/0020-Only-write-chunk-data-to-disk-if-it-serializes-witho.patch diff --git a/paper-server/patches/unapplied/0021-Entity-load-save-limit-per-chunk.patch b/paper-server/patches/features/0021-Entity-load-save-limit-per-chunk.patch similarity index 52% rename from paper-server/patches/unapplied/0021-Entity-load-save-limit-per-chunk.patch rename to paper-server/patches/features/0021-Entity-load-save-limit-per-chunk.patch index 85d8aa9cf2..02d3198fdf 100644 --- a/paper-server/patches/unapplied/0021-Entity-load-save-limit-per-chunk.patch +++ b/paper-server/patches/features/0021-Entity-load-save-limit-per-chunk.patch @@ -32,50 +32,48 @@ index 1c82dcd38f789707e15e8cbec72ef9cdc7efdf56..ba20e87d2105ce53cdaf4049de2388d0 if (entity.save(compoundTag)) { entitiesTag.add(compoundTag); diff --git a/net/minecraft/world/entity/EntityType.java b/net/minecraft/world/entity/EntityType.java -index 4c57990c94721dd0973477669e1dadfab5f16404..8af02ed823da098a5592ef195c9fe8ed8f245b53 100644 +index 98586dfc562cf6909df0f4bfa1c19e35b3172abe..f92adee1c187561d3790a5a5c8c81f5e1543ed97 100644 --- a/net/minecraft/world/entity/EntityType.java +++ b/net/minecraft/world/entity/EntityType.java -@@ -1430,9 +1430,20 @@ public class EntityType implements FeatureElement, EntityTypeT +@@ -1448,7 +1448,18 @@ public class EntityType implements FeatureElement, EntityTypeT } - public static Stream loadEntitiesRecursive(List entityTags, Level level, EntitySpawnReason spawnReason) { + public static Stream loadEntitiesRecursive(ValueInput.ValueInputList input, Level level, EntitySpawnReason spawnReason) { + final java.util.Map, Integer> loadedEntityCounts = new java.util.HashMap<>(); // Paper - Entity load/save limit per chunk - return entityTags.stream() - .flatMap(tag -> tag.asCompound().stream()) - .mapMulti((compoundTag, consumer) -> loadEntityRecursive(compoundTag, level, spawnReason, entity -> { -+ // Paper start - Entity load/save limit per chunk -+ final EntityType entityType = entity.getType(); -+ final int saveLimit = level.paperConfig().chunks.entityPerChunkSaveLimit.getOrDefault(entityType, -1); -+ if (saveLimit > -1) { -+ if (loadedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) { -+ return null; -+ } -+ loadedEntityCounts.merge(entityType, 1, Integer::sum); + return input.stream().mapMulti((valueInput, consumer) -> loadEntityRecursive(valueInput, level, spawnReason, entity -> { ++ // Paper start - Entity load/save limit per chunk ++ final EntityType entityType = entity.getType(); ++ final int saveLimit = level.paperConfig().chunks.entityPerChunkSaveLimit.getOrDefault(entityType, -1); ++ if (saveLimit > -1) { ++ if (loadedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) { ++ return null; + } -+ // Paper end - Entity load/save limit per chunk - consumer.accept(entity); - return entity; - })); ++ loadedEntityCounts.merge(entityType, 1, Integer::sum); ++ } ++ // Paper end - Entity load/save limit per chunk + consumer.accept(entity); + return entity; + })); diff --git a/net/minecraft/world/level/chunk/storage/EntityStorage.java b/net/minecraft/world/level/chunk/storage/EntityStorage.java -index bcc2a4081fac07c4579c3aabfe4353743f8cd876..f9fb1380be9cbe960127c208c65c19f770e50b6d 100644 +index bf45cce4db77966d44d7a8d97673bb6631a6adaf..f1f8575a4b37114ced3cdb1d2ea33a36a2db44fd 100644 --- a/net/minecraft/world/level/chunk/storage/EntityStorage.java +++ b/net/minecraft/world/level/chunk/storage/EntityStorage.java -@@ -87,7 +87,18 @@ public class EntityStorage implements EntityPersistentStorage { - } +@@ -95,7 +95,18 @@ public class EntityStorage implements EntityPersistentStorage { } else { - ListTag listTag = new ListTag(); -+ final java.util.Map, Integer> savedEntityCounts = new java.util.HashMap<>(); // Paper - Entity load/save limit per chunk - entities.getEntities().forEach(entity -> { -+ // Paper start - Entity load/save limit per chunk -+ final EntityType entityType = entity.getType(); -+ final int saveLimit = this.level.paperConfig().chunks.entityPerChunkSaveLimit.getOrDefault(entityType, -1); -+ if (saveLimit > -1) { -+ if (savedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) { -+ return; + try (ProblemReporter.ScopedCollector scopedCollector = new ProblemReporter.ScopedCollector(ChunkAccess.problemPath(pos), LOGGER)) { + ListTag listTag = new ListTag(); ++ final java.util.Map, Integer> savedEntityCounts = new java.util.HashMap<>(); // Paper - Entity load/save limit per chunk + entities.getEntities().forEach(entity -> { ++ // Paper start - Entity load/save limit per chunk ++ final EntityType entityType = entity.getType(); ++ final int saveLimit = this.level.paperConfig().chunks.entityPerChunkSaveLimit.getOrDefault(entityType, -1); ++ if (saveLimit > -1) { ++ if (savedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) { ++ return; ++ } ++ savedEntityCounts.merge(entityType, 1, Integer::sum); + } -+ savedEntityCounts.merge(entityType, 1, Integer::sum); -+ } -+ // Paper end - Entity load/save limit per chunk - CompoundTag compoundTag1 = new CompoundTag(); - if (entity.save(compoundTag1)) { - listTag.add(compoundTag1); ++ // Paper end - Entity load/save limit per chunk + TagValueOutput tagValueOutput = TagValueOutput.createWithContext(scopedCollector.forChild(entity.problemPath()), entity.registryAccess()); + if (entity.save(tagValueOutput)) { + CompoundTag compoundTag1 = tagValueOutput.buildResult(); diff --git a/paper-server/patches/unapplied/0022-Attempt-to-recalculate-regionfile-header-if-it-is-co.patch b/paper-server/patches/features/0022-Attempt-to-recalculate-regionfile-header-if-it-is-co.patch similarity index 99% rename from paper-server/patches/unapplied/0022-Attempt-to-recalculate-regionfile-header-if-it-is-co.patch rename to paper-server/patches/features/0022-Attempt-to-recalculate-regionfile-header-if-it-is-co.patch index e526626af1..c24795f73f 100644 --- a/paper-server/patches/unapplied/0022-Attempt-to-recalculate-regionfile-header-if-it-is-co.patch +++ b/paper-server/patches/features/0022-Attempt-to-recalculate-regionfile-header-if-it-is-co.patch @@ -778,10 +778,10 @@ index 1649119f45d970a9bf1683d676c47ecfc18ad047..cc544f3199cd6af29e50362923d06517 public static final RegionFileVersion VERSION_GZIP = register( new RegionFileVersion( diff --git a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java -index 03d1527073cf827fc3e191915fe5f7f064e36c3b..749096358fccbd5d1d13801092255c51096eb001 100644 +index 2e6263d8b466e0f61bc72eb818044734b7d0ee6d..e04d3479383cd480cf35ed7ac3c82e7f6fb69e28 100644 --- a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java +++ b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java -@@ -122,6 +122,18 @@ public record SerializableChunkData( +@@ -124,6 +124,18 @@ public record SerializableChunkData( } } // Paper end - guard against serializing mismatching coordinates @@ -799,8 +799,8 @@ index 03d1527073cf827fc3e191915fe5f7f064e36c3b..749096358fccbd5d1d13801092255c51 + // Paper end - Attempt to recalculate regionfile header if it is corrupt // Paper start - Do not let the server load chunks from newer versions - private static final int CURRENT_DATA_VERSION = net.minecraft.SharedConstants.getCurrentVersion().getDataVersion().getVersion(); -@@ -571,7 +583,7 @@ public record SerializableChunkData( + private static final int CURRENT_DATA_VERSION = net.minecraft.SharedConstants.getCurrentVersion().dataVersion().version(); +@@ -573,7 +585,7 @@ public record SerializableChunkData( compoundTag.putInt("xPos", this.chunkPos.x); compoundTag.putInt("yPos", this.minSectionY); compoundTag.putInt("zPos", this.chunkPos.z); diff --git a/paper-server/patches/unapplied/0023-Incremental-chunk-and-player-saving.patch b/paper-server/patches/features/0023-Incremental-chunk-and-player-saving.patch similarity index 89% rename from paper-server/patches/unapplied/0023-Incremental-chunk-and-player-saving.patch rename to paper-server/patches/features/0023-Incremental-chunk-and-player-saving.patch index ae7d01be8e..8823ad8a72 100644 --- a/paper-server/patches/unapplied/0023-Incremental-chunk-and-player-saving.patch +++ b/paper-server/patches/features/0023-Incremental-chunk-and-player-saving.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Incremental chunk and player saving diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 094ef7f54ad71795a2d8c2a8d03a32bef6ff2164..79bc1b7d9f640d2322814177eb3e921da8671e87 100644 +index 28e07984e22514d135a27fe13087e8d185813aad..f405195d206cfb2ad9598c1861a884e5b1f1fd50 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java -@@ -952,7 +952,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements AutoCloseable, ca.spottedleaf.moonr diff --git a/paper-server/patches/unapplied/0025-Optional-per-player-mob-spawns.patch b/paper-server/patches/features/0025-Optional-per-player-mob-spawns.patch similarity index 97% rename from paper-server/patches/unapplied/0025-Optional-per-player-mob-spawns.patch rename to paper-server/patches/features/0025-Optional-per-player-mob-spawns.patch index b521f05eb7..93df896305 100644 --- a/paper-server/patches/unapplied/0025-Optional-per-player-mob-spawns.patch +++ b/paper-server/patches/features/0025-Optional-per-player-mob-spawns.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Optional per player mob spawns diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java -index 886340232b58afd59caa6df29e211589a7781070..4f4bcc4bbfcc9b191d12d667b8fc1e644a9d5957 100644 +index 86ba02916c4a1c1311eeca5b1fb10a46626ba9ab..b40b94c49dc0997654aca0a1a0dffe482cd14eac 100644 --- a/net/minecraft/server/level/ChunkMap.java +++ b/net/minecraft/server/level/ChunkMap.java @@ -243,11 +243,29 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @@ -43,7 +43,7 @@ index 886340232b58afd59caa6df29e211589a7781070..4f4bcc4bbfcc9b191d12d667b8fc1e64 protected ChunkGenerator generator() { return this.worldGenContext.generator(); diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java -index 5d63bf024cbcbd2f627c64fee77553c9a512bd15..f863377a807b672f49f7140688f378eca2cf650b 100644 +index 8e9988130d9b912e5b858cd7792bdcefdeb66ada..25d74f866546362a17505b5d4abf85382c0df20c 100644 --- a/net/minecraft/server/level/ServerChunkCache.java +++ b/net/minecraft/server/level/ServerChunkCache.java @@ -541,9 +541,18 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon @@ -78,10 +78,10 @@ index 5d63bf024cbcbd2f627c64fee77553c9a512bd15..f863377a807b672f49f7140688f378ec profiler.popPush("tickSpawningChunks"); diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index 4b2801749328f250ce5735fbe7f6941a6bede01a..af04fcdba1e57b4eac678235b56ad3e1c70169b7 100644 +index b70929df38389d789dad46c0a6d94f6c08aa7eba..e96bb37bb7a7340a7ee33046820652ecd4accc53 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java -@@ -395,6 +395,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -406,6 +406,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc public boolean queueHealthUpdatePacket; public @Nullable net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket; // Paper end - cancellable death event diff --git a/paper-server/patches/unapplied/0026-Improve-cancelling-PreCreatureSpawnEvent-with-per-pl.patch b/paper-server/patches/features/0026-Improve-cancelling-PreCreatureSpawnEvent-with-per-pl.patch similarity index 93% rename from paper-server/patches/unapplied/0026-Improve-cancelling-PreCreatureSpawnEvent-with-per-pl.patch rename to paper-server/patches/features/0026-Improve-cancelling-PreCreatureSpawnEvent-with-per-pl.patch index 0f67c9da6d..7a941a9142 100644 --- a/paper-server/patches/unapplied/0026-Improve-cancelling-PreCreatureSpawnEvent-with-per-pl.patch +++ b/paper-server/patches/features/0026-Improve-cancelling-PreCreatureSpawnEvent-with-per-pl.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Improve cancelling PreCreatureSpawnEvent with per player mob diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java -index 4f4bcc4bbfcc9b191d12d667b8fc1e644a9d5957..0d8aefe8c886eaa4c33cbab53b0ad1c016f0531f 100644 +index b40b94c49dc0997654aca0a1a0dffe482cd14eac..b72000ce6bdcb97b787bfab79236f60bdb4aa2ee 100644 --- a/net/minecraft/server/level/ChunkMap.java +++ b/net/minecraft/server/level/ChunkMap.java @@ -262,8 +262,25 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @@ -37,7 +37,7 @@ index 4f4bcc4bbfcc9b191d12d667b8fc1e644a9d5957..0d8aefe8c886eaa4c33cbab53b0ad1c0 // Paper end - Optional per player mob spawns diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java -index f863377a807b672f49f7140688f378eca2cf650b..59e8a5e1b35c81883c9b1ca00c6e55d77584d8cc 100644 +index 25d74f866546362a17505b5d4abf85382c0df20c..7d78d270b7a076f595301acd9b3c6275e804496e 100644 --- a/net/minecraft/server/level/ServerChunkCache.java +++ b/net/minecraft/server/level/ServerChunkCache.java @@ -546,7 +546,17 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon @@ -60,10 +60,10 @@ index f863377a807b672f49f7140688f378eca2cf650b..59e8a5e1b35c81883c9b1ca00c6e55d7 spawnState = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, null, true); } else { diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index af04fcdba1e57b4eac678235b56ad3e1c70169b7..3781d9cc174b7aecacb9b9855d52c7b1ff05835c 100644 +index e96bb37bb7a7340a7ee33046820652ecd4accc53..53f038e1b5e7a13a08a0c925c8bd3f8a40868195 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java -@@ -399,6 +399,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -410,6 +410,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc public static final int MOBCATEGORY_TOTAL_ENUMS = net.minecraft.world.entity.MobCategory.values().length; public final int[] mobCounts = new int[MOBCATEGORY_TOTAL_ENUMS]; // Paper end - Optional per player mob spawns diff --git a/paper-server/patches/unapplied/0027-Optimize-Hoppers.patch b/paper-server/patches/features/0027-Optimize-Hoppers.patch similarity index 97% rename from paper-server/patches/unapplied/0027-Optimize-Hoppers.patch rename to paper-server/patches/features/0027-Optimize-Hoppers.patch index 6cf9616f88..f3f31f7976 100644 --- a/paper-server/patches/unapplied/0027-Optimize-Hoppers.patch +++ b/paper-server/patches/features/0027-Optimize-Hoppers.patch @@ -48,10 +48,10 @@ index 0000000000000000000000000000000000000000..24a2090e068ad3c0d08705050944abdf + } +} diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 79bc1b7d9f640d2322814177eb3e921da8671e87..f1373fd5fdebb9f4600ba7f32a5df6188de3a0e9 100644 +index f405195d206cfb2ad9598c1861a884e5b1f1fd50..9c4d690d1e4295ab4e73c9d5f34b5972969deda2 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java -@@ -1706,6 +1706,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0; // Paper - BlockPhysicsEvent serverLevel.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - Add EntityMoveEvent serverLevel.updateLagCompensationTick(); // Paper - lag compensation @@ -60,10 +60,10 @@ index 79bc1b7d9f640d2322814177eb3e921da8671e87..f1373fd5fdebb9f4600ba7f32a5df618 /* Drop global time updates if (this.tickCount % 20 == 0) { diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java -index 72cd623a1a3ce4b7a570a853456b067cd93736b1..ad7852a19ff73368ec9e7e63dcb7a064f78eefa0 100644 +index fc91f7f5ca01f1afe6ceb21f12d1a6ec6f5b68f9..cf283389d9263ba29720bf296a778be9eaf308a7 100644 --- a/net/minecraft/world/item/ItemStack.java +++ b/net/minecraft/world/item/ItemStack.java -@@ -831,10 +831,16 @@ public final class ItemStack implements DataComponentHolder { +@@ -811,10 +811,16 @@ public final class ItemStack implements DataComponentHolder { } public ItemStack copy() { @@ -83,10 +83,10 @@ index 72cd623a1a3ce4b7a570a853456b067cd93736b1..ad7852a19ff73368ec9e7e63dcb7a064 return itemStack; } diff --git a/net/minecraft/world/level/block/entity/BlockEntity.java b/net/minecraft/world/level/block/entity/BlockEntity.java -index 7783ff94e5183737d01c75c521b70b4fbd8c34a6..a1075c26d55cc01219acd94d0138f81aa9d34c48 100644 +index 275646a9f99f3c46bc81a23143c1960f2a6300b1..5986825d6a381eeb445dd424dd127864aa703163 100644 --- a/net/minecraft/world/level/block/entity/BlockEntity.java +++ b/net/minecraft/world/level/block/entity/BlockEntity.java -@@ -33,6 +33,7 @@ import net.minecraft.world.level.block.state.BlockState; +@@ -35,6 +35,7 @@ import net.minecraft.world.level.storage.ValueOutput; import org.slf4j.Logger; public abstract class BlockEntity { @@ -94,7 +94,7 @@ index 7783ff94e5183737d01c75c521b70b4fbd8c34a6..a1075c26d55cc01219acd94d0138f81a // CraftBukkit start - data containers private static final org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry(); public final org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer persistentDataContainer; -@@ -202,6 +203,7 @@ public abstract class BlockEntity { +@@ -227,6 +228,7 @@ public abstract class BlockEntity { public void setChanged() { if (this.level != null) { @@ -103,7 +103,7 @@ index 7783ff94e5183737d01c75c521b70b4fbd8c34a6..a1075c26d55cc01219acd94d0138f81a } } diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java -index 9a03934dd4d96184f37b9ff5661eb7bd76150464..15d4f60942c0cc612c1468b4c0fda886867a67cb 100644 +index 94d68fbb3d152b2fd43f989b728c5efabbf3c22c..800b7e78ae989868ed0b9e060c80dcd002759412 100644 --- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java +++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java @@ -143,18 +143,56 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen @@ -669,7 +669,7 @@ index 9a03934dd4d96184f37b9ff5661eb7bd76150464..15d4f60942c0cc612c1468b4c0fda886 @Override diff --git a/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java b/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java -index 1c98d003907feb16de8f26377fceedf728afe7fb..eed5f8f912544b79c8ed54dcdc5eeacb6dcfaccd 100644 +index d2cd30ed072a3d75c32b49a72920a9c26ce29922..dc59465d63e36bd50a48a8ea4197424556736552 100644 --- a/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java +++ b/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java @@ -54,7 +54,7 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc diff --git a/paper-server/patches/unapplied/0028-Flush-regionfiles-on-save-configuration-option.patch b/paper-server/patches/features/0028-Flush-regionfiles-on-save-configuration-option.patch similarity index 94% rename from paper-server/patches/unapplied/0028-Flush-regionfiles-on-save-configuration-option.patch rename to paper-server/patches/features/0028-Flush-regionfiles-on-save-configuration-option.patch index d7b455d7eb..7f331c737b 100644 --- a/paper-server/patches/unapplied/0028-Flush-regionfiles-on-save-configuration-option.patch +++ b/paper-server/patches/features/0028-Flush-regionfiles-on-save-configuration-option.patch @@ -14,7 +14,7 @@ timestamp so that fs watchers can detect when RegionFiles are modified. diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java b/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java -index 1acea58838f057ab87efd103cbecb6f5aeaef393..98fbc5c8044bd945d64569f13412a6e7e49a4e7f 100644 +index 09320f243a54f855b29d3833089b096975ca0075..709df35246fb328cda21679b53d44d9f96206cb3 100644 --- a/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java +++ b/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java @@ -1258,6 +1258,14 @@ public final class MoonriseRegionFileIO { diff --git a/paper-server/patches/unapplied/0029-Optimise-collision-checking-in-player-move-packet-ha.patch b/paper-server/patches/features/0029-Optimise-collision-checking-in-player-move-packet-ha.patch similarity index 71% rename from paper-server/patches/unapplied/0029-Optimise-collision-checking-in-player-move-packet-ha.patch rename to paper-server/patches/features/0029-Optimise-collision-checking-in-player-move-packet-ha.patch index b00faac56b..73a0f055bd 100644 --- a/paper-server/patches/unapplied/0029-Optimise-collision-checking-in-player-move-packet-ha.patch +++ b/paper-server/patches/features/0029-Optimise-collision-checking-in-player-move-packet-ha.patch @@ -6,53 +6,43 @@ Subject: [PATCH] Optimise collision checking in player move packet handling Move collision logic to just the hasNewCollision call instead of getCubes + hasNewCollision diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 0be741820fc7da2aac4f4aad85c4238ef49a0f57..337976c5c1ead87c36daa4e741b06e5a195b8302 100644 +index c9a0df5e5617e62703787942d067883ea537618b..aeb43902a09ef9c1b137964065780be3e87648f4 100644 --- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -555,7 +555,7 @@ public class ServerGamePacketListenerImpl - return; - } - -- boolean flag = serverLevel.noCollision(rootVehicle, rootVehicle.getBoundingBox().deflate(0.0625)); -+ final AABB oldBox = rootVehicle.getBoundingBox(); // Paper - copy from player movement packet - d3 = d - this.vehicleLastGoodX; // Paper - diff on change, used for checking large move vectors above - d4 = d1 - this.vehicleLastGoodY; // Paper - diff on change, used for checking large move vectors above - d5 = d2 - this.vehicleLastGoodZ; // Paper - diff on change, used for checking large move vectors above -@@ -565,6 +565,7 @@ public class ServerGamePacketListenerImpl +@@ -592,6 +592,7 @@ public class ServerGamePacketListenerImpl } rootVehicle.move(MoverType.PLAYER, new Vec3(d3, d4, d5)); + final boolean didCollide = toX != rootVehicle.getX() || toY != rootVehicle.getY() || toZ != rootVehicle.getZ(); // Paper - needed here as the difference in Y can be reset - also note: this is only a guess at whether collisions took place, floating point errors can make this true when it shouldn't be... - double verticalDelta = d4; // Paper - Decompile fix: lvt reassignment lost + double verticalDelta = d4; d3 = d - rootVehicle.getX(); d4 = d1 - rootVehicle.getY(); -@@ -576,14 +577,22 @@ public class ServerGamePacketListenerImpl +@@ -603,12 +604,21 @@ public class ServerGamePacketListenerImpl d7 = d3 * d3 + d4 * d4 + d5 * d5; - boolean flag2 = false; + boolean flag1 = false; if (d7 > org.spigotmc.SpigotConfig.movedWronglyThreshold) { // Spigot -- flag2 = true; -+ flag2 = true; // Paper - diff on change, this should be moved wrongly +- flag1 = true; ++ flag1 = true; // Paper - diff on change, this should be moved wrongly LOGGER.warn("{} (vehicle of {}) moved wrongly! {}", rootVehicle.getName().getString(), this.player.getName().getString(), Math.sqrt(d7)); } - rootVehicle.absSnapTo(d, d1, d2, f, f1); - this.player.absSnapTo(d, d1, d2, this.player.getYRot(), this.player.getXRot()); // CraftBukkit -- boolean flag3 = serverLevel.noCollision(rootVehicle, rootVehicle.getBoundingBox().deflate(0.0625)); -- if (flag && (flag2 || !flag3)) { +- if (flag1 && serverLevel.noCollision(rootVehicle, boundingBox) +- || this.isEntityCollidingWithAnythingNew(serverLevel, rootVehicle, boundingBox, d, d1, d2)) { + // Paper start - optimise out extra getCubes -+ boolean teleportBack = flag2; // violating this is always a fail ++ boolean teleportBack = flag1; + if (!teleportBack) { + // note: only call after setLocation, or else getBoundingBox is wrong + final AABB newBox = rootVehicle.getBoundingBox(); -+ if (didCollide || !oldBox.equals(newBox)) { -+ teleportBack = this.hasNewCollision(serverLevel, rootVehicle, oldBox, newBox); ++ if (didCollide || !boundingBox.equals(newBox)) { ++ teleportBack = this.hasNewCollision(serverLevel, rootVehicle, boundingBox, newBox); + } // else: no collision at all detected, why do we care? + } -+ if (teleportBack) { // Paper end - optimise out extra getCubes ++ if (teleportBack) { ++ // Paper end - optimise out extra getCubes rootVehicle.absSnapTo(x, y, z, f, f1); - this.player.absSnapTo(x, y, z, this.player.getYRot(), this.player.getXRot()); // CraftBukkit this.send(ClientboundMoveVehiclePacket.fromEntity(rootVehicle)); -@@ -661,9 +670,32 @@ public class ServerGamePacketListenerImpl + rootVehicle.removeLatestMovementRecording(); +@@ -687,9 +697,32 @@ public class ServerGamePacketListenerImpl } private boolean noBlocksAround(Entity entity) { @@ -88,7 +78,7 @@ index 0be741820fc7da2aac4f4aad85c4238ef49a0f57..337976c5c1ead87c36daa4e741b06e5a } @Override -@@ -1432,7 +1464,7 @@ public class ServerGamePacketListenerImpl +@@ -1465,7 +1498,7 @@ public class ServerGamePacketListenerImpl } } @@ -97,7 +87,7 @@ index 0be741820fc7da2aac4f4aad85c4238ef49a0f57..337976c5c1ead87c36daa4e741b06e5a d3 = d - this.lastGoodX; // Paper - diff on change, used for checking large move vectors above d4 = d1 - this.lastGoodY; // Paper - diff on change, used for checking large move vectors above d5 = d2 - this.lastGoodZ; // Paper - diff on change, used for checking large move vectors above -@@ -1471,6 +1503,7 @@ public class ServerGamePacketListenerImpl +@@ -1504,6 +1537,7 @@ public class ServerGamePacketListenerImpl boolean flag1 = this.player.verticalCollisionBelow; this.player.move(MoverType.PLAYER, new Vec3(d3, d4, d5)); this.player.onGround = packet.isOnGround(); // CraftBukkit - SPIGOT-5810, SPIGOT-5835, SPIGOT-6828: reset by this.player.move @@ -105,26 +95,26 @@ index 0be741820fc7da2aac4f4aad85c4238ef49a0f57..337976c5c1ead87c36daa4e741b06e5a // Paper start - prevent position desync if (this.awaitingPositionFromClient != null) { return; // ... thanks Mojang for letting move calls teleport across dimensions. -@@ -1503,7 +1536,17 @@ public class ServerGamePacketListenerImpl +@@ -1536,7 +1570,17 @@ public class ServerGamePacketListenerImpl } // Paper start - Add fail move event -- boolean teleportBack = !this.player.noPhysics && !this.player.isSleeping() && (movedWrongly && serverLevel.noCollision(this.player, boundingBox) || this.isPlayerCollidingWithAnythingNew(serverLevel, boundingBox, d, d1, d2)); +- boolean allowMovement = this.player.noPhysics || this.player.isSleeping() || (!movedWrongly || !serverLevel.noCollision(this.player, boundingBox)) && !this.isEntityCollidingWithAnythingNew(serverLevel, this.player, boundingBox, d, d1, d2); + // Paper start - optimise out extra getCubes -+ boolean teleportBack = !this.player.noPhysics && !this.player.isSleeping() && movedWrongly; ++ boolean allowMovement = this.player.noPhysics || this.player.isSleeping() || !movedWrongly; + this.player.absSnapTo(d, d1, d2, f, f1); // prevent desync by tping to the set position, dropped for unknown reasons by mojang -+ if (!this.player.noPhysics && !this.player.isSleeping() && !teleportBack) { ++ if (!this.player.noPhysics && !this.player.isSleeping() && allowMovement) { + final AABB newBox = this.player.getBoundingBox(); + if (didCollide || !boundingBox.equals(newBox)) { + // note: only call after setLocation, or else getBoundingBox is wrong -+ teleportBack = this.hasNewCollision(serverLevel, this.player, boundingBox, newBox); ++ allowMovement = !this.hasNewCollision(serverLevel, this.player, boundingBox, newBox); + } // else: no collision at all detected, why do we care? + } + // Paper end - optimise out extra getCubes - if (teleportBack) { + if (!allowMovement) { io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.CLIPPED_INTO_BLOCK, toX, toY, toZ, toYaw, toPitch, false); -@@ -1640,7 +1683,7 @@ public class ServerGamePacketListenerImpl +@@ -1672,7 +1716,7 @@ public class ServerGamePacketListenerImpl private boolean updateAwaitingTeleport() { if (this.awaitingPositionFromClient != null) { @@ -133,7 +123,7 @@ index 0be741820fc7da2aac4f4aad85c4238ef49a0f57..337976c5c1ead87c36daa4e741b06e5a this.awaitingTeleportTime = this.tickCount; this.teleport( this.awaitingPositionFromClient.x, -@@ -1659,6 +1702,33 @@ public class ServerGamePacketListenerImpl +@@ -1691,6 +1735,33 @@ public class ServerGamePacketListenerImpl } } @@ -164,6 +154,6 @@ index 0be741820fc7da2aac4f4aad85c4238ef49a0f57..337976c5c1ead87c36daa4e741b06e5a + return false; + } + // Paper end - optimise out extra getCubes - private boolean isPlayerCollidingWithAnythingNew(LevelReader level, AABB box, double x, double y, double z) { - AABB aabb = this.player.getBoundingBox().move(x - this.player.getX(), y - this.player.getY(), z - this.player.getZ()); - Iterable collisions = level.getCollisions(this.player, aabb.deflate(1.0E-5F)); + private boolean isEntityCollidingWithAnythingNew(LevelReader levelReader, Entity entity, AABB aabb, double d, double d1, double d2) { + AABB aabb1 = entity.getBoundingBox().move(d - entity.getX(), d1 - entity.getY(), d2 - entity.getZ()); + Iterable preMoveCollisions = levelReader.getPreMoveCollisions(entity, aabb1.deflate(1.0E-5F), aabb.getBottomCenter());