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 { +@@ -0,0 +0,0 @@ public class EntitySection { protected static final Logger LOGGER = LogManager.getLogger(); private final ClassInstanceMultiMap storage; private Visibility chunkStatus; @@ -41,53 +41,44 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public EntitySection(Class entityClass, Visibility status) { this.chunkStatus = status; -@@ -0,0 +0,0 @@ public class EntitySection { +@@ -0,0 +0,0 @@ public class EntitySection { } - 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 { - 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 { + 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 { - - 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 { } @@ -97,16 +88,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + public void getEntities(AABB box, Consumer 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 void getEntities(EntityTypeTest filter, AABB box, Consumer 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 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 entities, NaturalSpawner.ChunkGetter chunkSource) { -+ return createState(spawningChunkCount, entities, chunkSource, false); + public static NaturalSpawner.SpawnState createState(int spawningChunkCount, Iterable entities, NaturalSpawner.ChunkGetter chunkSource, LocalMobCapCalculator localmobcapcalculator) { ++ return createState(spawningChunkCount, entities, chunkSource, localmobcapcalculator, false); + } -+ public static NaturalSpawner.SpawnState createState(int spawningChunkCount, Iterable entities, NaturalSpawner.ChunkGetter chunkSource, boolean countMobs) { -+ // Paper end - add countMobs parameter ++ ++ public static NaturalSpawner.SpawnState createState(int spawningChunkCount, Iterable entities, NaturalSpawner.ChunkGetter chunkSource, LocalMobCapCalculator localmobcapcalculator, boolean countMobs) { ++ // Paper end PotentialCalculator spawnercreatureprobabilities = new PotentialCalculator(); Object2IntOpenHashMap 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) {