1cfd363d32
Upstream has released updates that appear to apply and compile correctly. This update has not been tested by PaperMC and as with ANY update, please do your own testing Bukkit Changes: fc460d1b PR-735: Add Villager#zombify c8c8331e PR-690: Add method to read ItemStack input 62845f2f SPIGOT-6829: Add per-player world border API CraftBukkit Changes: a459f4d4 PR-1033: Add Villager#zombify d65d1430 PR-975: Add method to read ItemStack input b5559f8c SPIGOT-6990: Fix setRepairCost(0) in Anvil 6c308e1b SPIGOT-6829: Add per-player world border API Spigot Changes: 42b61526 SPIGOT-7000: Generation and /locate issues when using custom structure seeds
371 Zeilen
24 KiB
Diff
371 Zeilen
24 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 8356a0e816324ce67df14151bdc186e60d8a223c..1324d48ff7540c4fe9148b3c6d4952ebbfb3fc22 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
|
@@ -76,6 +76,23 @@ public class ChunkHolder {
|
|
boolean isUpdateQueued = false; // Paper
|
|
private final ChunkMap chunkMap; // Paper
|
|
|
|
+ // 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;
|
|
+
|
|
+ void onChunkAdd() {
|
|
+ long key = net.minecraft.server.MCUtil.getCoordinateKey(this.pos);
|
|
+ this.playersInMobSpawnRange = this.chunkMap.playerMobSpawnMap.getObjectsInRange(key);
|
|
+ this.playersInChunkTickRange = this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(key);
|
|
+ }
|
|
+
|
|
+ void onChunkRemove() {
|
|
+ this.playersInMobSpawnRange = null;
|
|
+ this.playersInChunkTickRange = null;
|
|
+ }
|
|
+ // Paper end - optimise anyPlayerCloseEnoughForSpawning
|
|
+
|
|
public ChunkHolder(ChunkPos pos, int level, LevelHeightAccessor world, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) {
|
|
this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size());
|
|
this.fullChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE;
|
|
@@ -97,6 +114,7 @@ public class ChunkHolder {
|
|
this.setTicketLevel(level);
|
|
this.changedBlocksPerSection = new ShortSet[world.getSectionsCount()];
|
|
this.chunkMap = (ChunkMap)playersWatchingChunkProvider; // Paper
|
|
+ this.onChunkAdd(); // Paper - optimise anyPlayerCloseEnoughForSpawning
|
|
}
|
|
|
|
// Paper start
|
|
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
index 38efde791c99dd22de71183676d0301a1d5a14e0..63e264c862053874585b0f6aad2f89389c2dadcb 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
@@ -181,11 +181,23 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
final CallbackExecutor chunkLoadConversionCallbackExecutor = new CallbackExecutor(); // Paper
|
|
// Paper start - distance maps
|
|
private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets<ServerPlayer> pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>();
|
|
+ // 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) {
|
|
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, this.distanceManager.getSimulationDistance());
|
|
@@ -195,6 +207,10 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
|
|
void removePlayerFromDistanceMaps(ServerPlayer player) {
|
|
|
|
+ // 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);
|
|
@@ -206,6 +222,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
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.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, this.distanceManager.getSimulationDistance());
|
|
@@ -286,6 +303,38 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
this.regionManagers.add(this.dataRegionManager);
|
|
// Paper end
|
|
this.playerMobDistanceMap = this.level.paperConfig.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() {
|
|
@@ -537,6 +586,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
holder = (ChunkHolder) this.pendingUnloads.remove(pos);
|
|
if (holder != null) {
|
|
holder.setTicketLevel(level);
|
|
+ holder.onChunkAdd(); // Paper - optimise anyPlayerCloseEnoughForSpawning - PUT HERE AFTER RE-ADDING ONLY
|
|
} else {
|
|
holder = new ChunkHolder(new ChunkPos(pos), level, this.level, this.lightEngine, this.queueSorter, this);
|
|
// Paper start
|
|
@@ -632,6 +682,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
ChunkHolder playerchunk = (ChunkHolder) this.updatingChunkMap.remove(j);
|
|
|
|
if (playerchunk != null) {
|
|
+ playerchunk.onChunkRemove(); // Paper
|
|
this.pendingUnloads.put(j, playerchunk);
|
|
this.modified = true;
|
|
++i;
|
|
@@ -1370,43 +1421,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 4a9d0fca55b71f817defcb4286154c0a47bede03..62118348d6fb00f063507debb488e1ff431d139c 100644
|
|
--- a/src/main/java/net/minecraft/server/level/DistanceManager.java
|
|
+++ b/src/main/java/net/minecraft/server/level/DistanceManager.java
|
|
@@ -49,7 +49,7 @@ public abstract class DistanceManager {
|
|
final Long2ObjectMap<ObjectSet<ServerPlayer>> playersPerChunk = new Long2ObjectOpenHashMap();
|
|
public final Long2ObjectOpenHashMap<SortedArraySet<Ticket<?>>> tickets = new Long2ObjectOpenHashMap();
|
|
private final DistanceManager.ChunkTicketTracker ticketTracker = new DistanceManager.ChunkTicketTracker();
|
|
- private final DistanceManager.FixedPlayerDistanceChunkTracker naturalSpawnChunkCounter = new DistanceManager.FixedPlayerDistanceChunkTracker(8);
|
|
+ public static final int MOB_SPAWN_RANGE = 8; // private final ChunkMapDistance.b f = new ChunkMapDistance.b(8); // Paper - no longer used
|
|
private final TickingTracker tickingTicketsTracker = new TickingTracker();
|
|
private final DistanceManager.PlayerTicketTracker playerTicketManager = new DistanceManager.PlayerTicketTracker(33);
|
|
// Paper start use a queue, but still keep unique requirement
|
|
@@ -140,7 +140,7 @@ public abstract class DistanceManager {
|
|
protected abstract ChunkHolder updateChunkScheduling(long pos, int level, @Nullable ChunkHolder holder, int k);
|
|
|
|
public boolean runAllUpdates(ChunkMap chunkStorage) {
|
|
- this.naturalSpawnChunkCounter.runAllUpdates();
|
|
+ //this.f.a(); // Paper - no longer used
|
|
this.tickingTicketsTracker.runAllUpdates();
|
|
this.playerTicketManager.runAllUpdates();
|
|
int i = Integer.MAX_VALUE - this.ticketTracker.runDistanceUpdates(Integer.MAX_VALUE);
|
|
@@ -289,7 +289,7 @@ public abstract class DistanceManager {
|
|
((ObjectSet) this.playersPerChunk.computeIfAbsent(i, (j) -> {
|
|
return new ObjectOpenHashSet();
|
|
})).add(player);
|
|
- this.naturalSpawnChunkCounter.update(i, 0, true);
|
|
+ //this.f.update(i, 0, true); // Paper - no longer used
|
|
this.playerTicketManager.update(i, 0, true);
|
|
this.tickingTicketsTracker.addTicket(TicketType.PLAYER, chunkcoordintpair, this.getPlayerTicketLevel(), chunkcoordintpair);
|
|
}
|
|
@@ -303,7 +303,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.f.update(i, Integer.MAX_VALUE, false); // Paper - no longer used
|
|
this.playerTicketManager.update(i, Integer.MAX_VALUE, false);
|
|
this.tickingTicketsTracker.removeTicket(TicketType.PLAYER, chunkcoordintpair, this.getPlayerTicketLevel(), chunkcoordintpair);
|
|
}
|
|
@@ -347,13 +347,17 @@ public abstract class DistanceManager {
|
|
// Paper end
|
|
|
|
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 cf5a5d98420c3849621bfdfae7bda7d5cb4b2dc9..846e6f41fdb6413b10f908c6b3f5c199a9f5ef38 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
|
@@ -872,6 +872,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 = net.minecraft.server.MCUtil.getChunkCoordinate(player.getX());
|
|
+ int chunkZ = net.minecraft.server.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();
|
|
|
|
@@ -915,15 +946,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()) {
|
|
@@ -931,9 +954,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 d00dfcb2005b07f50c3a7a8a8268c5bc8305f333..9413ef3398553d2c778bcda6f97d99c9570d3b3e 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
|
@@ -253,6 +253,7 @@ public class ServerPlayer extends Player {
|
|
// CraftBukkit end
|
|
public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // 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 ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile) {
|