Fix mob spawning

We should only iterate over the local region's entities, not the
global entity list to set up the spawner state, as everything else
about the spawner state (player count / chunk count) is regionised.
Additionally, move the last spawner state to regionised state so that
paper mobcaps command functions as expected.
This commit is contained in:
Spottedleaf 2023-03-03 15:58:43 -08:00
parent 147df3c14c
commit 04b28a65ca

View File

@ -5309,7 +5309,7 @@ index 0000000000000000000000000000000000000000..a40b88fbee7b92de38b49c4dfa7c2796
+} +}
diff --git a/src/main/java/io/papermc/paper/threadedregions/RegionisedWorldData.java b/src/main/java/io/papermc/paper/threadedregions/RegionisedWorldData.java diff --git a/src/main/java/io/papermc/paper/threadedregions/RegionisedWorldData.java b/src/main/java/io/papermc/paper/threadedregions/RegionisedWorldData.java
new file mode 100644 new file mode 100644
index 0000000000000000000000000000000000000000..8317638bdb40764c389a68ced176e6d334eeb599 index 0000000000000000000000000000000000000000..af875578822408fdc914548409dcb83a247c7c04
--- /dev/null --- /dev/null
+++ b/src/main/java/io/papermc/paper/threadedregions/RegionisedWorldData.java +++ b/src/main/java/io/papermc/paper/threadedregions/RegionisedWorldData.java
@@ -0,0 +1,664 @@ @@ -0,0 +1,664 @@
@ -5340,29 +5340,27 @@ index 0000000000000000000000000000000000000000..8317638bdb40764c389a68ced176e6d3
+import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerLevel;
+import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.server.network.ServerGamePacketListenerImpl; +import net.minecraft.server.network.ServerGamePacketListenerImpl;
+import net.minecraft.util.Mth; +import net.minecraft.util.VisibleForDebug;
+import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.Entity;
+import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.Mob;
+import net.minecraft.world.entity.ai.village.VillageSiege; +import net.minecraft.world.entity.ai.village.VillageSiege;
+import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.item.ItemEntity;
+import net.minecraft.world.level.BlockEventData; +import net.minecraft.world.level.BlockEventData;
+import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.ChunkPos;
+import net.minecraft.world.level.NaturalSpawner;
+import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Block;
+import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntity;
+import net.minecraft.world.level.block.entity.TickingBlockEntity; +import net.minecraft.world.level.block.entity.TickingBlockEntity;
+import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.chunk.LevelChunk;
+import net.minecraft.world.level.gameevent.GameEvent;
+import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.level.material.Fluid;
+import net.minecraft.world.level.redstone.CollectingNeighborUpdater; +import net.minecraft.world.level.redstone.CollectingNeighborUpdater;
+import net.minecraft.world.level.redstone.NeighborUpdater; +import net.minecraft.world.level.redstone.NeighborUpdater;
+import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.AABB;
+import net.minecraft.world.phys.Vec3;
+import net.minecraft.world.ticks.LevelTicks; +import net.minecraft.world.ticks.LevelTicks;
+import org.bukkit.craftbukkit.block.CraftBlockState; +import org.bukkit.craftbukkit.block.CraftBlockState;
+import org.bukkit.craftbukkit.util.UnsafeList; +import org.bukkit.craftbukkit.util.UnsafeList;
+import org.bukkit.entity.SpawnCategory;
+import org.slf4j.Logger; +import org.slf4j.Logger;
+ +import javax.annotation.Nullable;
+import java.util.ArrayDeque; +import java.util.ArrayDeque;
+import java.util.ArrayList; +import java.util.ArrayList;
+import java.util.Arrays; +import java.util.Arrays;
@ -5371,7 +5369,6 @@ index 0000000000000000000000000000000000000000..8317638bdb40764c389a68ced176e6d3
+import java.util.Iterator; +import java.util.Iterator;
+import java.util.List; +import java.util.List;
+import java.util.Map; +import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Consumer; +import java.util.function.Consumer;
+import java.util.function.Predicate; +import java.util.function.Predicate;
+ +
@ -5680,6 +5677,9 @@ index 0000000000000000000000000000000000000000..8317638bdb40764c389a68ced176e6d3
+ public final TempCollisionList<AABB> tempCollisionList = new TempCollisionList<>(); + public final TempCollisionList<AABB> tempCollisionList = new TempCollisionList<>();
+ public final TempCollisionList<Entity> tempEntitiesList = new TempCollisionList<>(); + public final TempCollisionList<Entity> tempEntitiesList = new TempCollisionList<>();
+ public int currentPrimedTnt = 0; // Spigot + public int currentPrimedTnt = 0; // Spigot
+ @Nullable
+ @VisibleForDebug
+ public NaturalSpawner.SpawnState lastSpawnState;
+ +
+ // not transient + // not transient
+ public java.util.ArrayDeque<net.minecraft.world.level.block.RedstoneTorchBlock.Toggle> redstoneUpdateInfos; + public java.util.ArrayDeque<net.minecraft.world.level.block.RedstoneTorchBlock.Toggle> redstoneUpdateInfos;
@ -13260,10 +13260,10 @@ index 88fca8b160df6804f30ed2cf8cf1f645085434e2..341650384498eebe3f7a3315c398bec9
} }
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
index 736f37979c882e41e7571202df38eb6a2923fcb0..06ad3857f04ec073ae753b6569c5ae2ce7719ede 100644 index 736f37979c882e41e7571202df38eb6a2923fcb0..09a6a74f9bbcbbfba8bfc0424cde60002343b1af 100644
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
@@ -61,7 +61,7 @@ public class ServerChunkCache extends ChunkSource { @@ -61,73 +61,42 @@ public class ServerChunkCache extends ChunkSource {
public final ServerChunkCache.MainThreadExecutor mainThreadProcessor; public final ServerChunkCache.MainThreadExecutor mainThreadProcessor;
public final ChunkMap chunkMap; public final ChunkMap chunkMap;
private final DimensionDataStorage dataStorage; private final DimensionDataStorage dataStorage;
@ -13272,9 +13272,13 @@ index 736f37979c882e41e7571202df38eb6a2923fcb0..06ad3857f04ec073ae753b6569c5ae2c
public boolean spawnEnemies = true; public boolean spawnEnemies = true;
public boolean spawnFriendlies = true; public boolean spawnFriendlies = true;
private static final int CACHE_SIZE = 4; private static final int CACHE_SIZE = 4;
@@ -72,62 +72,33 @@ public class ServerChunkCache extends ChunkSource { private final long[] lastChunkPos = new long[4];
@VisibleForDebug private final ChunkStatus[] lastChunkStatus = new ChunkStatus[4];
private NaturalSpawner.SpawnState lastSpawnState; private final ChunkAccess[] lastChunk = new ChunkAccess[4];
- @Nullable
- @VisibleForDebug
- private NaturalSpawner.SpawnState lastSpawnState;
+ // Folia - moved to regionised world data
// Paper start // Paper start
- final com.destroystokyo.paper.util.concurrent.WeakSeqLock loadedChunkMapSeqLock = new com.destroystokyo.paper.util.concurrent.WeakSeqLock(); - final com.destroystokyo.paper.util.concurrent.WeakSeqLock loadedChunkMapSeqLock = new com.destroystokyo.paper.util.concurrent.WeakSeqLock();
- final it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<LevelChunk> loadedChunkMap = new it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<>(8192, 0.5f); - final it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<LevelChunk> loadedChunkMap = new it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<>(8192, 0.5f);
@ -13345,7 +13349,7 @@ index 736f37979c882e41e7571202df38eb6a2923fcb0..06ad3857f04ec073ae753b6569c5ae2c
} }
public final LevelChunk getChunkAtIfLoadedMainThreadNoCache(int x, int z) { public final LevelChunk getChunkAtIfLoadedMainThreadNoCache(int x, int z) {
@@ -142,7 +113,7 @@ public class ServerChunkCache extends ChunkSource { @@ -142,7 +111,7 @@ public class ServerChunkCache extends ChunkSource {
return (LevelChunk)this.getChunk(x, z, ChunkStatus.FULL, true); return (LevelChunk)this.getChunk(x, z, ChunkStatus.FULL, true);
} }
@ -13354,7 +13358,7 @@ index 736f37979c882e41e7571202df38eb6a2923fcb0..06ad3857f04ec073ae753b6569c5ae2c
public void getEntityTickingChunkAsync(int x, int z, java.util.function.Consumer<LevelChunk> onLoad) { public void getEntityTickingChunkAsync(int x, int z, java.util.function.Consumer<LevelChunk> onLoad) {
io.papermc.paper.chunk.system.ChunkSystem.scheduleTickingState( io.papermc.paper.chunk.system.ChunkSystem.scheduleTickingState(
@@ -293,8 +264,7 @@ public class ServerChunkCache extends ChunkSource { @@ -293,8 +262,7 @@ public class ServerChunkCache extends ChunkSource {
this.distanceManager.removeTicket(ticketType, chunkPos, ticketLevel, identifier); this.distanceManager.removeTicket(ticketType, chunkPos, ticketLevel, identifier);
} }
@ -13364,7 +13368,7 @@ index 736f37979c882e41e7571202df38eb6a2923fcb0..06ad3857f04ec073ae753b6569c5ae2c
// Paper end // Paper end
public ServerChunkCache(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureTemplateManager structureTemplateManager, Executor workerExecutor, ChunkGenerator chunkGenerator, int viewDistance, int simulationDistance, boolean dsync, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier<DimensionDataStorage> persistentStateManagerFactory) { public ServerChunkCache(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureTemplateManager structureTemplateManager, Executor workerExecutor, ChunkGenerator chunkGenerator, int viewDistance, int simulationDistance, boolean dsync, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier<DimensionDataStorage> persistentStateManagerFactory) {
@@ -368,26 +338,7 @@ public class ServerChunkCache extends ChunkSource { @@ -368,26 +336,7 @@ public class ServerChunkCache extends ChunkSource {
public LevelChunk getChunkAtIfLoadedImmediately(int x, int z) { public LevelChunk getChunkAtIfLoadedImmediately(int x, int z) {
long k = ChunkPos.asLong(x, z); long k = ChunkPos.asLong(x, z);
@ -13392,7 +13396,7 @@ index 736f37979c882e41e7571202df38eb6a2923fcb0..06ad3857f04ec073ae753b6569c5ae2c
} }
// Paper end // Paper end
// Paper start - async chunk io // Paper start - async chunk io
@@ -483,6 +434,7 @@ public class ServerChunkCache extends ChunkSource { @@ -483,6 +432,7 @@ public class ServerChunkCache extends ChunkSource {
} }
public CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> getChunkFuture(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) { public CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> getChunkFuture(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) {
@ -13400,7 +13404,7 @@ index 736f37979c882e41e7571202df38eb6a2923fcb0..06ad3857f04ec073ae753b6569c5ae2c
boolean flag1 = io.papermc.paper.util.TickThread.isTickThread(); // Paper - rewrite chunk system boolean flag1 = io.papermc.paper.util.TickThread.isTickThread(); // Paper - rewrite chunk system
CompletableFuture completablefuture; CompletableFuture completablefuture;
@@ -659,10 +611,11 @@ public class ServerChunkCache extends ChunkSource { @@ -659,10 +609,11 @@ public class ServerChunkCache extends ChunkSource {
} }
private void tickChunks() { private void tickChunks() {
@ -13414,7 +13418,7 @@ index 736f37979c882e41e7571202df38eb6a2923fcb0..06ad3857f04ec073ae753b6569c5ae2c
boolean flag = this.level.isDebug(); boolean flag = this.level.isDebug();
if (flag) { if (flag) {
@@ -670,9 +623,11 @@ public class ServerChunkCache extends ChunkSource { @@ -670,9 +621,11 @@ public class ServerChunkCache extends ChunkSource {
} else { } else {
// Paper start - optimize isOutisdeRange // Paper start - optimize isOutisdeRange
ChunkMap playerChunkMap = this.chunkMap; ChunkMap playerChunkMap = this.chunkMap;
@ -13428,7 +13432,7 @@ index 736f37979c882e41e7571202df38eb6a2923fcb0..06ad3857f04ec073ae753b6569c5ae2c
continue; continue;
} }
@@ -685,8 +640,9 @@ public class ServerChunkCache extends ChunkSource { @@ -685,8 +638,9 @@ public class ServerChunkCache extends ChunkSource {
com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(player.getBukkitEntity(), (byte)chunkRange); com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(player.getBukkitEntity(), (byte)chunkRange);
event.callEvent(); event.callEvent();
@ -13440,7 +13444,7 @@ index 736f37979c882e41e7571202df38eb6a2923fcb0..06ad3857f04ec073ae753b6569c5ae2c
continue; continue;
} }
@@ -694,7 +650,7 @@ public class ServerChunkCache extends ChunkSource { @@ -694,7 +648,7 @@ public class ServerChunkCache extends ChunkSource {
int chunkX = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getX()); int chunkX = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getX());
int chunkZ = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getZ()); int chunkZ = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getZ());
@ -13449,7 +13453,7 @@ index 736f37979c882e41e7571202df38eb6a2923fcb0..06ad3857f04ec073ae753b6569c5ae2c
player.lastEntitySpawnRadiusSquared = (double)((range << 4) * (range << 4)); // used in anyPlayerCloseEnoughForSpawning player.lastEntitySpawnRadiusSquared = (double)((range << 4) * (range << 4)); // used in anyPlayerCloseEnoughForSpawning
player.playerNaturallySpawnedEvent = event; player.playerNaturallySpawnedEvent = event;
} }
@@ -704,23 +660,16 @@ public class ServerChunkCache extends ChunkSource { @@ -704,26 +658,19 @@ public class ServerChunkCache extends ChunkSource {
gameprofilerfiller.push("pollingChunks"); gameprofilerfiller.push("pollingChunks");
int k = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING); int k = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING);
@ -13472,12 +13476,16 @@ index 736f37979c882e41e7571202df38eb6a2923fcb0..06ad3857f04ec073ae753b6569c5ae2c
- } - }
- // Paper end - // Paper end
+ // Folia start - threaded regions - revert per-player mob caps + // Folia start - threaded regions - revert per-player mob caps
+ spawnercreature_d = this.spawnFriendlies || this.spawnEnemies ? NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk, new LocalMobCapCalculator(this.chunkMap)) : null; + spawnercreature_d = this.spawnFriendlies || this.spawnEnemies ? NaturalSpawner.createState(l, regionisedWorldData.getLocalEntities(), this::getFullChunk, new LocalMobCapCalculator(this.chunkMap)) : null; // Folia - region threading
+ // Folia end - threaded regions - revert per-player mob caps + // Folia end - threaded regions - revert per-player mob caps
this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings
this.lastSpawnState = spawnercreature_d; - this.lastSpawnState = spawnercreature_d;
@@ -731,17 +680,17 @@ public class ServerChunkCache extends ChunkSource { + regionisedWorldData.lastSpawnState = spawnercreature_d; // Folia - region threading
gameprofilerfiller.popPush("filteringLoadedChunks");
// Paper - moved down
this.level.timings.chunkTicks.startTiming(); // Paper
@@ -731,17 +678,17 @@ public class ServerChunkCache extends ChunkSource {
// Paper - moved down // Paper - moved down
gameprofilerfiller.popPush("spawnAndTick"); gameprofilerfiller.popPush("spawnAndTick");
@ -13500,7 +13508,7 @@ index 736f37979c882e41e7571202df38eb6a2923fcb0..06ad3857f04ec073ae753b6569c5ae2c
while (iterator1.hasNext()) { while (iterator1.hasNext()) {
shuffled.add(iterator1.next()); shuffled.add(iterator1.next());
} }
@@ -791,14 +740,14 @@ public class ServerChunkCache extends ChunkSource { @@ -791,14 +738,14 @@ public class ServerChunkCache extends ChunkSource {
// Paper start - use set of chunks requiring updates, rather than iterating every single one loaded // Paper start - use set of chunks requiring updates, rather than iterating every single one loaded
gameprofilerfiller.popPush("broadcast"); gameprofilerfiller.popPush("broadcast");
this.level.timings.broadcastChunkUpdates.startTiming(); // Paper - timing this.level.timings.broadcastChunkUpdates.startTiming(); // Paper - timing
@ -13519,7 +13527,7 @@ index 736f37979c882e41e7571202df38eb6a2923fcb0..06ad3857f04ec073ae753b6569c5ae2c
} }
} }
} }
@@ -806,8 +755,8 @@ public class ServerChunkCache extends ChunkSource { @@ -806,8 +753,8 @@ public class ServerChunkCache extends ChunkSource {
gameprofilerfiller.pop(); gameprofilerfiller.pop();
// Paper end - use set of chunks requiring updates, rather than iterating every single one loaded // Paper end - use set of chunks requiring updates, rather than iterating every single one loaded
// Paper start - controlled flush for entity tracker packets // Paper start - controlled flush for entity tracker packets
@ -13530,7 +13538,7 @@ index 736f37979c882e41e7571202df38eb6a2923fcb0..06ad3857f04ec073ae753b6569c5ae2c
net.minecraft.server.network.ServerGamePacketListenerImpl connection = player.connection; net.minecraft.server.network.ServerGamePacketListenerImpl connection = player.connection;
if (connection != null) { if (connection != null) {
connection.connection.disableAutomaticFlush(); connection.connection.disableAutomaticFlush();
@@ -880,14 +829,19 @@ public class ServerChunkCache extends ChunkSource { @@ -880,14 +827,19 @@ public class ServerChunkCache extends ChunkSource {
@Override @Override
public void onLightUpdate(LightLayer type, SectionPos pos) { public void onLightUpdate(LightLayer type, SectionPos pos) {
@ -13552,7 +13560,17 @@ index 736f37979c882e41e7571202df38eb6a2923fcb0..06ad3857f04ec073ae753b6569c5ae2c
} }
public <T> void addRegionTicket(TicketType<T> ticketType, ChunkPos pos, int radius, T argument) { public <T> void addRegionTicket(TicketType<T> ticketType, ChunkPos pos, int radius, T argument) {
@@ -992,8 +946,43 @@ public class ServerChunkCache extends ChunkSource { @@ -959,7 +911,8 @@ public class ServerChunkCache extends ChunkSource {
@Nullable
@VisibleForDebug
public NaturalSpawner.SpawnState getLastSpawnState() {
- return this.lastSpawnState;
+ io.papermc.paper.threadedregions.RegionisedWorldData worldData = this.level.getCurrentWorldData(); // Folia - region threading
+ return worldData == null ? null : worldData.lastSpawnState; // Folia - region threading
}
public void removeTicketsOnClosing() {
@@ -992,8 +945,43 @@ public class ServerChunkCache extends ChunkSource {
return ServerChunkCache.this.mainThread; return ServerChunkCache.this.mainThread;
} }
@ -13596,7 +13614,7 @@ index 736f37979c882e41e7571202df38eb6a2923fcb0..06ad3857f04ec073ae753b6569c5ae2c
ServerChunkCache.this.level.getProfiler().incrementCounter("runTask"); ServerChunkCache.this.level.getProfiler().incrementCounter("runTask");
super.doRunTask(task); super.doRunTask(task);
} }
@@ -1001,11 +990,16 @@ public class ServerChunkCache extends ChunkSource { @@ -1001,11 +989,16 @@ public class ServerChunkCache extends ChunkSource {
@Override @Override
// CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task
public boolean pollTask() { public boolean pollTask() {