346 lines
22 KiB
Diff
346 lines
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 c5389e7f3665c06e487dfde3200b7e229694fbd2..4164204ba80f68a768de0ed1721c6447b972a631 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
|
@@ -79,16 +79,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
|
|
+
|
|
// Paper start - replace player chunk loader
|
|
private final com.destroystokyo.paper.util.maplist.ReferenceList<ServerPlayer> playersSentChunkTo = new com.destroystokyo.paper.util.maplist.ReferenceList<>();
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
index 52d9d0f2366f292c56eee9fe241cb43bc2900b23..80b2ff12e48e1aabebd9ebcf5958c1f5d073d55b 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
@@ -174,12 +174,24 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
return net.minecraft.server.MinecraftServer.getServer().getScaledTrackingDistance(vanilla);
|
|
}
|
|
// Paper end - use distance map to optimise tracker
|
|
+ // 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.level.playerChunkLoader.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));
|
|
@@ -198,6 +210,10 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
void removePlayerFromDistanceMaps(ServerPlayer player) {
|
|
this.level.playerChunkLoader.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);
|
|
@@ -215,6 +231,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.level.playerChunkLoader.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));
|
|
@@ -356,6 +373,38 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
this.playerEntityTrackerTrackMaps[ordinal] = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets);
|
|
}
|
|
// Paper end - use distance map to optimise entity tracker
|
|
+ // 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() {
|
|
@@ -930,43 +979,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 0a926afa06a5e37cf2650afa1b5099a2a9ffa659..ae4a4710ba07614be42cdcbf52cee04cfa08466b 100644
|
|
--- a/src/main/java/net/minecraft/server/level/DistanceManager.java
|
|
+++ b/src/main/java/net/minecraft/server/level/DistanceManager.java
|
|
@@ -50,7 +50,7 @@ public abstract class DistanceManager {
|
|
private static final int INITIAL_TICKET_LIST_CAPACITY = 4;
|
|
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
|
|
// Paper - rewrite chunk system
|
|
private final ChunkMap chunkMap; // Paper
|
|
|
|
@@ -136,7 +136,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
|
|
}
|
|
@@ -150,7 +150,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
|
|
}
|
|
@@ -192,13 +192,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 3f5d572994bc8b3f1e106105dc0bb202ad005b8c..5c5fe2087a7617324ab8e18389e3ffa9ac413026 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
|
@@ -517,6 +517,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();
|
|
|
|
@@ -560,15 +591,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()) {
|
|
@@ -576,9 +599,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 ce2972c62f91724f6a9e56c8103fba219f7a60bb..6c00162847b59ffa3d1403b956545c57ba539139 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
|
@@ -273,6 +273,7 @@ public class ServerPlayer extends Player {
|
|
public Integer clientViewDistance;
|
|
// 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
|
|
public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - there are a lot of changes to do if we change all methods leading to the event
|