geforkt von Mirrors/Paper
afe633df08
* convert API tests to mockito * convert server tests to mockito * add co-author
347 Zeilen
22 KiB
Diff
347 Zeilen
22 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
|
Date: Tue, 5 May 2020 20:40:53 -0700
|
|
Subject: [PATCH] Optimize anyPlayerCloseEnoughForSpawning to use distance maps
|
|
|
|
Use a distance map to find the players in range quickly
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
|
index 2ba3bb4e5670ece798a8882801a856d82851c00a..a61f55ed1fbe5aac5289014cb95cb6950b4c77fa 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
|
@@ -83,16 +83,29 @@ public class ChunkHolder {
|
|
|
|
// Paper start
|
|
public void onChunkAdd() {
|
|
-
|
|
+ // Paper start - optimise anyPlayerCloseEnoughForSpawning
|
|
+ long key = io.papermc.paper.util.MCUtil.getCoordinateKey(this.pos);
|
|
+ this.playersInMobSpawnRange = this.chunkMap.playerMobSpawnMap.getObjectsInRange(key);
|
|
+ this.playersInChunkTickRange = this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(key);
|
|
+ // Paper end - optimise anyPlayerCloseEnoughForSpawning
|
|
}
|
|
|
|
public void onChunkRemove() {
|
|
-
|
|
+ // Paper start - optimise anyPlayerCloseEnoughForSpawning
|
|
+ this.playersInMobSpawnRange = null;
|
|
+ this.playersInChunkTickRange = null;
|
|
+ // Paper end - optimise anyPlayerCloseEnoughForSpawning
|
|
}
|
|
// Paper end
|
|
|
|
public final io.papermc.paper.chunk.system.scheduling.NewChunkHolder newChunkHolder; // Paper - rewrite chunk system
|
|
|
|
+ // Paper start - optimise anyPlayerCloseEnoughForSpawning
|
|
+ // cached here to avoid a map lookup
|
|
+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> playersInMobSpawnRange;
|
|
+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> playersInChunkTickRange;
|
|
+ // Paper end - optimise anyPlayerCloseEnoughForSpawning
|
|
+
|
|
public ChunkHolder(ChunkPos pos, LevelHeightAccessor world, LevelLightEngine lightingProvider, ChunkHolder.PlayerProvider playersWatchingChunkProvider, io.papermc.paper.chunk.system.scheduling.NewChunkHolder newChunkHolder) { // Paper - rewrite chunk system
|
|
this.newChunkHolder = newChunkHolder; // Paper - rewrite chunk system
|
|
this.chunkToSaveHistory = null;
|
|
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
index 69ac6b4fbdf4cebbaa36234e17e2d51c732de8af..e87ade8697a33b9ea23dce59838a9ccd02ab09f6 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
@@ -156,12 +156,24 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
// Paper start - distance maps
|
|
private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets<ServerPlayer> pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>();
|
|
public final io.papermc.paper.chunk.PlayerChunkLoader playerChunkManager = new io.papermc.paper.chunk.PlayerChunkLoader(this, this.pooledLinkedPlayerHashSets); // Paper - replace chunk loader
|
|
+ // Paper start - optimise ChunkMap#anyPlayerCloseEnoughForSpawning
|
|
+ // A note about the naming used here:
|
|
+ // Previously, mojang used a "spawn range" of 8 for controlling both ticking and
|
|
+ // mob spawn range. However, spigot makes the spawn range configurable by
|
|
+ // checking if the chunk is in the tick range (8) and the spawn range
|
|
+ // obviously this means a spawn range > 8 cannot be implemented
|
|
+
|
|
+ // these maps are named after spigot's uses
|
|
+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerMobSpawnMap; // this map is absent from updateMaps since it's controlled at the start of the chunkproviderserver tick
|
|
+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerChunkTickRangeMap;
|
|
+ // Paper end - optimise ChunkMap#anyPlayerCloseEnoughForSpawning
|
|
|
|
void addPlayerToDistanceMaps(ServerPlayer player) {
|
|
this.playerChunkManager.addPlayer(player); // Paper - replace chunk loader
|
|
int chunkX = MCUtil.getChunkCoordinate(player.getX());
|
|
int chunkZ = MCUtil.getChunkCoordinate(player.getZ());
|
|
// Note: players need to be explicitly added to distance maps before they can be updated
|
|
+ this.playerChunkTickRangeMap.add(player, chunkX, chunkZ, DistanceManager.MOB_SPAWN_RANGE); // Paper - optimise ChunkMap#anyPlayerCloseEnoughForSpawning
|
|
// Paper start - per player mob spawning
|
|
if (this.playerMobDistanceMap != null) {
|
|
this.playerMobDistanceMap.add(player, chunkX, chunkZ, io.papermc.paper.chunk.system.ChunkSystem.getTickViewDistance(player));
|
|
@@ -172,6 +184,10 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
void removePlayerFromDistanceMaps(ServerPlayer player) {
|
|
this.playerChunkManager.removePlayer(player); // Paper - replace chunk loader
|
|
|
|
+ // Paper start - optimise ChunkMap#anyPlayerCloseEnoughForSpawning
|
|
+ this.playerMobSpawnMap.remove(player);
|
|
+ this.playerChunkTickRangeMap.remove(player);
|
|
+ // Paper end - optimise ChunkMap#anyPlayerCloseEnoughForSpawning
|
|
// Paper start - per player mob spawning
|
|
if (this.playerMobDistanceMap != null) {
|
|
this.playerMobDistanceMap.remove(player);
|
|
@@ -184,6 +200,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
int chunkZ = MCUtil.getChunkCoordinate(player.getZ());
|
|
// Note: players need to be explicitly added to distance maps before they can be updated
|
|
this.playerChunkManager.updatePlayer(player); // Paper - replace chunk loader
|
|
+ this.playerChunkTickRangeMap.update(player, chunkX, chunkZ, DistanceManager.MOB_SPAWN_RANGE); // Paper - optimise ChunkMap#anyPlayerCloseEnoughForSpawning
|
|
// Paper start - per player mob spawning
|
|
if (this.playerMobDistanceMap != null) {
|
|
this.playerMobDistanceMap.update(player, chunkX, chunkZ, io.papermc.paper.chunk.system.ChunkSystem.getTickViewDistance(player));
|
|
@@ -275,6 +292,38 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
this.regionManagers.add(this.dataRegionManager);
|
|
// Paper end
|
|
this.playerMobDistanceMap = this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets) : null; // Paper
|
|
+ // Paper start - optimise ChunkMap#anyPlayerCloseEnoughForSpawning
|
|
+ this.playerChunkTickRangeMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets,
|
|
+ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ,
|
|
+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> newState) -> {
|
|
+ ChunkHolder playerChunk = ChunkMap.this.getUpdatingChunkIfPresent(MCUtil.getCoordinateKey(rangeX, rangeZ));
|
|
+ if (playerChunk != null) {
|
|
+ playerChunk.playersInChunkTickRange = newState;
|
|
+ }
|
|
+ },
|
|
+ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ,
|
|
+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> newState) -> {
|
|
+ ChunkHolder playerChunk = ChunkMap.this.getUpdatingChunkIfPresent(MCUtil.getCoordinateKey(rangeX, rangeZ));
|
|
+ if (playerChunk != null) {
|
|
+ playerChunk.playersInChunkTickRange = newState;
|
|
+ }
|
|
+ });
|
|
+ this.playerMobSpawnMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets,
|
|
+ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ,
|
|
+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> newState) -> {
|
|
+ ChunkHolder playerChunk = ChunkMap.this.getUpdatingChunkIfPresent(MCUtil.getCoordinateKey(rangeX, rangeZ));
|
|
+ if (playerChunk != null) {
|
|
+ playerChunk.playersInMobSpawnRange = newState;
|
|
+ }
|
|
+ },
|
|
+ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ,
|
|
+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> newState) -> {
|
|
+ ChunkHolder playerChunk = ChunkMap.this.getUpdatingChunkIfPresent(MCUtil.getCoordinateKey(rangeX, rangeZ));
|
|
+ if (playerChunk != null) {
|
|
+ playerChunk.playersInMobSpawnRange = newState;
|
|
+ }
|
|
+ });
|
|
+ // Paper end - optimise ChunkMap#anyPlayerCloseEnoughForSpawning
|
|
}
|
|
|
|
protected ChunkGenerator generator() {
|
|
@@ -834,43 +883,48 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
return this.anyPlayerCloseEnoughForSpawning(pos, false);
|
|
}
|
|
|
|
- boolean anyPlayerCloseEnoughForSpawning(ChunkPos chunkcoordintpair, boolean reducedRange) {
|
|
- int chunkRange = level.spigotConfig.mobSpawnRange;
|
|
- chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.spigotConfig.viewDistance : chunkRange;
|
|
- chunkRange = (chunkRange > 8) ? 8 : chunkRange;
|
|
-
|
|
- final int finalChunkRange = chunkRange; // Paper for lambda below
|
|
- //double blockRange = (reducedRange) ? Math.pow(chunkRange << 4, 2) : 16384.0D; // Paper - use from event
|
|
- double blockRange = 16384.0D; // Paper
|
|
- // Spigot end
|
|
- long i = chunkcoordintpair.toLong();
|
|
+ // Paper start - optimise anyPlayerCloseEnoughForSpawning
|
|
+ final boolean anyPlayerCloseEnoughForSpawning(ChunkPos chunkcoordintpair, boolean reducedRange) {
|
|
+ return this.anyPlayerCloseEnoughForSpawning(this.getUpdatingChunkIfPresent(chunkcoordintpair.toLong()), chunkcoordintpair, reducedRange);
|
|
+ }
|
|
|
|
- if (!this.distanceManager.hasPlayersNearby(i)) {
|
|
+ final boolean anyPlayerCloseEnoughForSpawning(ChunkHolder playerchunk, ChunkPos chunkcoordintpair, boolean reducedRange) {
|
|
+ // this function is so hot that removing the map lookup call can have an order of magnitude impact on its performance
|
|
+ // tested and confirmed via System.nanoTime()
|
|
+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> playersInRange = reducedRange ? playerchunk.playersInMobSpawnRange : playerchunk.playersInChunkTickRange;
|
|
+ if (playersInRange == null) {
|
|
return false;
|
|
- } else {
|
|
- Iterator iterator = this.playerMap.getPlayers(i).iterator();
|
|
-
|
|
- ServerPlayer entityplayer;
|
|
+ }
|
|
+ Object[] backingSet = playersInRange.getBackingSet();
|
|
|
|
- do {
|
|
- if (!iterator.hasNext()) {
|
|
- return false;
|
|
+ if (reducedRange) {
|
|
+ for (int i = 0, len = backingSet.length; i < len; ++i) {
|
|
+ Object raw = backingSet[i];
|
|
+ if (!(raw instanceof ServerPlayer player)) {
|
|
+ continue;
|
|
}
|
|
-
|
|
- entityplayer = (ServerPlayer) iterator.next();
|
|
- // Paper start - add PlayerNaturallySpawnCreaturesEvent
|
|
- com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event;
|
|
- blockRange = 16384.0D;
|
|
- if (reducedRange) {
|
|
- event = entityplayer.playerNaturallySpawnedEvent;
|
|
- if (event == null || event.isCancelled()) return false;
|
|
- blockRange = (double) ((event.getSpawnRadius() << 4) * (event.getSpawnRadius() << 4));
|
|
+ // don't check spectator and whatnot, already handled by mob spawn map update
|
|
+ if (euclideanDistanceSquared(chunkcoordintpair, player) < player.lastEntitySpawnRadiusSquared) {
|
|
+ return true; // in range
|
|
}
|
|
- // Paper end
|
|
- } while (!this.playerIsCloseEnoughForSpawning(entityplayer, chunkcoordintpair, blockRange)); // Spigot
|
|
-
|
|
- return true;
|
|
+ }
|
|
+ } else {
|
|
+ final double range = (DistanceManager.MOB_SPAWN_RANGE * 16) * (DistanceManager.MOB_SPAWN_RANGE * 16);
|
|
+ // before spigot, mob spawn range was actually mob spawn range + tick range, but it was split
|
|
+ for (int i = 0, len = backingSet.length; i < len; ++i) {
|
|
+ Object raw = backingSet[i];
|
|
+ if (!(raw instanceof ServerPlayer player)) {
|
|
+ continue;
|
|
+ }
|
|
+ // don't check spectator and whatnot, already handled by mob spawn map update
|
|
+ if (euclideanDistanceSquared(chunkcoordintpair, player) < range) {
|
|
+ return true; // in range
|
|
+ }
|
|
+ }
|
|
}
|
|
+ // no players in range
|
|
+ return false;
|
|
+ // Paper end - optimise anyPlayerCloseEnoughForSpawning
|
|
}
|
|
|
|
public List<ServerPlayer> getPlayersCloseForSpawning(ChunkPos pos) {
|
|
diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java
|
|
index d3c3db919e9b0507e8543313d9028394e5163673..52cba8f68d274cce106304aef1249a95474d3238 100644
|
|
--- a/src/main/java/net/minecraft/server/level/DistanceManager.java
|
|
+++ b/src/main/java/net/minecraft/server/level/DistanceManager.java
|
|
@@ -54,7 +54,7 @@ public abstract class DistanceManager {
|
|
private static final int BLOCK_TICKING_LEVEL_THRESHOLD = 33;
|
|
final Long2ObjectMap<ObjectSet<ServerPlayer>> playersPerChunk = new Long2ObjectOpenHashMap();
|
|
// Paper - rewrite chunk system
|
|
- private final DistanceManager.FixedPlayerDistanceChunkTracker naturalSpawnChunkCounter = new DistanceManager.FixedPlayerDistanceChunkTracker(8);
|
|
+ public static final int MOB_SPAWN_RANGE = 8; // private final DistanceManager.FixedPlayerDistanceChunkTracker naturalSpawnChunkCounter = new DistanceManager.FixedPlayerDistanceChunkTracker(8); // Paper - no longer used
|
|
//private final TickingTracker tickingTicketsTracker = new TickingTracker(); // Paper - no longer used
|
|
//private final DistanceManager.PlayerTicketTracker playerTicketManager = new DistanceManager.PlayerTicketTracker(33); // Paper - no longer used
|
|
// Paper - rewrite chunk system
|
|
@@ -142,7 +142,7 @@ public abstract class DistanceManager {
|
|
long i = chunkcoordintpair.toLong();
|
|
|
|
// Paper - no longer used
|
|
- this.naturalSpawnChunkCounter.update(i, 0, true);
|
|
+ //this.naturalSpawnChunkCounter.update(i, 0, true); // Paper - no longer used
|
|
//this.playerTicketManager.update(i, 0, true); // Paper - no longer used
|
|
//this.tickingTicketsTracker.addTicket(TicketType.PLAYER, chunkcoordintpair, this.getPlayerTicketLevel(), chunkcoordintpair); // Paper - no longer used
|
|
}
|
|
@@ -156,7 +156,7 @@ public abstract class DistanceManager {
|
|
if (objectset != null) objectset.remove(player); // Paper - some state corruption happens here, don't crash, clean up gracefully.
|
|
if (objectset == null || objectset.isEmpty()) { // Paper
|
|
this.playersPerChunk.remove(i);
|
|
- this.naturalSpawnChunkCounter.update(i, Integer.MAX_VALUE, false);
|
|
+ // this.naturalSpawnChunkCounter.update(i, Integer.MAX_VALUE, false); // Paper - no longer used
|
|
//this.playerTicketManager.update(i, Integer.MAX_VALUE, false); // Paper - no longer used
|
|
//this.tickingTicketsTracker.removeTicket(TicketType.PLAYER, chunkcoordintpair, this.getPlayerTicketLevel(), chunkcoordintpair); // Paper - no longer used
|
|
}
|
|
@@ -198,13 +198,17 @@ public abstract class DistanceManager {
|
|
}
|
|
|
|
public int getNaturalSpawnChunkCount() {
|
|
- this.naturalSpawnChunkCounter.runAllUpdates();
|
|
- return this.naturalSpawnChunkCounter.chunks.size();
|
|
+ // Paper start - use distance map to implement
|
|
+ // note: this is the spawn chunk count
|
|
+ return this.chunkMap.playerChunkTickRangeMap.size();
|
|
+ // Paper end - use distance map to implement
|
|
}
|
|
|
|
public boolean hasPlayersNearby(long chunkPos) {
|
|
- this.naturalSpawnChunkCounter.runAllUpdates();
|
|
- return this.naturalSpawnChunkCounter.chunks.containsKey(chunkPos);
|
|
+ // Paper start - use distance map to implement
|
|
+ // note: this is the is spawn chunk method
|
|
+ return this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(chunkPos) != null;
|
|
+ // Paper end - use distance map to implement
|
|
}
|
|
|
|
public String getDebugStatus() {
|
|
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
|
index 665e088cb0b73f6a0c62f29c56da462bab7c927e..298e4468f7b5346733257f7117f76c66e9a1d8f0 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
|
@@ -658,6 +658,37 @@ public class ServerChunkCache extends ChunkSource {
|
|
if (flag) {
|
|
this.chunkMap.tick();
|
|
} else {
|
|
+ // Paper start - optimize isOutisdeRange
|
|
+ ChunkMap playerChunkMap = this.chunkMap;
|
|
+ for (ServerPlayer player : this.level.players) {
|
|
+ if (!player.affectsSpawning || player.isSpectator()) {
|
|
+ playerChunkMap.playerMobSpawnMap.remove(player);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ int viewDistance = this.chunkMap.getEffectiveViewDistance();
|
|
+
|
|
+ // copied and modified from isOutisdeRange
|
|
+ int chunkRange = level.spigotConfig.mobSpawnRange;
|
|
+ chunkRange = (chunkRange > viewDistance) ? (byte)viewDistance : chunkRange;
|
|
+ chunkRange = (chunkRange > DistanceManager.MOB_SPAWN_RANGE) ? DistanceManager.MOB_SPAWN_RANGE : chunkRange;
|
|
+
|
|
+ com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(player.getBukkitEntity(), (byte)chunkRange);
|
|
+ event.callEvent();
|
|
+ if (event.isCancelled() || event.getSpawnRadius() < 0 || playerChunkMap.playerChunkTickRangeMap.getLastViewDistance(player) == -1) {
|
|
+ playerChunkMap.playerMobSpawnMap.remove(player);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ int range = Math.min(event.getSpawnRadius(), 32); // limit to max view distance
|
|
+ int chunkX = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getX());
|
|
+ int chunkZ = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getZ());
|
|
+
|
|
+ playerChunkMap.playerMobSpawnMap.addOrUpdate(player, chunkX, chunkZ, range);
|
|
+ player.lastEntitySpawnRadiusSquared = (double)((range << 4) * (range << 4)); // used in anyPlayerCloseEnoughForSpawning
|
|
+ player.playerNaturallySpawnedEvent = event;
|
|
+ }
|
|
+ // Paper end - optimize isOutisdeRange
|
|
LevelData worlddata = this.level.getLevelData();
|
|
ProfilerFiller gameprofilerfiller = this.level.getProfiler();
|
|
|
|
@@ -701,15 +732,7 @@ public class ServerChunkCache extends ChunkSource {
|
|
boolean flag2 = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit
|
|
|
|
Collections.shuffle(list);
|
|
- // Paper start - call player naturally spawn event
|
|
- int chunkRange = level.spigotConfig.mobSpawnRange;
|
|
- chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.spigotConfig.viewDistance : chunkRange;
|
|
- chunkRange = Math.min(chunkRange, 8);
|
|
- for (ServerPlayer entityPlayer : this.level.players()) {
|
|
- entityPlayer.playerNaturallySpawnedEvent = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(entityPlayer.getBukkitEntity(), (byte) chunkRange);
|
|
- entityPlayer.playerNaturallySpawnedEvent.callEvent();
|
|
- };
|
|
- // Paper end
|
|
+ // Paper - moved natural spawn event up
|
|
Iterator iterator1 = list.iterator();
|
|
|
|
while (iterator1.hasNext()) {
|
|
@@ -717,9 +740,9 @@ public class ServerChunkCache extends ChunkSource {
|
|
LevelChunk chunk1 = chunkproviderserver_a.chunk;
|
|
ChunkPos chunkcoordintpair = chunk1.getPos();
|
|
|
|
- if (this.level.isNaturalSpawningAllowed(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkcoordintpair)) {
|
|
+ if (this.level.isNaturalSpawningAllowed(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkproviderserver_a.holder, chunkcoordintpair, false)) { // Paper - optimise anyPlayerCloseEnoughForSpawning
|
|
chunk1.incrementInhabitedTime(j);
|
|
- if (flag2 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkcoordintpair, true)) { // Spigot
|
|
+ if (flag2 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkproviderserver_a.holder, chunkcoordintpair, true)) { // Spigot // Paper - optimise anyPlayerCloseEnoughForSpawning
|
|
NaturalSpawner.spawnForChunk(this.level, chunk1, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag1);
|
|
}
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
|
index 33b6f23f483535714fc020da47c79fca33271c62..35d28066295bfbdac3f35b0565ea658bd20de892 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
|
@@ -264,6 +264,7 @@ public class ServerPlayer extends Player {
|
|
public String kickLeaveMessage = null; // SPIGOT-3034: Forward leave message to PlayerQuitEvent
|
|
// CraftBukkit end
|
|
public boolean isRealPlayer; // Paper
|
|
+ public double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks
|
|
public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> cachedSingleHashSet; // Paper
|
|
public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper
|
|
|