2 patch
Dieser Commit ist enthalten in:
Ursprung
961f297963
Commit
d001eefd7e
@ -6,10 +6,10 @@ Subject: [PATCH] Use distance map to optimise entity tracker
|
||||
Use the distance map to find candidate players for tracking.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index e5ad635a480d32e7a10ee92c65cfc18a98beafad..74f393ffa2ae2d0e25b3f0b674cef7a987e985d3 100644
|
||||
index 11fd6d24ed0612e4df1a0493907178fb9c455d1c..d7023cb0974f6c28a0fb8a0a6e5a6600fe30d3e3 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1652,6 +1652,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -1718,6 +1718,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,21 +18,21 @@ index e5ad635a480d32e7a10ee92c65cfc18a98beafad..74f393ffa2ae2d0e25b3f0b674cef7a9
|
||||
return initialDistance;
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 6c7af93cead523830d32b007cc69b313e59abef1..41147be189f764c2346cf015890a148f9730bc0f 100644
|
||||
index f9fcf99ec7151b4f00ef2c40b0cbc2fd3a8e002c..f7032e1d64afa6707756bb5a2af9d43a808c9736 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -61,6 +61,7 @@ import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket;
|
||||
@@ -58,6 +58,7 @@ import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket;
|
||||
import net.minecraft.network.protocol.game.DebugPackets;
|
||||
import net.minecraft.server.MCUtil;
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.progress.ChunkProgressListener;
|
||||
import net.minecraft.server.network.ServerPlayerConnection;
|
||||
import net.minecraft.util.CsvOutput;
|
||||
import net.minecraft.util.Mth;
|
||||
@@ -193,21 +194,55 @@ 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<>();
|
||||
@@ -222,11 +223,33 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceTickMap;
|
||||
public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceNoTickMap;
|
||||
// Paper end - no-tick view distance
|
||||
+ // Paper start - use distance map to optimise tracker
|
||||
+ public static boolean isLegacyTrackingEntity(Entity entity) {
|
||||
+ return entity.isLegacyTrackingEntity;
|
||||
@ -60,6 +60,10 @@ index 6c7af93cead523830d32b007cc69b313e59abef1..41147be189f764c2346cf015890a148f
|
||||
+ trackMap.add(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance()));
|
||||
+ }
|
||||
+ // Paper end - use distance map to optimise entity tracker
|
||||
// Paper start - no-tick view distance
|
||||
int effectiveTickViewDistance = this.getEffectiveViewDistance();
|
||||
int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance);
|
||||
@@ -243,7 +266,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
|
||||
void removePlayerFromDistanceMaps(ServerPlayer player) {
|
||||
@ -69,9 +73,10 @@ index 6c7af93cead523830d32b007cc69b313e59abef1..41147be189f764c2346cf015890a148f
|
||||
+ this.playerEntityTrackerTrackMaps[i].remove(player);
|
||||
+ }
|
||||
+ // Paper end - use distance map to optimise tracker
|
||||
}
|
||||
|
||||
void updateMaps(ServerPlayer player) {
|
||||
// Paper start - no-tick view distance
|
||||
this.playerViewDistanceBroadcastMap.remove(player);
|
||||
this.playerViewDistanceTickMap.remove(player);
|
||||
@@ -255,6 +282,14 @@ 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
|
||||
@ -83,12 +88,12 @@ index 6c7af93cead523830d32b007cc69b313e59abef1..41147be189f764c2346cf015890a148f
|
||||
+ trackMap.update(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance()));
|
||||
+ }
|
||||
+ // Paper end - use distance map to optimise entity tracker
|
||||
}
|
||||
// Paper end
|
||||
|
||||
@@ -244,6 +279,45 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, flag, this.level); // Paper
|
||||
this.setViewDistance(i);
|
||||
// Paper start - no-tick view distance
|
||||
int effectiveTickViewDistance = this.getEffectiveViewDistance();
|
||||
int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance);
|
||||
@@ -306,6 +341,45 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, dsync, world);
|
||||
this.setViewDistance(viewDistance);
|
||||
this.playerMobDistanceMap = this.level.paperConfig.perPlayerMobSpawns ? new com.destroystokyo.paper.util.PlayerMobDistanceMap() : null; // Paper
|
||||
+ // Paper start - use distance map to optimise entity tracker
|
||||
+ this.playerEntityTrackerTrackMaps = new com.destroystokyo.paper.util.misc.PlayerAreaMap[TRACKING_RANGE_TYPES.length];
|
||||
@ -129,10 +134,10 @@ index 6c7af93cead523830d32b007cc69b313e59abef1..41147be189f764c2346cf015890a148f
|
||||
+ this.playerEntityTrackerTrackMaps[ordinal] = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets);
|
||||
+ }
|
||||
+ // Paper end - use distance map to optimise entity tracker
|
||||
}
|
||||
|
||||
public void updatePlayerMobTypeMap(Entity entity) {
|
||||
@@ -1490,17 +1564,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
// Paper start - no-tick view distance
|
||||
this.setNoTickViewDistance(this.level.paperConfig.noTickViewDistance);
|
||||
this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets,
|
||||
@@ -1424,17 +1498,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
|
||||
public void move(ServerPlayer player) {
|
||||
@ -149,9 +154,9 @@ index 6c7af93cead523830d32b007cc69b313e59abef1..41147be189f764c2346cf015890a148f
|
||||
- }
|
||||
+ // Paper - delay this logic for the entity tracker tick, no need to duplicate it
|
||||
|
||||
int i = Mth.floor(player.getX()) >> 4;
|
||||
int j = Mth.floor(player.getZ()) >> 4;
|
||||
@@ -1616,7 +1680,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
int i = SectionPos.blockToSectionCoord(player.getBlockX());
|
||||
int j = SectionPos.blockToSectionCoord(player.getBlockZ());
|
||||
@@ -1589,7 +1653,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
|
||||
entity.tracker = playerchunkmap_entitytracker; // Paper - Fast access to tracker
|
||||
this.entityMap.put(entity.getId(), playerchunkmap_entitytracker);
|
||||
@ -160,7 +165,7 @@ index 6c7af93cead523830d32b007cc69b313e59abef1..41147be189f764c2346cf015890a148f
|
||||
if (entity instanceof ServerPlayer) {
|
||||
ServerPlayer entityplayer = (ServerPlayer) entity;
|
||||
|
||||
@@ -1659,7 +1723,37 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1633,7 +1697,37 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
entity.tracker = null; // Paper - We're no longer tracked
|
||||
}
|
||||
|
||||
@ -198,7 +203,7 @@ index 6c7af93cead523830d32b007cc69b313e59abef1..41147be189f764c2346cf015890a148f
|
||||
List<ServerPlayer> list = Lists.newArrayList();
|
||||
List<ServerPlayer> list1 = this.level.players();
|
||||
|
||||
@@ -1728,23 +1822,31 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1742,23 +1836,31 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
|
||||
DebugPackets.sendPoiPacketsForChunk(this.level, chunk.getPos());
|
||||
List<Entity> list = Lists.newArrayList();
|
||||
List<Entity> list1 = Lists.newArrayList();
|
||||
@ -222,7 +227,7 @@ index 6c7af93cead523830d32b007cc69b313e59abef1..41147be189f764c2346cf015890a148f
|
||||
+ // keep the vanilla logic here - this is REQUIRED or else passengers and their vehicles disappear!
|
||||
+ // (and god knows what the leash thing is)
|
||||
|
||||
- if (entity != player && entity.xChunk == chunk.getPos().x && entity.zChunk == chunk.getPos().z) {
|
||||
- if (entity != player && entity.chunkPosition().equals(chunk.getPos())) {
|
||||
- playerchunkmap_entitytracker.updatePlayer(player);
|
||||
- if (entity instanceof Mob && ((Mob) entity).getLeashHolder() != null) {
|
||||
- list.add(entity);
|
||||
@ -242,16 +247,7 @@ index 6c7af93cead523830d32b007cc69b313e59abef1..41147be189f764c2346cf015890a148f
|
||||
|
||||
Iterator iterator;
|
||||
Entity entity1;
|
||||
@@ -1782,7 +1884,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
|
||||
public class TrackedEntity {
|
||||
|
||||
- private final ServerEntity serverEntity;
|
||||
+ final ServerEntity serverEntity; // Paper - private -> package private
|
||||
private final Entity entity;
|
||||
private final int range;
|
||||
private SectionPos lastSectionPos;
|
||||
@@ -1799,6 +1901,42 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1837,6 +1939,42 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
|
||||
this.lastSectionPos = SectionPos.of(entity);
|
||||
}
|
||||
|
||||
@ -283,9 +279,9 @@ index 6c7af93cead523830d32b007cc69b313e59abef1..41147be189f764c2346cf015890a148f
|
||||
+ // stuff could have been removed, so we need to check the trackedPlayers set
|
||||
+ // for players that were removed
|
||||
+
|
||||
+ for (ServerPlayer player : this.seenBy.toArray(new ServerPlayer[0])) { // avoid CME
|
||||
+ if (newTrackerCandidates == null || !newTrackerCandidates.contains(player)) {
|
||||
+ this.updatePlayer(player);
|
||||
+ for (ServerPlayerConnection conn : this.seenBy.toArray(new ServerPlayerConnection[0])) { // avoid CME
|
||||
+ if (newTrackerCandidates == null || !newTrackerCandidates.contains(conn)) {
|
||||
+ this.updatePlayer(conn.getPlayer());
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
@ -294,7 +290,7 @@ index 6c7af93cead523830d32b007cc69b313e59abef1..41147be189f764c2346cf015890a148f
|
||||
public boolean equals(Object object) {
|
||||
return object instanceof ChunkMap.TrackedEntity ? ((ChunkMap.TrackedEntity) object).entity.getId() == this.entity.getId() : false;
|
||||
}
|
||||
@@ -1899,7 +2037,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1922,7 +2060,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
|
||||
int j = entity.getType().clientTrackingRange() * 16;
|
||||
j = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, j); // Paper
|
||||
|
||||
@ -304,10 +300,10 @@ index 6c7af93cead523830d32b007cc69b313e59abef1..41147be189f764c2346cf015890a148f
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java
|
||||
index 1609ab94c86e964421f996d4d46aef30f8b8e696..d797873db52ba265ac4478f9f3c6344badd4739e 100644
|
||||
index 28afe2f238ded241acf77c3272a44068646b9133..6b492b72b177e3c58580561585609b176876acf1 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerEntity.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
|
||||
@@ -100,6 +100,7 @@ public class ServerEntity {
|
||||
@@ -87,6 +87,7 @@ public class ServerEntity {
|
||||
this.wasOnGround = entity.isOnGround();
|
||||
}
|
||||
|
||||
@ -316,18 +312,18 @@ index 1609ab94c86e964421f996d4d46aef30f8b8e696..d797873db52ba265ac4478f9f3c6344b
|
||||
List<Entity> list = this.entity.getPassengers();
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index 2b48c4a2b512c42bed2c767db90a28898c74286a..d9bb00752ac81b2171d3ad25fd84904467a18e3b 100644
|
||||
index 9897a0ac66dd788b0b22a88b20ca86a386e397e4..dec5690bd90830bace704b553dbcd1d2633ab668 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -46,6 +46,7 @@ import net.minecraft.network.syncher.EntityDataSerializers;
|
||||
@@ -50,6 +50,7 @@ import net.minecraft.network.syncher.EntityDataSerializers;
|
||||
import net.minecraft.network.syncher.SynchedEntityData;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
+import net.minecraft.server.MCUtil;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ChunkMap;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
@@ -294,6 +295,21 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
@@ -322,6 +323,21 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
|
||||
}
|
||||
// CraftBukkit end
|
||||
|
||||
@ -348,20 +344,20 @@ index 2b48c4a2b512c42bed2c767db90a28898c74286a..d9bb00752ac81b2171d3ad25fd849044
|
||||
+
|
||||
public Entity(EntityType<?> type, Level world) {
|
||||
this.id = Entity.ENTITY_COUNTER.incrementAndGet();
|
||||
this.passengers = Lists.newArrayList();
|
||||
this.passengers = ImmutableList.of();
|
||||
diff --git a/src/main/java/org/spigotmc/TrackingRange.java b/src/main/java/org/spigotmc/TrackingRange.java
|
||||
index b03fa9024c7f0238e1379f6ae4486db5300a70e9..7b6011be849ecffdd791d439f70ae5dffc96f264 100644
|
||||
index 24b1dfcf91d36947c87e9e5c2524317f8775ba95..e5bcbfe175a697e04886d04543e1278b7e83a184 100644
|
||||
--- a/src/main/java/org/spigotmc/TrackingRange.java
|
||||
+++ b/src/main/java/org/spigotmc/TrackingRange.java
|
||||
@@ -20,6 +20,7 @@ public class TrackingRange
|
||||
*/
|
||||
public static int getEntityTrackingRange(Entity entity, int defaultRange)
|
||||
@@ -24,6 +24,7 @@ public class TrackingRange
|
||||
{
|
||||
return defaultRange;
|
||||
}
|
||||
+ if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon) return defaultRange; // Paper - enderdragon is exempt
|
||||
SpigotWorldConfig config = entity.level.spigotConfig;
|
||||
if ( entity instanceof ServerPlayer )
|
||||
{
|
||||
@@ -43,8 +44,48 @@ public class TrackingRange
|
||||
@@ -47,8 +48,48 @@ public class TrackingRange
|
||||
return config.miscTrackingRange;
|
||||
} else
|
||||
{
|
@ -6,12 +6,12 @@ Subject: [PATCH] Optimize isOutsideRange 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 d12d5459c847d3f0d655c85e31d81c27b7a2face..0147798c0285f64b8d767dfb2709d92f66ac72ef 100644
|
||||
index 58369d70bcd8b2c25609b6f101d9cbe2031df352..969b0c9cf6d7eb2055d3b804f25a3cbc161ceaea 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
@@ -69,6 +69,18 @@ public class ChunkHolder {
|
||||
long lastAutoSaveTime; // Paper - incremental autosave
|
||||
long inactiveTimeStart; // Paper - incremental autosave
|
||||
@@ -100,6 +100,18 @@ public class ChunkHolder {
|
||||
}
|
||||
// Paper end
|
||||
|
||||
+ // Paper start - optimise isOutsideOfRange
|
||||
+ // cached here to avoid a map lookup
|
||||
@ -25,22 +25,22 @@ index d12d5459c847d3f0d655c85e31d81c27b7a2face..0147798c0285f64b8d767dfb2709d92f
|
||||
+ }
|
||||
+ // Paper end - optimise isOutsideOfRange
|
||||
+
|
||||
public ChunkHolder(ChunkPos pos, int level, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) {
|
||||
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;
|
||||
@@ -85,6 +97,7 @@ public class ChunkHolder {
|
||||
this.queueLevel = this.oldTicketLevel;
|
||||
@@ -121,6 +133,7 @@ public class ChunkHolder {
|
||||
this.setTicketLevel(level);
|
||||
this.changedBlocksPerSection = new ShortSet[world.getSectionsCount()];
|
||||
this.chunkMap = (ChunkMap)playersWatchingChunkProvider; // Paper
|
||||
+ this.updateRanges(); // Paper - optimise isOutsideOfRange
|
||||
}
|
||||
|
||||
// Paper start
|
||||
// CraftBukkit start
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 41147be189f764c2346cf015890a148f9730bc0f..56ca469bf930bcced88efdafc78f464c756a5be9 100644
|
||||
index f7032e1d64afa6707756bb5a2af9d43a808c9736..18335e2c5c9e50a8ed31a3d2b585835bcc28bbe6 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -208,6 +208,17 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -237,6 +237,17 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
return MinecraftServer.getServer().applyTrackingRangeScale(vanilla);
|
||||
}
|
||||
// Paper end - use distance map to optimise tracker
|
||||
@ -58,17 +58,20 @@ index 41147be189f764c2346cf015890a148f9730bc0f..56ca469bf930bcced88efdafc78f464c
|
||||
|
||||
void addPlayerToDistanceMaps(ServerPlayer player) {
|
||||
int chunkX = MCUtil.getChunkCoordinate(player.getX());
|
||||
@@ -221,6 +232,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -250,6 +261,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
trackMap.add(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance()));
|
||||
}
|
||||
// Paper end - use distance map to optimise entity tracker
|
||||
+ // Paper start - optimise PlayerChunkMap#isOutsideRange
|
||||
+ this.playerChunkTickRangeMap.update(player, chunkX, chunkZ, DistanceManager.MOB_SPAWN_RANGE);
|
||||
+ // Paper end - optimise PlayerChunkMap#isOutsideRange
|
||||
+ // Paper start - optimise PlayerChunkMap#isOutsideRange
|
||||
+ this.playerChunkTickRangeMap.add(player, chunkX, chunkZ, DistanceManager.MOB_SPAWN_RANGE);
|
||||
+ // Paper end - optimise PlayerChunkMap#isOutsideRange
|
||||
}
|
||||
|
||||
void removePlayerFromDistanceMaps(ServerPlayer player) {
|
||||
@@ -229,6 +243,10 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
// Paper start - no-tick view distance
|
||||
int effectiveTickViewDistance = this.getEffectiveViewDistance();
|
||||
int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance);
|
||||
@@ -271,6 +288,10 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
this.playerEntityTrackerTrackMaps[i].remove(player);
|
||||
}
|
||||
// Paper end - use distance map to optimise tracker
|
||||
@ -76,29 +79,29 @@ index 41147be189f764c2346cf015890a148f9730bc0f..56ca469bf930bcced88efdafc78f464c
|
||||
+ this.playerMobSpawnMap.remove(player);
|
||||
+ this.playerChunkTickRangeMap.remove(player);
|
||||
+ // Paper end - optimise PlayerChunkMap#isOutsideRange
|
||||
}
|
||||
|
||||
void updateMaps(ServerPlayer player) {
|
||||
@@ -243,6 +261,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
// Paper start - no-tick view distance
|
||||
this.playerViewDistanceBroadcastMap.remove(player);
|
||||
this.playerViewDistanceTickMap.remove(player);
|
||||
@@ -290,6 +311,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
trackMap.update(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance()));
|
||||
}
|
||||
// Paper end - use distance map to optimise entity tracker
|
||||
+ // Paper start - optimise PlayerChunkMap#isOutsideRange
|
||||
+ this.playerChunkTickRangeMap.update(player, chunkX, chunkZ, DistanceManager.MOB_SPAWN_RANGE);
|
||||
+ // Paper end - optimise PlayerChunkMap#isOutsideRange
|
||||
}
|
||||
// Paper end
|
||||
|
||||
@@ -274,7 +295,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
this.worldgenMailbox = this.queueSorter.getProcessor(threadedmailbox, false);
|
||||
// Paper start - no-tick view distance
|
||||
int effectiveTickViewDistance = this.getEffectiveViewDistance();
|
||||
int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance);
|
||||
@@ -336,7 +360,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
this.mainThreadMailbox = this.queueSorter.getProcessor(mailbox, false);
|
||||
this.mailboxLight = this.queueSorter.getProcessor(lightthreaded, false);// Paper
|
||||
this.lightEngine = new ThreadedLevelLightEngine(chunkProvider, this, this.level.dimensionType().hasSkyLight(), threadedmailbox1, this.queueSorter.getProcessor(threadedmailbox1, false));
|
||||
- this.distanceManager = new ChunkMap.ChunkDistanceManager(workerExecutor, mainThreadExecutor);
|
||||
+ this.distanceManager = new ChunkMap.ChunkDistanceManager(workerExecutor, mainThreadExecutor); this.distanceManager.chunkMap = this; // Paper
|
||||
this.overworldDataStorage = supplier;
|
||||
this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, flag, this.level); // Paper
|
||||
this.setViewDistance(i);
|
||||
@@ -318,6 +339,38 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
- this.distanceManager = new ChunkMap.ChunkDistanceManager(executor, mainThreadExecutor);
|
||||
+ this.distanceManager = new ChunkMap.ChunkDistanceManager(executor, mainThreadExecutor); this.distanceManager.chunkMap = this; // Paper
|
||||
this.overworldDataStorage = persistentStateManagerFactory;
|
||||
this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, dsync, world);
|
||||
this.setViewDistance(viewDistance);
|
||||
@@ -380,6 +404,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
|
||||
@ -134,18 +137,10 @@ index 41147be189f764c2346cf015890a148f9730bc0f..56ca469bf930bcced88efdafc78f464c
|
||||
+ }
|
||||
+ });
|
||||
+ // Paper end - optimise PlayerChunkMap#isOutsideRange
|
||||
}
|
||||
|
||||
public void updatePlayerMobTypeMap(Entity entity) {
|
||||
@@ -337,6 +390,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
return entityPlayer.mobCounts[enumCreatureType.ordinal()];
|
||||
}
|
||||
|
||||
+ private static double getDistanceSquaredFromChunk(ChunkPos chunkPos, Entity entity) { return euclideanDistanceSquared(chunkPos, entity); } // Paper - OBFHELPER
|
||||
private static double euclideanDistanceSquared(ChunkPos pos, Entity entity) {
|
||||
double d0 = (double) (pos.x * 16 + 8);
|
||||
double d1 = (double) (pos.z * 16 + 8);
|
||||
@@ -515,6 +569,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
// Paper start - no-tick view distance
|
||||
this.setNoTickViewDistance(this.level.paperConfig.noTickViewDistance);
|
||||
this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets,
|
||||
@@ -649,6 +705,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
} else {
|
||||
if (holder != null) {
|
||||
holder.setTicketLevel(level);
|
||||
@ -153,46 +148,40 @@ index 41147be189f764c2346cf015890a148f9730bc0f..56ca469bf930bcced88efdafc78f464c
|
||||
}
|
||||
|
||||
if (holder != null) {
|
||||
@@ -1493,30 +1548,53 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
return isOutsideOfRange(chunkcoordintpair, false);
|
||||
@@ -1434,29 +1491,50 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
return this.isOutsideOfRange(chunkPos, false);
|
||||
}
|
||||
|
||||
- boolean isOutsideOfRange(ChunkPos chunkcoordintpair, boolean reducedRange) {
|
||||
- int chunkRange = level.spigotConfig.mobSpawnRange;
|
||||
- chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.spigotConfig.viewDistance : chunkRange;
|
||||
- chunkRange = (chunkRange > 8) ? 8 : chunkRange;
|
||||
+ // Paper start - optimise isOutsideOfRange
|
||||
+ final boolean isOutsideOfRange(ChunkPos chunkcoordintpair, boolean reducedRange) {
|
||||
+ return this.isOutsideOfRange(this.getUpdatingChunkIfPresent(chunkcoordintpair.toLong()), chunkcoordintpair, reducedRange);
|
||||
+ }
|
||||
|
||||
-
|
||||
- final int finalChunkRange = chunkRange; // Paper for lambda below
|
||||
- //double blockRange = (reducedRange) ? Math.pow(chunkRange << 4, 2) : 16384.0D; // Paper - use from event
|
||||
- // Spigot end
|
||||
- long i = chunkcoordintpair.toLong();
|
||||
+ // Paper start - optimise isOutsideOfRange
|
||||
+ final boolean isOutsideOfRange(ChunkPos chunkcoordintpair, boolean reducedRange) {
|
||||
+ return this.isOutsideOfRange(this.getUpdatingChunkIfPresent(chunkcoordintpair.toLong()), chunkcoordintpair, reducedRange);
|
||||
+ }
|
||||
+ final boolean isOutsideOfRange(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 true;
|
||||
+ }
|
||||
+ Object[] backingSet = playersInRange.getBackingSet();
|
||||
|
||||
- return !this.distanceManager.hasPlayersNearby(i) ? true : this.playerMap.a(i).noneMatch((entityplayer) -> {
|
||||
- // Paper start -
|
||||
- return !this.distanceManager.hasPlayersNearby(i) ? true : this.playerMap.getPlayers(i).noneMatch((entityplayer) -> {
|
||||
- // Paper start - add PlayerNaturallySpawnCreaturesEvent
|
||||
- com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event;
|
||||
- double blockRange = 16384.0D;
|
||||
- if (reducedRange) {
|
||||
- event = entityplayer.playerNaturallySpawnedEvent;
|
||||
- if (event == null || event.isCancelled()) return false;
|
||||
- blockRange = (double) ((event.getSpawnRadius() << 4) * (event.getSpawnRadius() << 4));
|
||||
- }
|
||||
+ if (playersInRange == null) {
|
||||
+ return true;
|
||||
+ }
|
||||
|
||||
- return (!entityplayer.isSpectator() && a(chunkcoordintpair, (Entity) entityplayer) < blockRange); // Spigot
|
||||
- // Paper end
|
||||
- });
|
||||
+ Object[] backingSet = playersInRange.getBackingSet();
|
||||
+
|
||||
+ if (reducedRange) {
|
||||
+ for (int i = 0, len = backingSet.length; i < len; ++i) {
|
||||
+ Object raw = backingSet[i];
|
||||
@ -201,10 +190,13 @@ index 41147be189f764c2346cf015890a148f9730bc0f..56ca469bf930bcced88efdafc78f464c
|
||||
+ }
|
||||
+ ServerPlayer player = (ServerPlayer) raw;
|
||||
+ // don't check spectator and whatnot, already handled by mob spawn map update
|
||||
+ if (player.lastEntitySpawnRadiusSquared > getDistanceSquaredFromChunk(chunkcoordintpair, player)) {
|
||||
+ if (player.lastEntitySpawnRadiusSquared > euclideanDistanceSquared(chunkcoordintpair, player)) {
|
||||
+ return false; // in range
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
- // Paper end
|
||||
- return !entityplayer.isSpectator() && ChunkMap.euclideanDistanceSquared(chunkcoordintpair, (Entity) entityplayer) < blockRange; // Spigot
|
||||
- });
|
||||
+ } 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
|
||||
@ -215,7 +207,7 @@ index 41147be189f764c2346cf015890a148f9730bc0f..56ca469bf930bcced88efdafc78f464c
|
||||
+ }
|
||||
+ ServerPlayer player = (ServerPlayer) raw;
|
||||
+ // don't check spectator and whatnot, already handled by mob spawn map update
|
||||
+ if (range > getDistanceSquaredFromChunk(chunkcoordintpair, player)) {
|
||||
+ if (range > euclideanDistanceSquared(chunkcoordintpair, player)) {
|
||||
+ return false; // in range
|
||||
+ }
|
||||
+ }
|
||||
@ -228,11 +220,11 @@ index 41147be189f764c2346cf015890a148f9730bc0f..56ca469bf930bcced88efdafc78f464c
|
||||
private boolean skipPlayer(ServerPlayer player) {
|
||||
return player.isSpectator() && !this.level.getGameRules().getBoolean(GameRules.RULE_SPECTATORSGENERATECHUNKS);
|
||||
diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java
|
||||
index 90429d3f5c5b725098cfb001d54c70608f3df7bb..91c672531087430c47365657a3219ab5980d3467 100644
|
||||
index b49d380ef088aed3204ec71abc437c348ef004fa..577b391dcba1db712c1e2c83296e1c87b3e34ab2 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/DistanceManager.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/DistanceManager.java
|
||||
@@ -37,7 +37,7 @@ public abstract class DistanceManager {
|
||||
private final Long2ObjectMap<ObjectSet<ServerPlayer>> playersPerChunk = new Long2ObjectOpenHashMap();
|
||||
@@ -45,7 +45,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);
|
||||
@ -240,25 +232,25 @@ index 90429d3f5c5b725098cfb001d54c70608f3df7bb..91c672531087430c47365657a3219ab5
|
||||
private final DistanceManager.PlayerTicketTracker playerTicketManager = new DistanceManager.PlayerTicketTracker(33);
|
||||
// Paper start use a queue, but still keep unique requirement
|
||||
public final java.util.Queue<ChunkHolder> pendingChunkUpdates = new java.util.ArrayDeque<ChunkHolder>() {
|
||||
@@ -56,6 +56,8 @@ public abstract class DistanceManager {
|
||||
private final Executor mainThreadExecutor;
|
||||
@@ -64,6 +64,8 @@ public abstract class DistanceManager {
|
||||
final Executor mainThreadExecutor;
|
||||
private long ticketTickCounter;
|
||||
|
||||
+ ChunkMap chunkMap; // Paper
|
||||
+
|
||||
protected DistanceManager(Executor workerExecutor, Executor mainThreadExecutor) {
|
||||
mainThreadExecutor.getClass();
|
||||
Objects.requireNonNull(mainThreadExecutor);
|
||||
ProcessorHandle<Runnable> mailbox = ProcessorHandle.of("player ticket throttler", mainThreadExecutor::execute);
|
||||
@@ -100,7 +102,7 @@ public abstract class DistanceManager {
|
||||
@@ -108,7 +110,7 @@ public abstract class DistanceManager {
|
||||
protected abstract ChunkHolder updateChunkScheduling(long pos, int level, @Nullable ChunkHolder holder, int k);
|
||||
|
||||
public boolean runAllUpdates(ChunkMap chunkStorage) {
|
||||
public boolean runAllUpdates(ChunkMap playerchunkmap) {
|
||||
- this.naturalSpawnChunkCounter.runAllUpdates();
|
||||
+ //this.f.a(); // Paper - no longer used
|
||||
this.playerTicketManager.runAllUpdates();
|
||||
int i = Integer.MAX_VALUE - this.ticketTracker.runDistanceUpdates(Integer.MAX_VALUE);
|
||||
boolean flag = i != 0;
|
||||
@@ -236,7 +238,7 @@ public abstract class DistanceManager {
|
||||
@@ -244,7 +246,7 @@ public abstract class DistanceManager {
|
||||
((ObjectSet) this.playersPerChunk.computeIfAbsent(i, (j) -> {
|
||||
return new ObjectOpenHashSet();
|
||||
})).add(player);
|
||||
@ -267,7 +259,7 @@ index 90429d3f5c5b725098cfb001d54c70608f3df7bb..91c672531087430c47365657a3219ab5
|
||||
this.playerTicketManager.update(i, 0, true);
|
||||
}
|
||||
|
||||
@@ -248,7 +250,7 @@ public abstract class DistanceManager {
|
||||
@@ -256,7 +258,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);
|
||||
@ -276,7 +268,7 @@ index 90429d3f5c5b725098cfb001d54c70608f3df7bb..91c672531087430c47365657a3219ab5
|
||||
this.playerTicketManager.update(i, Integer.MAX_VALUE, false);
|
||||
}
|
||||
|
||||
@@ -272,13 +274,17 @@ public abstract class DistanceManager {
|
||||
@@ -280,13 +282,17 @@ public abstract class DistanceManager {
|
||||
}
|
||||
|
||||
public int getNaturalSpawnChunkCount() {
|
||||
@ -299,11 +291,11 @@ index 90429d3f5c5b725098cfb001d54c70608f3df7bb..91c672531087430c47365657a3219ab5
|
||||
|
||||
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 79fb63c40dd0543a6f629e78f390f23f34992ba1..52c2e81f2e2bcd74d4e9aac3ecb5ab618e289abd 100644
|
||||
index 3d1c4f8e0db37c6dabece657a17595e7bf1e3dc2..3faa808f41f057a9956c697ec1323330f5920b86 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -753,6 +753,37 @@ public class ServerChunkCache extends ChunkSource {
|
||||
boolean flag1 = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !level.players().isEmpty(); // CraftBukkit
|
||||
@@ -729,6 +729,37 @@ public class ServerChunkCache extends ChunkSource {
|
||||
boolean flag1 = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit
|
||||
|
||||
if (!flag) {
|
||||
+ // Paper start - optimize isOutisdeRange
|
||||
@ -340,7 +332,7 @@ index 79fb63c40dd0543a6f629e78f390f23f34992ba1..52c2e81f2e2bcd74d4e9aac3ecb5ab61
|
||||
this.level.getProfiler().push("pollingChunks");
|
||||
int k = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING);
|
||||
boolean flag2 = level.ticksPerAnimalSpawns != 0L && worlddata.getGameTime() % level.ticksPerAnimalSpawns == 0L; // CraftBukkit
|
||||
@@ -782,15 +813,7 @@ public class ServerChunkCache extends ChunkSource {
|
||||
@@ -758,15 +789,7 @@ public class ServerChunkCache extends ChunkSource {
|
||||
this.level.getProfiler().pop();
|
||||
//List<PlayerChunk> list = Lists.newArrayList(this.playerChunkMap.f()); // Paper
|
||||
//Collections.shuffle(list); // Paper
|
||||
@ -357,28 +349,27 @@ index 79fb63c40dd0543a6f629e78f390f23f34992ba1..52c2e81f2e2bcd74d4e9aac3ecb5ab61
|
||||
this.level.timings.chunkTicks.startTiming(); // Paper
|
||||
final int[] chunksTicked = {0}; this.chunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping
|
||||
Optional<LevelChunk> optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left();
|
||||
@@ -807,9 +830,9 @@ public class ServerChunkCache extends ChunkSource {
|
||||
LevelChunk chunk = (LevelChunk) optional1.get();
|
||||
ChunkPos chunkcoordintpair = playerchunk.getPos();
|
||||
@@ -781,9 +804,9 @@ public class ServerChunkCache extends ChunkSource {
|
||||
this.level.getProfiler().pop();
|
||||
ChunkPos chunkcoordintpair = chunk.getPos();
|
||||
|
||||
- if (!this.chunkMap.noPlayersCloseForSpawning(chunkcoordintpair)) {
|
||||
+ if (!this.chunkMap.isOutsideOfRange(playerchunk, chunkcoordintpair, false)) { // Paper - optimise isOutsideOfRange
|
||||
- if (this.level.isPositionEntityTicking(chunkcoordintpair) && !this.chunkMap.noPlayersCloseForSpawning(chunkcoordintpair)) {
|
||||
+ if (this.level.isPositionEntityTicking(chunkcoordintpair) && !this.chunkMap.isOutsideOfRange(playerchunk, chunkcoordintpair, false)) { // Paper - optimise isOutsideOfRange
|
||||
chunk.setInhabitedTime(chunk.getInhabitedTime() + j);
|
||||
- if (flag1 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunk.getPos()) && !this.chunkMap.isOutsideOfRange(chunkcoordintpair, true)) { // Spigot
|
||||
+ if (flag1 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunk.getPos()) && !this.chunkMap.isOutsideOfRange(playerchunk, chunkcoordintpair, true)) { // Spigot // Paper - optimise isOutsideOfRange
|
||||
NaturalSpawner.spawnForChunk(this.level, chunk, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag2);
|
||||
if (chunksTicked[0]++ % 10 == 0) this.level.getServer().midTickLoadChunks(); // Paper
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 24c508ade61a6ad90b0ef73cdc995f531ef18263..95f1f4727a8e2000931e6f36b862e3ad28334a69 100644
|
||||
index c083ee1322f86809300fce1552eacd663aaa650d..cd34b5aa61c78d8138500a93f0a9714bedd7ed86 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -247,6 +247,8 @@ public class ServerPlayer extends Player implements ContainerListener {
|
||||
@@ -244,6 +244,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
|
||||
boolean needsChunkCenterUpdate; // Paper - no-tick view distance
|
||||
|
||||
+ double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks
|
||||
+
|
||||
public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ServerPlayerGameMode interactionManager) {
|
||||
super(world, world.getSpawn(), world.getSharedSpawnAngle(), profile);
|
||||
this.respawnDimension = Level.OVERWORLD;
|
In neuem Issue referenzieren
Einen Benutzer sperren