mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-22 17:07:34 +01:00
Optimise chunk tick iteration
When per-player mob spawning is enabled we do not need to randomly shuffle the chunk list. Additionally, we can use the NearbyPlayers class to quickly retrieve nearby players instead of possible searching all players on the server.
This commit is contained in:
parent
8d922746d9
commit
38dc3b25d8
@ -1,346 +0,0 @@
|
||||
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
|
@ -1,215 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Thu, 7 May 2020 05:48:54 -0700
|
||||
Subject: [PATCH] Optimise chunk tick iteration
|
||||
|
||||
Use a dedicated list of entity ticking chunks to reduce the cost
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
index 4164204ba80f68a768de0ed1721c6447b972a631..4ae1ba645d9fdc1eb6d5a3e4f8ceed9b4841e003 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
@@ -84,6 +84,11 @@ public class ChunkHolder {
|
||||
this.playersInMobSpawnRange = this.chunkMap.playerMobSpawnMap.getObjectsInRange(key);
|
||||
this.playersInChunkTickRange = this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(key);
|
||||
// Paper end - optimise anyPlayerCloseEnoughForSpawning
|
||||
+ // Paper start - optimise chunk tick iteration
|
||||
+ if (this.needsBroadcastChanges()) {
|
||||
+ this.chunkMap.needsChangeBroadcasting.add(this);
|
||||
+ }
|
||||
+ // Paper end - optimise chunk tick iteration
|
||||
}
|
||||
|
||||
public void onChunkRemove() {
|
||||
@@ -91,6 +96,11 @@ public class ChunkHolder {
|
||||
this.playersInMobSpawnRange = null;
|
||||
this.playersInChunkTickRange = null;
|
||||
// Paper end - optimise anyPlayerCloseEnoughForSpawning
|
||||
+ // Paper start - optimise chunk tick iteration
|
||||
+ if (this.needsBroadcastChanges()) {
|
||||
+ this.chunkMap.needsChangeBroadcasting.remove(this);
|
||||
+ }
|
||||
+ // Paper end - optimise chunk tick iteration
|
||||
}
|
||||
// Paper end
|
||||
|
||||
@@ -230,7 +240,7 @@ public class ChunkHolder {
|
||||
|
||||
if (i < 0 || i >= this.changedBlocksPerSection.length) return; // CraftBukkit - SPIGOT-6086, SPIGOT-6296
|
||||
if (this.changedBlocksPerSection[i] == null) {
|
||||
- this.hasChangedSections = true;
|
||||
+ this.hasChangedSections = true; this.addToBroadcastMap(); // Paper - optimise chunk tick iteration
|
||||
this.changedBlocksPerSection[i] = new ShortOpenHashSet();
|
||||
}
|
||||
|
||||
@@ -254,6 +264,7 @@ public class ChunkHolder {
|
||||
int k = this.lightEngine.getMaxLightSection();
|
||||
|
||||
if (y >= j && y <= k) {
|
||||
+ this.addToBroadcastMap(); // Paper - optimise chunk tick iteration
|
||||
int l = y - j;
|
||||
|
||||
if (lightType == LightLayer.SKY) {
|
||||
@@ -268,8 +279,19 @@ public class ChunkHolder {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start - optimise chunk tick iteration
|
||||
+ public final boolean needsBroadcastChanges() {
|
||||
+ return this.hasChangedSections || !this.skyChangedLightSectionFilter.isEmpty() || !this.blockChangedLightSectionFilter.isEmpty();
|
||||
+ }
|
||||
+
|
||||
+ private void addToBroadcastMap() {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("ChunkHolder update");
|
||||
+ this.chunkMap.needsChangeBroadcasting.add(this);
|
||||
+ }
|
||||
+ // Paper end - optimise chunk tick iteration
|
||||
+
|
||||
public void broadcastChanges(LevelChunk chunk) {
|
||||
- if (this.hasChangedSections || !this.skyChangedLightSectionFilter.isEmpty() || !this.blockChangedLightSectionFilter.isEmpty()) {
|
||||
+ if (this.needsBroadcastChanges()) { // Paper - moved into above, other logic needs to call
|
||||
Level world = chunk.getLevel();
|
||||
List list;
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 80b2ff12e48e1aabebd9ebcf5958c1f5d073d55b..bcf0dfe50add8e260a280e45673727f964bac6fd 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -115,6 +115,8 @@ import org.bukkit.craftbukkit.generator.CustomChunkGenerator;
|
||||
import org.bukkit.entity.Player;
|
||||
// CraftBukkit end
|
||||
|
||||
+import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; // Paper
|
||||
+
|
||||
public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider {
|
||||
|
||||
private static final byte CHUNK_TYPE_REPLACEABLE = -1;
|
||||
@@ -152,6 +154,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
private final Queue<Runnable> unloadQueue;
|
||||
int viewDistance;
|
||||
public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerMobDistanceMap; // Paper
|
||||
+ public final ReferenceOpenHashSet<ChunkHolder> needsChangeBroadcasting = new ReferenceOpenHashSet<>();
|
||||
|
||||
// Paper - rewrite chunk system
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
index 5c5fe2087a7617324ab8e18389e3ffa9ac413026..828de28f2777e2477a9c6545c8af96c4ca4e352b 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -48,6 +48,7 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemp
|
||||
import net.minecraft.world.level.storage.DimensionDataStorage;
|
||||
import net.minecraft.world.level.storage.LevelData;
|
||||
import net.minecraft.world.level.storage.LevelStorageSource;
|
||||
+import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; // Paper
|
||||
|
||||
public class ServerChunkCache extends ChunkSource {
|
||||
|
||||
@@ -574,42 +575,59 @@ public class ServerChunkCache extends ChunkSource {
|
||||
|
||||
this.lastSpawnState = spawnercreature_d;
|
||||
gameprofilerfiller.popPush("filteringLoadedChunks");
|
||||
- List<ServerChunkCache.ChunkAndHolder> list = Lists.newArrayListWithCapacity(l);
|
||||
- Iterator iterator = this.chunkMap.getChunks().iterator();
|
||||
+ // Paper - moved down
|
||||
this.level.timings.chunkTicks.startTiming(); // Paper
|
||||
|
||||
- while (iterator.hasNext()) {
|
||||
- ChunkHolder playerchunk = (ChunkHolder) iterator.next();
|
||||
- LevelChunk chunk = playerchunk.getTickingChunk();
|
||||
-
|
||||
- if (chunk != null) {
|
||||
- list.add(new ServerChunkCache.ChunkAndHolder(chunk, playerchunk));
|
||||
- }
|
||||
- }
|
||||
+ // Paper - moved down
|
||||
|
||||
gameprofilerfiller.popPush("spawnAndTick");
|
||||
boolean flag2 = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit
|
||||
|
||||
- Collections.shuffle(list);
|
||||
+ // Paper - only shuffle if per-player mob spawning is disabled
|
||||
// Paper - moved natural spawn event up
|
||||
- Iterator iterator1 = list.iterator();
|
||||
|
||||
+ // Paper start - optimise chunk tick iteratio
|
||||
+ Iterator<LevelChunk> iterator1;
|
||||
+ if (this.level.paperConfig().entities.spawning.perPlayerMobSpawns) {
|
||||
+ iterator1 = this.entityTickingChunks.iterator();
|
||||
+ } else {
|
||||
+ iterator1 = this.entityTickingChunks.unsafeIterator();
|
||||
+ List<LevelChunk> shuffled = Lists.newArrayListWithCapacity(this.entityTickingChunks.size());
|
||||
+ while (iterator1.hasNext()) {
|
||||
+ shuffled.add(iterator1.next());
|
||||
+ }
|
||||
+ Collections.shuffle(shuffled);
|
||||
+ iterator1 = shuffled.iterator();
|
||||
+ }
|
||||
+ try {
|
||||
while (iterator1.hasNext()) {
|
||||
- ServerChunkCache.ChunkAndHolder chunkproviderserver_a = (ServerChunkCache.ChunkAndHolder) iterator1.next();
|
||||
- LevelChunk chunk1 = chunkproviderserver_a.chunk;
|
||||
+ LevelChunk chunk1 = iterator1.next();
|
||||
+ ChunkHolder holder = chunk1.playerChunk;
|
||||
+ if (holder != null) {
|
||||
+ // Paper - move down
|
||||
+ // Paper end - optimise chunk tick iteration
|
||||
ChunkPos chunkcoordintpair = chunk1.getPos();
|
||||
|
||||
- if (this.level.isNaturalSpawningAllowed(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkproviderserver_a.holder, chunkcoordintpair, false)) { // Paper - optimise anyPlayerCloseEnoughForSpawning
|
||||
+ if ((true || this.level.isNaturalSpawningAllowed(chunkcoordintpair)) && this.chunkMap.anyPlayerCloseEnoughForSpawning(holder, chunkcoordintpair, false)) { // Paper - optimise anyPlayerCloseEnoughForSpawning // Paper - the chunk is known ticking
|
||||
chunk1.incrementInhabitedTime(j);
|
||||
- if (flag2 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkproviderserver_a.holder, chunkcoordintpair, true)) { // Spigot // Paper - optimise anyPlayerCloseEnoughForSpawning
|
||||
+ if (flag2 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(holder, chunkcoordintpair, true)) { // Spigot // Paper - optimise anyPlayerCloseEnoughForSpawning & optimise chunk tick iteration
|
||||
NaturalSpawner.spawnForChunk(this.level, chunk1, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag1);
|
||||
}
|
||||
|
||||
- if (this.level.shouldTickBlocksAt(chunkcoordintpair.toLong())) {
|
||||
+ if (true || this.level.shouldTickBlocksAt(chunkcoordintpair.toLong())) { // Paper - the chunk is known ticking
|
||||
this.level.tickChunk(chunk1, k);
|
||||
}
|
||||
}
|
||||
+ // Paper start - optimise chunk tick iteration
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ } finally {
|
||||
+ if (iterator1 instanceof io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet.Iterator safeIterator) {
|
||||
+ safeIterator.finishedIterating();
|
||||
+ }
|
||||
}
|
||||
+ // Paper end - optimise chunk tick iteration
|
||||
this.level.timings.chunkTicks.stopTiming(); // Paper
|
||||
gameprofilerfiller.popPush("customSpawners");
|
||||
if (flag2) {
|
||||
@@ -617,15 +635,24 @@ public class ServerChunkCache extends ChunkSource {
|
||||
this.level.tickCustomSpawners(this.spawnEnemies, this.spawnFriendlies);
|
||||
} // Paper - timings
|
||||
}
|
||||
-
|
||||
- gameprofilerfiller.popPush("broadcast");
|
||||
- list.forEach((chunkproviderserver_a1) -> {
|
||||
- this.level.timings.broadcastChunkUpdates.startTiming(); // Paper - timing
|
||||
- chunkproviderserver_a1.holder.broadcastChanges(chunkproviderserver_a1.chunk);
|
||||
- this.level.timings.broadcastChunkUpdates.stopTiming(); // Paper - timing
|
||||
- });
|
||||
gameprofilerfiller.pop();
|
||||
+ // Paper start - use set of chunks requiring updates, rather than iterating every single one loaded
|
||||
+ gameprofilerfiller.popPush("broadcast");
|
||||
+ this.level.timings.broadcastChunkUpdates.startTiming(); // Paper - timing
|
||||
+ if (!this.chunkMap.needsChangeBroadcasting.isEmpty()) {
|
||||
+ ReferenceOpenHashSet<ChunkHolder> copy = this.chunkMap.needsChangeBroadcasting.clone();
|
||||
+ this.chunkMap.needsChangeBroadcasting.clear();
|
||||
+ for (ChunkHolder holder : copy) {
|
||||
+ holder.broadcastChanges(holder.getFullChunkNowUnchecked()); // LevelChunks are NEVER unloaded
|
||||
+ if (holder.needsBroadcastChanges()) {
|
||||
+ // I DON'T want to KNOW what DUMB plugins might be doing.
|
||||
+ this.chunkMap.needsChangeBroadcasting.add(holder);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ this.level.timings.broadcastChunkUpdates.stopTiming(); // Paper - timing
|
||||
gameprofilerfiller.pop();
|
||||
+ // Paper end - use set of chunks requiring updates, rather than iterating every single one loaded
|
||||
this.chunkMap.tick();
|
||||
}
|
||||
}
|
@ -5467,6 +5467,453 @@ index 0000000000000000000000000000000000000000..808d1449ac44ae86a650932365081fba
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/util/player/NearbyPlayers.java b/src/main/java/io/papermc/paper/util/player/NearbyPlayers.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..60c7680d678f9dc6a6a3109b1f6af8150ccd9100
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/util/player/NearbyPlayers.java
|
||||
@@ -0,0 +1,203 @@
|
||||
+package io.papermc.paper.util.player;
|
||||
+
|
||||
+import com.destroystokyo.paper.util.maplist.ReferenceList;
|
||||
+import io.papermc.paper.chunk.system.ChunkSystem;
|
||||
+import io.papermc.paper.util.CoordinateUtils;
|
||||
+import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap;
|
||||
+import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap;
|
||||
+import net.minecraft.core.BlockPos;
|
||||
+import net.minecraft.server.level.ServerLevel;
|
||||
+import net.minecraft.server.level.ServerPlayer;
|
||||
+import net.minecraft.world.level.ChunkPos;
|
||||
+
|
||||
+public final class NearbyPlayers {
|
||||
+
|
||||
+ public static enum NearbyMapType {
|
||||
+ GENERAL,
|
||||
+ GENERAL_SMALL,
|
||||
+ GENERAL_REALLY_SMALL,
|
||||
+ TICK_VIEW_DISTANCE,
|
||||
+ VIEW_DISTANCE;
|
||||
+ }
|
||||
+
|
||||
+ private static final NearbyMapType[] MOB_TYPES = NearbyMapType.values();
|
||||
+ public static final int TOTAL_MAP_TYPES = MOB_TYPES.length;
|
||||
+
|
||||
+ private static final int GENERAL_AREA_VIEW_DISTANCE = 33;
|
||||
+ private static final int GENERAL_SMALL_VIEW_DISTANCE = 10;
|
||||
+ private static final int GENERAL_REALLY_SMALL_VIEW_DISTANCE = 3;
|
||||
+
|
||||
+ public static final int GENERAL_AREA_VIEW_DISTANCE_BLOCKS = (GENERAL_AREA_VIEW_DISTANCE << 4);
|
||||
+ public static final int GENERAL_SMALL_AREA_VIEW_DISTANCE_BLOCKS = (GENERAL_SMALL_VIEW_DISTANCE << 4);
|
||||
+ public static final int GENERAL_REALLY_SMALL_AREA_VIEW_DISTANCE_BLOCKS = (GENERAL_REALLY_SMALL_VIEW_DISTANCE << 4);
|
||||
+
|
||||
+ private final ServerLevel world;
|
||||
+ private final Reference2ReferenceOpenHashMap<ServerPlayer, TrackedPlayer[]> players = new Reference2ReferenceOpenHashMap<>();
|
||||
+ private final Long2ReferenceOpenHashMap<TrackedChunk> byChunk = new Long2ReferenceOpenHashMap<>();
|
||||
+
|
||||
+ public NearbyPlayers(final ServerLevel world) {
|
||||
+ this.world = world;
|
||||
+ }
|
||||
+
|
||||
+ public void addPlayer(final ServerPlayer player) {
|
||||
+ final TrackedPlayer[] newTrackers = new TrackedPlayer[TOTAL_MAP_TYPES];
|
||||
+ if (this.players.put(player, newTrackers) != null) {
|
||||
+ throw new IllegalStateException("Already have player " + player);
|
||||
+ }
|
||||
+
|
||||
+ final ChunkPos chunk = player.chunkPosition();
|
||||
+
|
||||
+ for (int i = 0; i < TOTAL_MAP_TYPES; ++i) {
|
||||
+ // use 0 for default, will be updated by tickPlayer
|
||||
+ (newTrackers[i] = new TrackedPlayer(player, MOB_TYPES[i])).add(chunk.x, chunk.z, 0);
|
||||
+ }
|
||||
+
|
||||
+ // update view distances
|
||||
+ this.tickPlayer(player);
|
||||
+ }
|
||||
+
|
||||
+ public void removePlayer(final ServerPlayer player) {
|
||||
+ final TrackedPlayer[] players = this.players.remove(player);
|
||||
+ if (players == null) {
|
||||
+ throw new IllegalStateException("Don't have player " + player);
|
||||
+ }
|
||||
+
|
||||
+ for (final TrackedPlayer tracker : players) {
|
||||
+ tracker.remove();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public void tickPlayer(final ServerPlayer player) {
|
||||
+ final TrackedPlayer[] players = this.players.get(player);
|
||||
+ if (players == null) {
|
||||
+ throw new IllegalStateException("Don't have player " + player);
|
||||
+ }
|
||||
+
|
||||
+ final ChunkPos chunk = player.chunkPosition();
|
||||
+
|
||||
+ players[NearbyMapType.GENERAL.ordinal()].update(chunk.x, chunk.z, GENERAL_AREA_VIEW_DISTANCE);
|
||||
+ players[NearbyMapType.GENERAL_SMALL.ordinal()].update(chunk.x, chunk.z, GENERAL_SMALL_VIEW_DISTANCE);
|
||||
+ players[NearbyMapType.GENERAL_REALLY_SMALL.ordinal()].update(chunk.x, chunk.z, GENERAL_REALLY_SMALL_VIEW_DISTANCE);
|
||||
+ players[NearbyMapType.TICK_VIEW_DISTANCE.ordinal()].update(chunk.x, chunk.z, ChunkSystem.getTickViewDistance(player));
|
||||
+ players[NearbyMapType.VIEW_DISTANCE.ordinal()].update(chunk.x, chunk.z, ChunkSystem.getLoadViewDistance(player));
|
||||
+ }
|
||||
+
|
||||
+ public TrackedChunk getChunk(final ChunkPos pos) {
|
||||
+ return this.byChunk.get(CoordinateUtils.getChunkKey(pos));
|
||||
+ }
|
||||
+
|
||||
+ public TrackedChunk getChunk(final BlockPos pos) {
|
||||
+ return this.byChunk.get(CoordinateUtils.getChunkKey(pos));
|
||||
+ }
|
||||
+
|
||||
+ public ReferenceList<ServerPlayer> getPlayers(final BlockPos pos, final NearbyMapType type) {
|
||||
+ final TrackedChunk chunk = this.byChunk.get(CoordinateUtils.getChunkKey(pos));
|
||||
+
|
||||
+ return chunk == null ? null : chunk.players[type.ordinal()];
|
||||
+ }
|
||||
+
|
||||
+ public ReferenceList<ServerPlayer> getPlayers(final ChunkPos pos, final NearbyMapType type) {
|
||||
+ final TrackedChunk chunk = this.byChunk.get(CoordinateUtils.getChunkKey(pos));
|
||||
+
|
||||
+ return chunk == null ? null : chunk.players[type.ordinal()];
|
||||
+ }
|
||||
+
|
||||
+ public ReferenceList<ServerPlayer> getPlayersByChunk(final int chunkX, final int chunkZ, final NearbyMapType type) {
|
||||
+ final TrackedChunk chunk = this.byChunk.get(CoordinateUtils.getChunkKey(chunkX, chunkZ));
|
||||
+
|
||||
+ return chunk == null ? null : chunk.players[type.ordinal()];
|
||||
+ }
|
||||
+
|
||||
+ public ReferenceList<ServerPlayer> getPlayersByBlock(final int blockX, final int blockZ, final NearbyMapType type) {
|
||||
+ final TrackedChunk chunk = this.byChunk.get(CoordinateUtils.getChunkKey(blockX >> 4, blockZ >> 4));
|
||||
+
|
||||
+ return chunk == null ? null : chunk.players[type.ordinal()];
|
||||
+ }
|
||||
+
|
||||
+ public static final class TrackedChunk {
|
||||
+
|
||||
+ public final ReferenceList<ServerPlayer>[] players = new ReferenceList[TOTAL_MAP_TYPES];
|
||||
+ private int nonEmptyLists;
|
||||
+ private int updateCount;
|
||||
+
|
||||
+ public boolean isEmpty() {
|
||||
+ return this.nonEmptyLists == 0;
|
||||
+ }
|
||||
+
|
||||
+ public int getUpdateCount() {
|
||||
+ return this.updateCount;
|
||||
+ }
|
||||
+
|
||||
+ public ReferenceList<ServerPlayer> getPlayers(final NearbyMapType type) {
|
||||
+ return this.players[type.ordinal()];
|
||||
+ }
|
||||
+
|
||||
+ public void addPlayer(final ServerPlayer player, final NearbyMapType type) {
|
||||
+ ++this.updateCount;
|
||||
+ final int idx = type.ordinal();
|
||||
+ final ReferenceList<ServerPlayer> list = this.players[idx];
|
||||
+ if (list == null) {
|
||||
+ ++this.nonEmptyLists;
|
||||
+ (this.players[idx] = new ReferenceList<>()).add(player);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (!list.add(player)) {
|
||||
+ throw new IllegalStateException("Already contains player " + player);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public void removePlayer(final ServerPlayer player, final NearbyMapType type) {
|
||||
+ ++this.updateCount;
|
||||
+ final int idx = type.ordinal();
|
||||
+ final ReferenceList<ServerPlayer> list = this.players[idx];
|
||||
+ if (list == null) {
|
||||
+ throw new IllegalStateException("Does not contain player " + player);
|
||||
+ }
|
||||
+
|
||||
+ if (!list.remove(player)) {
|
||||
+ throw new IllegalStateException("Does not contain player " + player);
|
||||
+ }
|
||||
+
|
||||
+ if (list.size() == 0) {
|
||||
+ this.players[idx] = null;
|
||||
+ --this.nonEmptyLists;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private final class TrackedPlayer extends SingleUserAreaMap<ServerPlayer> {
|
||||
+
|
||||
+ final NearbyMapType type;
|
||||
+
|
||||
+ public TrackedPlayer(final ServerPlayer player, final NearbyMapType type) {
|
||||
+ super(player);
|
||||
+ this.type = type;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ protected void addCallback(final ServerPlayer parameter, final int chunkX, final int chunkZ) {
|
||||
+ final long chunkKey = CoordinateUtils.getChunkKey(chunkX, chunkZ);
|
||||
+
|
||||
+ NearbyPlayers.this.byChunk.computeIfAbsent(chunkKey, (final long keyInMap) -> {
|
||||
+ return new TrackedChunk();
|
||||
+ }).addPlayer(parameter, this.type);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ protected void removeCallback(final ServerPlayer parameter, final int chunkX, final int chunkZ) {
|
||||
+ final long chunkKey = CoordinateUtils.getChunkKey(chunkX, chunkZ);
|
||||
+
|
||||
+ final TrackedChunk chunk = NearbyPlayers.this.byChunk.get(chunkKey);
|
||||
+ if (chunk == null) {
|
||||
+ throw new IllegalStateException("Chunk should exist at " + new ChunkPos(chunkKey));
|
||||
+ }
|
||||
+
|
||||
+ chunk.removePlayer(parameter, this.type);
|
||||
+
|
||||
+ if (chunk.isEmpty()) {
|
||||
+ NearbyPlayers.this.byChunk.remove(chunkKey);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/util/player/SingleUserAreaMap.java b/src/main/java/io/papermc/paper/util/player/SingleUserAreaMap.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..d603887f4d0464f4463172fd79bcd5298d54983e
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/util/player/SingleUserAreaMap.java
|
||||
@@ -0,0 +1,232 @@
|
||||
+package io.papermc.paper.util.player;
|
||||
+
|
||||
+import io.papermc.paper.util.IntegerUtil;
|
||||
+
|
||||
+public abstract class SingleUserAreaMap<T> {
|
||||
+
|
||||
+ private static final int NOT_SET = Integer.MIN_VALUE;
|
||||
+
|
||||
+ private final T parameter;
|
||||
+ private int lastChunkX = NOT_SET;
|
||||
+ private int lastChunkZ = NOT_SET;
|
||||
+ private int distance = NOT_SET;
|
||||
+
|
||||
+ public SingleUserAreaMap(final T parameter) {
|
||||
+ this.parameter = parameter;
|
||||
+ }
|
||||
+
|
||||
+ /* math sign function except 0 returns 1 */
|
||||
+ protected static int sign(int val) {
|
||||
+ return 1 | (val >> (Integer.SIZE - 1));
|
||||
+ }
|
||||
+
|
||||
+ protected abstract void addCallback(final T parameter, final int chunkX, final int chunkZ);
|
||||
+
|
||||
+ protected abstract void removeCallback(final T parameter, final int chunkX, final int chunkZ);
|
||||
+
|
||||
+ private void addToNew(final T parameter, final int chunkX, final int chunkZ, final int distance) {
|
||||
+ final int maxX = chunkX + distance;
|
||||
+ final int maxZ = chunkZ + distance;
|
||||
+
|
||||
+ for (int cx = chunkX - distance; cx <= maxX; ++cx) {
|
||||
+ for (int cz = chunkZ - distance; cz <= maxZ; ++cz) {
|
||||
+ this.addCallback(parameter, cx, cz);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private void removeFromOld(final T parameter, final int chunkX, final int chunkZ, final int distance) {
|
||||
+ final int maxX = chunkX + distance;
|
||||
+ final int maxZ = chunkZ + distance;
|
||||
+
|
||||
+ for (int cx = chunkX - distance; cx <= maxX; ++cx) {
|
||||
+ for (int cz = chunkZ - distance; cz <= maxZ; ++cz) {
|
||||
+ this.removeCallback(parameter, cx, cz);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public final boolean add(final int chunkX, final int chunkZ, final int distance) {
|
||||
+ if (distance < 0) {
|
||||
+ throw new IllegalArgumentException(Integer.toString(distance));
|
||||
+ }
|
||||
+ if (this.lastChunkX != NOT_SET) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ this.lastChunkX = chunkX;
|
||||
+ this.lastChunkZ = chunkZ;
|
||||
+ this.distance = distance;
|
||||
+
|
||||
+ this.addToNew(this.parameter, chunkX, chunkZ, distance);
|
||||
+
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ public final boolean update(final int toX, final int toZ, final int newViewDistance) {
|
||||
+ if (newViewDistance < 0) {
|
||||
+ throw new IllegalArgumentException(Integer.toString(newViewDistance));
|
||||
+ }
|
||||
+ final int fromX = this.lastChunkX;
|
||||
+ final int fromZ = this.lastChunkZ;
|
||||
+ final int oldViewDistance = this.distance;
|
||||
+ if (fromX == NOT_SET) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ this.lastChunkX = toX;
|
||||
+ this.lastChunkZ = toZ;
|
||||
+ this.distance = newViewDistance;
|
||||
+
|
||||
+ final T parameter = this.parameter;
|
||||
+
|
||||
+
|
||||
+ final int dx = toX - fromX;
|
||||
+ final int dz = toZ - fromZ;
|
||||
+
|
||||
+ final int totalX = IntegerUtil.branchlessAbs(fromX - toX);
|
||||
+ final int totalZ = IntegerUtil.branchlessAbs(fromZ - toZ);
|
||||
+
|
||||
+ if (Math.max(totalX, totalZ) > (2 * Math.max(newViewDistance, oldViewDistance))) {
|
||||
+ // teleported?
|
||||
+ this.removeFromOld(parameter, fromX, fromZ, oldViewDistance);
|
||||
+ this.addToNew(parameter, toX, toZ, newViewDistance);
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ if (oldViewDistance != newViewDistance) {
|
||||
+ // remove loop
|
||||
+
|
||||
+ final int oldMinX = fromX - oldViewDistance;
|
||||
+ final int oldMinZ = fromZ - oldViewDistance;
|
||||
+ final int oldMaxX = fromX + oldViewDistance;
|
||||
+ final int oldMaxZ = fromZ + oldViewDistance;
|
||||
+ for (int currX = oldMinX; currX <= oldMaxX; ++currX) {
|
||||
+ for (int currZ = oldMinZ; currZ <= oldMaxZ; ++currZ) {
|
||||
+
|
||||
+ // only remove if we're outside the new view distance...
|
||||
+ if (Math.max(IntegerUtil.branchlessAbs(currX - toX), IntegerUtil.branchlessAbs(currZ - toZ)) > newViewDistance) {
|
||||
+ this.removeCallback(parameter, currX, currZ);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // add loop
|
||||
+
|
||||
+ final int newMinX = toX - newViewDistance;
|
||||
+ final int newMinZ = toZ - newViewDistance;
|
||||
+ final int newMaxX = toX + newViewDistance;
|
||||
+ final int newMaxZ = toZ + newViewDistance;
|
||||
+ for (int currX = newMinX; currX <= newMaxX; ++currX) {
|
||||
+ for (int currZ = newMinZ; currZ <= newMaxZ; ++currZ) {
|
||||
+
|
||||
+ // only add if we're outside the old view distance...
|
||||
+ if (Math.max(IntegerUtil.branchlessAbs(currX - fromX), IntegerUtil.branchlessAbs(currZ - fromZ)) > oldViewDistance) {
|
||||
+ this.addCallback(parameter, currX, currZ);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ // x axis is width
|
||||
+ // z axis is height
|
||||
+ // right refers to the x axis of where we moved
|
||||
+ // top refers to the z axis of where we moved
|
||||
+
|
||||
+ // same view distance
|
||||
+
|
||||
+ // used for relative positioning
|
||||
+ final int up = sign(dz); // 1 if dz >= 0, -1 otherwise
|
||||
+ final int right = sign(dx); // 1 if dx >= 0, -1 otherwise
|
||||
+
|
||||
+ // The area excluded by overlapping the two view distance squares creates four rectangles:
|
||||
+ // Two on the left, and two on the right. The ones on the left we consider the "removed" section
|
||||
+ // and on the right the "added" section.
|
||||
+ // https://i.imgur.com/MrnOBgI.png is a reference image. Note that the outside border is not actually
|
||||
+ // exclusive to the regions they surround.
|
||||
+
|
||||
+ // 4 points of the rectangle
|
||||
+ int maxX; // exclusive
|
||||
+ int minX; // inclusive
|
||||
+ int maxZ; // exclusive
|
||||
+ int minZ; // inclusive
|
||||
+
|
||||
+ if (dx != 0) {
|
||||
+ // handle right addition
|
||||
+
|
||||
+ maxX = toX + (oldViewDistance * right) + right; // exclusive
|
||||
+ minX = fromX + (oldViewDistance * right) + right; // inclusive
|
||||
+ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive
|
||||
+ minZ = toZ - (oldViewDistance * up); // inclusive
|
||||
+
|
||||
+ for (int currX = minX; currX != maxX; currX += right) {
|
||||
+ for (int currZ = minZ; currZ != maxZ; currZ += up) {
|
||||
+ this.addCallback(parameter, currX, currZ);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (dz != 0) {
|
||||
+ // handle up addition
|
||||
+
|
||||
+ maxX = toX + (oldViewDistance * right) + right; // exclusive
|
||||
+ minX = toX - (oldViewDistance * right); // inclusive
|
||||
+ maxZ = toZ + (oldViewDistance * up) + up; // exclusive
|
||||
+ minZ = fromZ + (oldViewDistance * up) + up; // inclusive
|
||||
+
|
||||
+ for (int currX = minX; currX != maxX; currX += right) {
|
||||
+ for (int currZ = minZ; currZ != maxZ; currZ += up) {
|
||||
+ this.addCallback(parameter, currX, currZ);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (dx != 0) {
|
||||
+ // handle left removal
|
||||
+
|
||||
+ maxX = toX - (oldViewDistance * right); // exclusive
|
||||
+ minX = fromX - (oldViewDistance * right); // inclusive
|
||||
+ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive
|
||||
+ minZ = toZ - (oldViewDistance * up); // inclusive
|
||||
+
|
||||
+ for (int currX = minX; currX != maxX; currX += right) {
|
||||
+ for (int currZ = minZ; currZ != maxZ; currZ += up) {
|
||||
+ this.removeCallback(parameter, currX, currZ);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (dz != 0) {
|
||||
+ // handle down removal
|
||||
+
|
||||
+ maxX = fromX + (oldViewDistance * right) + right; // exclusive
|
||||
+ minX = fromX - (oldViewDistance * right); // inclusive
|
||||
+ maxZ = toZ - (oldViewDistance * up); // exclusive
|
||||
+ minZ = fromZ - (oldViewDistance * up); // inclusive
|
||||
+
|
||||
+ for (int currX = minX; currX != maxX; currX += right) {
|
||||
+ for (int currZ = minZ; currZ != maxZ; currZ += up) {
|
||||
+ this.removeCallback(parameter, currX, currZ);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ public final boolean remove() {
|
||||
+ final int chunkX = this.lastChunkX;
|
||||
+ final int chunkZ = this.lastChunkZ;
|
||||
+ final int distance = this.distance;
|
||||
+ if (chunkX == NOT_SET) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ this.lastChunkX = this.lastChunkZ = this.distance = NOT_SET;
|
||||
+
|
||||
+ this.removeFromOld(this.parameter, chunkX, chunkZ, distance);
|
||||
+
|
||||
+ return true;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java
|
||||
index 092bfedfb32c38550d1cab1b696feac6df09131f..9870eccc1dc5c2201f12f8e2affe647f6b0375f8 100644
|
||||
--- a/src/main/java/net/minecraft/Util.java
|
||||
@ -5580,30 +6027,29 @@ index 929d31aa624f035eb314dece08969b102f5781fc..e94f0361cbca873f05b5b768c68c0933
|
||||
+ // Paper end - MC Utils - default query payloads
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/network/protocol/login/ServerboundCustomQueryAnswerPacket.java b/src/main/java/net/minecraft/network/protocol/login/ServerboundCustomQueryAnswerPacket.java
|
||||
index 44cac39893eb968aa8ea21ee571c0dcb866ce06c..953e7573f6b2ca73a8c27c4d63edec89b173f333 100644
|
||||
index 44cac39893eb968aa8ea21ee571c0dcb866ce06c..5151d68ba6ec72a7124f298253c5f0af080b2ea6 100644
|
||||
--- a/src/main/java/net/minecraft/network/protocol/login/ServerboundCustomQueryAnswerPacket.java
|
||||
+++ b/src/main/java/net/minecraft/network/protocol/login/ServerboundCustomQueryAnswerPacket.java
|
||||
@@ -15,7 +15,18 @@ public record ServerboundCustomQueryAnswerPacket(int transactionId, @Nullable Cu
|
||||
@@ -15,7 +15,17 @@ public record ServerboundCustomQueryAnswerPacket(int transactionId, @Nullable Cu
|
||||
}
|
||||
|
||||
private static CustomQueryAnswerPayload readPayload(int queryId, FriendlyByteBuf buf) {
|
||||
- return readUnknownPayload(buf);
|
||||
+ // Paper start - MC Utils - default query payloads
|
||||
+ return new net.minecraft.network.protocol.login.ServerboundCustomQueryAnswerPacket.QueryAnswerPayload(
|
||||
+ buf.readNullable((buf2) -> {
|
||||
+ int i = buf2.readableBytes();
|
||||
+ if (i >= 0 && i <= MAX_PAYLOAD_SIZE) {
|
||||
+ return new FriendlyByteBuf(buf2.readBytes(i));
|
||||
+ } else {
|
||||
+ throw new IllegalArgumentException("Payload may not be larger than " + MAX_PAYLOAD_SIZE + " bytes");
|
||||
+ }
|
||||
+ })
|
||||
+ );
|
||||
+ FriendlyByteBuf buffer = buf.readNullable((buf2) -> {
|
||||
+ int i = buf2.readableBytes();
|
||||
+ if (i >= 0 && i <= MAX_PAYLOAD_SIZE) {
|
||||
+ return new FriendlyByteBuf(buf2.readBytes(i));
|
||||
+ } else {
|
||||
+ throw new IllegalArgumentException("Payload may not be larger than " + MAX_PAYLOAD_SIZE + " bytes");
|
||||
+ }
|
||||
+ });
|
||||
+ return buffer == null ? null : new net.minecraft.network.protocol.login.ServerboundCustomQueryAnswerPacket.QueryAnswerPayload(buffer);
|
||||
+ // Paper end - MC Utils - default query payloads
|
||||
}
|
||||
|
||||
private static CustomQueryAnswerPayload readUnknownPayload(FriendlyByteBuf buf) {
|
||||
@@ -40,4 +51,21 @@ public record ServerboundCustomQueryAnswerPacket(int transactionId, @Nullable Cu
|
||||
@@ -40,4 +50,21 @@ public record ServerboundCustomQueryAnswerPacket(int transactionId, @Nullable Cu
|
||||
public void handle(ServerLoginPacketListener listener) {
|
||||
listener.handleCustomQueryPacket(this);
|
||||
}
|
||||
@ -5920,10 +6366,10 @@ index 1641bdf8725df778ba91bf5cd22c1ebbb3745058..facfdbb87e89f4db33ce13233c2ba436
|
||||
+ // Paper end
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index e9cf8686b59c232816b2fde92fc6616f77979a64..90dce7ed0d3d3dee3bae6657ac3cbeb54dd199ce 100644
|
||||
index e9cf8686b59c232816b2fde92fc6616f77979a64..10132390dd356461f696971b34df3eeed05c572e 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -167,6 +167,56 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -167,6 +167,62 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
};
|
||||
// CraftBukkit end
|
||||
|
||||
@ -5934,16 +6380,21 @@ index e9cf8686b59c232816b2fde92fc6616f77979a64..90dce7ed0d3d3dee3bae6657ac3cbeb5
|
||||
+ int chunkX = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getX());
|
||||
+ int chunkZ = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getZ());
|
||||
+ // Note: players need to be explicitly added to distance maps before they can be updated
|
||||
+ this.nearbyPlayers.addPlayer(player);
|
||||
+ }
|
||||
+
|
||||
+ void removePlayerFromDistanceMaps(ServerPlayer player) {
|
||||
+
|
||||
+ int chunkX = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getX());
|
||||
+ int chunkZ = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getZ());
|
||||
+ // Note: players need to be explicitly added to distance maps before they can be updated
|
||||
+ this.nearbyPlayers.removePlayer(player);
|
||||
+ }
|
||||
+
|
||||
+ void updateMaps(ServerPlayer player) {
|
||||
+ int chunkX = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getX());
|
||||
+ int chunkZ = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getZ());
|
||||
+ // Note: players need to be explicitly added to distance maps before they can be updated
|
||||
+ this.nearbyPlayers.tickPlayer(player);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+ // Paper start
|
||||
@ -5975,23 +6426,33 @@ index e9cf8686b59c232816b2fde92fc6616f77979a64..90dce7ed0d3d3dee3bae6657ac3cbeb5
|
||||
+ public final ChunkHolder getUnloadingChunkHolder(int chunkX, int chunkZ) {
|
||||
+ return this.pendingUnloads.get(io.papermc.paper.util.CoordinateUtils.getChunkKey(chunkX, chunkZ));
|
||||
+ }
|
||||
+ public final io.papermc.paper.util.player.NearbyPlayers nearbyPlayers;
|
||||
+ // Paper end
|
||||
+
|
||||
public ChunkMap(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureTemplateManager structureTemplateManager, Executor executor, BlockableEventLoop<Runnable> mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier<DimensionDataStorage> persistentStateManagerFactory, int viewDistance, boolean dsync) {
|
||||
super(session.getDimensionPath(world.dimension()).resolve("region"), dataFixer, dsync);
|
||||
this.visibleChunkMap = this.updatingChunkMap.clone();
|
||||
@@ -220,6 +270,10 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -220,7 +276,19 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
this.overworldDataStorage = persistentStateManagerFactory;
|
||||
this.poiManager = new PoiManager(path.resolve("poi"), dataFixer, dsync, iregistrycustom, world);
|
||||
this.setServerViewDistance(viewDistance);
|
||||
+ // Paper start
|
||||
+ this.dataRegionManager = new io.papermc.paper.chunk.SingleThreadChunkRegionManager(this.level, 2, (1.0 / 3.0), 1, 6, "Data", DataRegionData::new, DataRegionSectionData::new);
|
||||
+ this.regionManagers.add(this.dataRegionManager);
|
||||
+ this.nearbyPlayers = new io.papermc.paper.util.player.NearbyPlayers(this.level);
|
||||
+ // Paper end
|
||||
+ }
|
||||
+
|
||||
+ // Paper start
|
||||
+ // always use accessor, so folia can override
|
||||
+ public final io.papermc.paper.util.player.NearbyPlayers getNearbyPlayers() {
|
||||
+ return this.nearbyPlayers;
|
||||
}
|
||||
+ // Paper end
|
||||
|
||||
protected ChunkGenerator generator() {
|
||||
@@ -321,6 +375,15 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
return this.generator;
|
||||
@@ -321,6 +389,15 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
}
|
||||
|
||||
@ -6007,7 +6468,7 @@ index e9cf8686b59c232816b2fde92fc6616f77979a64..90dce7ed0d3d3dee3bae6657ac3cbeb5
|
||||
private CompletableFuture<Either<List<ChunkAccess>, ChunkHolder.ChunkLoadingFailure>> getChunkRangeFuture(ChunkHolder centerChunk, int margin, IntFunction<ChunkStatus> distanceToStatus) {
|
||||
if (margin == 0) {
|
||||
ChunkStatus chunkstatus = (ChunkStatus) distanceToStatus.apply(0);
|
||||
@@ -417,9 +480,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -417,9 +494,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
};
|
||||
|
||||
stringbuilder.append("Updating:").append(System.lineSeparator());
|
||||
@ -6019,7 +6480,7 @@ index e9cf8686b59c232816b2fde92fc6616f77979a64..90dce7ed0d3d3dee3bae6657ac3cbeb5
|
||||
CrashReport crashreport = CrashReport.forThrowable(exception, "Chunk loading");
|
||||
CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Chunk loading");
|
||||
|
||||
@@ -461,8 +524,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -461,8 +538,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
holder.setTicketLevel(level);
|
||||
} else {
|
||||
holder = new ChunkHolder(new ChunkPos(pos), level, this.level, this.lightEngine, this.queueSorter, this);
|
||||
@ -6034,7 +6495,7 @@ index e9cf8686b59c232816b2fde92fc6616f77979a64..90dce7ed0d3d3dee3bae6657ac3cbeb5
|
||||
this.updatingChunkMap.put(pos, holder);
|
||||
this.modified = true;
|
||||
}
|
||||
@@ -484,7 +553,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -484,7 +567,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
|
||||
protected void saveAllChunks(boolean flush) {
|
||||
if (flush) {
|
||||
@ -6043,7 +6504,7 @@ index e9cf8686b59c232816b2fde92fc6616f77979a64..90dce7ed0d3d3dee3bae6657ac3cbeb5
|
||||
MutableBoolean mutableboolean = new MutableBoolean();
|
||||
|
||||
do {
|
||||
@@ -513,7 +582,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -513,7 +596,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
});
|
||||
this.flushWorker();
|
||||
} else {
|
||||
@ -6052,7 +6513,7 @@ index e9cf8686b59c232816b2fde92fc6616f77979a64..90dce7ed0d3d3dee3bae6657ac3cbeb5
|
||||
}
|
||||
|
||||
}
|
||||
@@ -532,7 +601,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -532,7 +615,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
|
||||
public boolean hasWork() {
|
||||
@ -6061,7 +6522,7 @@ index e9cf8686b59c232816b2fde92fc6616f77979a64..90dce7ed0d3d3dee3bae6657ac3cbeb5
|
||||
}
|
||||
|
||||
private void processUnloads(BooleanSupplier shouldKeepTicking) {
|
||||
@@ -543,6 +612,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -543,6 +626,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
ChunkHolder playerchunk = (ChunkHolder) this.updatingChunkMap.remove(j);
|
||||
|
||||
if (playerchunk != null) {
|
||||
@ -6069,7 +6530,7 @@ index e9cf8686b59c232816b2fde92fc6616f77979a64..90dce7ed0d3d3dee3bae6657ac3cbeb5
|
||||
this.pendingUnloads.put(j, playerchunk);
|
||||
this.modified = true;
|
||||
++i;
|
||||
@@ -560,7 +630,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -560,7 +644,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
|
||||
int l = 0;
|
||||
@ -6078,7 +6539,7 @@ index e9cf8686b59c232816b2fde92fc6616f77979a64..90dce7ed0d3d3dee3bae6657ac3cbeb5
|
||||
|
||||
while (l < 20 && shouldKeepTicking.getAsBoolean() && objectiterator.hasNext()) {
|
||||
if (this.saveChunkIfNeeded((ChunkHolder) objectiterator.next())) {
|
||||
@@ -578,7 +648,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -578,7 +662,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
if (completablefuture1 != completablefuture) {
|
||||
this.scheduleUnload(pos, holder);
|
||||
} else {
|
||||
@ -6091,7 +6552,7 @@ index e9cf8686b59c232816b2fde92fc6616f77979a64..90dce7ed0d3d3dee3bae6657ac3cbeb5
|
||||
if (ichunkaccess instanceof LevelChunk) {
|
||||
((LevelChunk) ichunkaccess).setLoaded(false);
|
||||
}
|
||||
@@ -594,7 +668,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -594,7 +682,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
this.lightEngine.tryScheduleUpdate();
|
||||
this.progressListener.onStatusChange(ichunkaccess.getPos(), (ChunkStatus) null);
|
||||
this.chunkSaveCooldowns.remove(ichunkaccess.getPos().toLong());
|
||||
@ -6102,7 +6563,7 @@ index e9cf8686b59c232816b2fde92fc6616f77979a64..90dce7ed0d3d3dee3bae6657ac3cbeb5
|
||||
|
||||
}
|
||||
};
|
||||
@@ -1037,7 +1113,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1037,7 +1127,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
|
||||
public int size() {
|
||||
@ -6111,7 +6572,7 @@ index e9cf8686b59c232816b2fde92fc6616f77979a64..90dce7ed0d3d3dee3bae6657ac3cbeb5
|
||||
}
|
||||
|
||||
public DistanceManager getDistanceManager() {
|
||||
@@ -1045,19 +1121,19 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1045,19 +1135,19 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
|
||||
protected Iterable<ChunkHolder> getChunks() {
|
||||
@ -6136,7 +6597,7 @@ index e9cf8686b59c232816b2fde92fc6616f77979a64..90dce7ed0d3d3dee3bae6657ac3cbeb5
|
||||
Optional<ChunkAccess> optional = Optional.ofNullable(playerchunk.getLastAvailable());
|
||||
Optional<LevelChunk> optional1 = optional.flatMap((ichunkaccess) -> {
|
||||
return ichunkaccess instanceof LevelChunk ? Optional.of((LevelChunk) ichunkaccess) : Optional.empty();
|
||||
@@ -1182,6 +1258,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1182,6 +1272,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
|
||||
player.setChunkTrackingView(ChunkTrackingView.EMPTY);
|
||||
this.updateChunkTracking(player);
|
||||
@ -6144,7 +6605,7 @@ index e9cf8686b59c232816b2fde92fc6616f77979a64..90dce7ed0d3d3dee3bae6657ac3cbeb5
|
||||
} else {
|
||||
SectionPos sectionposition = player.getLastSectionPos();
|
||||
|
||||
@@ -1190,6 +1267,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1190,6 +1281,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
this.distanceManager.removePlayer(sectionposition, player);
|
||||
}
|
||||
|
||||
@ -6152,7 +6613,7 @@ index e9cf8686b59c232816b2fde92fc6616f77979a64..90dce7ed0d3d3dee3bae6657ac3cbeb5
|
||||
this.applyChunkTrackingView(player, ChunkTrackingView.EMPTY);
|
||||
}
|
||||
|
||||
@@ -1241,6 +1319,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1241,6 +1333,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
this.updateChunkTracking(player);
|
||||
}
|
||||
|
||||
@ -6160,7 +6621,7 @@ index e9cf8686b59c232816b2fde92fc6616f77979a64..90dce7ed0d3d3dee3bae6657ac3cbeb5
|
||||
}
|
||||
|
||||
private void updateChunkTracking(ServerPlayer player) {
|
||||
@@ -1493,7 +1572,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1493,7 +1586,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
private class ChunkDistanceManager extends DistanceManager {
|
||||
|
||||
protected ChunkDistanceManager(Executor workerExecutor, Executor mainThreadExecutor) {
|
||||
|
@ -1010,7 +1010,7 @@ index ff3f00cf1d5180f83b16acac5676aa22cd967c8a..5aa21689e308842fe5b64689265ba45a
|
||||
// CraftBukkit end
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 90dce7ed0d3d3dee3bae6657ac3cbeb54dd199ce..449bd9f505fdfb9eab46ff9309d7665bced1e5f8 100644
|
||||
index 10132390dd356461f696971b34df3eeed05c572e..4dc04c16453174dde2c6bfad711ec9dec01c8f30 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -1,8 +1,10 @@
|
||||
@ -1024,7 +1024,7 @@ index 90dce7ed0d3d3dee3bae6657ac3cbeb54dd199ce..449bd9f505fdfb9eab46ff9309d7665b
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Queues;
|
||||
import com.google.common.collect.Sets;
|
||||
@@ -882,6 +884,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -896,6 +898,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
ChunkStatus chunkstatus = ChunkLevel.generationStatus(chunkHolder.getTicketLevel());
|
||||
|
||||
return !chunkstatus.isOrAfter(ChunkStatus.FULL) ? ChunkHolder.UNLOADED_CHUNK : either.mapLeft((ichunkaccess) -> {
|
||||
@ -1032,7 +1032,7 @@ index 90dce7ed0d3d3dee3bae6657ac3cbeb54dd199ce..449bd9f505fdfb9eab46ff9309d7665b
|
||||
ChunkPos chunkcoordintpair = chunkHolder.getPos();
|
||||
ProtoChunk protochunk = (ProtoChunk) ichunkaccess;
|
||||
LevelChunk chunk;
|
||||
@@ -906,6 +909,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -920,6 +923,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
|
||||
return chunk;
|
||||
@ -1040,7 +1040,7 @@ index 90dce7ed0d3d3dee3bae6657ac3cbeb54dd199ce..449bd9f505fdfb9eab46ff9309d7665b
|
||||
});
|
||||
}, (runnable) -> {
|
||||
ProcessorHandle mailbox = this.mainThreadMailbox;
|
||||
@@ -1457,6 +1461,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1471,6 +1475,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
List<ServerPlayer> list = Lists.newArrayList();
|
||||
List<ServerPlayer> list1 = this.level.players();
|
||||
ObjectIterator objectiterator = this.entityMap.values().iterator();
|
||||
@ -1048,7 +1048,7 @@ index 90dce7ed0d3d3dee3bae6657ac3cbeb54dd199ce..449bd9f505fdfb9eab46ff9309d7665b
|
||||
|
||||
ChunkMap.TrackedEntity playerchunkmap_entitytracker;
|
||||
|
||||
@@ -1481,14 +1486,17 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1495,14 +1500,17 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
playerchunkmap_entitytracker.serverEntity.sendChanges();
|
||||
}
|
||||
}
|
||||
|
@ -4493,7 +4493,7 @@ index facfdbb87e89f4db33ce13233c2ba4366d35c15b..807a6bb1026dac2c4cd0a50afe06fd62
|
||||
private final DebugBuffer<ChunkHolder.ChunkSaveDebug> chunkToSaveHistory;
|
||||
public int oldTicketLevel;
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 449bd9f505fdfb9eab46ff9309d7665bced1e5f8..8c84461a5711cb408b0ead397417c31cb2f4d336 100644
|
||||
index 4dc04c16453174dde2c6bfad711ec9dec01c8f30..b47e30e9ebe0d6a930e01aaf67c138fc345fb11e 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -124,7 +124,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
|
@ -2095,7 +2095,7 @@ index 0000000000000000000000000000000000000000..99f49b5625cf51d6c97640553cf5c420
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/chunk/system/ChunkSystem.java b/src/main/java/io/papermc/paper/chunk/system/ChunkSystem.java
|
||||
index 87ae7d64e67ebae5ab53cc239cdf6580dca31652..56c35149fd142af6ffe31434fec0064cf6ea3be5 100644
|
||||
index 87ae7d64e67ebae5ab53cc239cdf6580dca31652..cbeaadaecf816070b3a37938c8e683180939afc4 100644
|
||||
--- a/src/main/java/io/papermc/paper/chunk/system/ChunkSystem.java
|
||||
+++ b/src/main/java/io/papermc/paper/chunk/system/ChunkSystem.java
|
||||
@@ -32,191 +32,41 @@ public final class ChunkSystem {
|
||||
@ -2299,7 +2299,40 @@ index 87ae7d64e67ebae5ab53cc239cdf6580dca31652..56c35149fd142af6ffe31434fec0064c
|
||||
}
|
||||
|
||||
public static boolean hasAnyChunkHolders(final ServerLevel level) {
|
||||
@@ -270,23 +120,15 @@ public final class ChunkSystem {
|
||||
@@ -243,26 +93,31 @@ public final class ChunkSystem {
|
||||
|
||||
public static void onChunkBorder(final LevelChunk chunk, final ChunkHolder holder) {
|
||||
chunk.playerChunk = holder;
|
||||
+ chunk.chunkStatus = net.minecraft.server.level.FullChunkStatus.FULL;
|
||||
}
|
||||
|
||||
public static void onChunkNotBorder(final LevelChunk chunk, final ChunkHolder holder) {
|
||||
-
|
||||
+ chunk.chunkStatus = net.minecraft.server.level.FullChunkStatus.INACCESSIBLE;
|
||||
}
|
||||
|
||||
public static void onChunkTicking(final LevelChunk chunk, final ChunkHolder holder) {
|
||||
chunk.level.getChunkSource().tickingChunks.add(chunk);
|
||||
+ chunk.chunkStatus = net.minecraft.server.level.FullChunkStatus.BLOCK_TICKING;
|
||||
}
|
||||
|
||||
public static void onChunkNotTicking(final LevelChunk chunk, final ChunkHolder holder) {
|
||||
chunk.level.getChunkSource().tickingChunks.remove(chunk);
|
||||
+ chunk.chunkStatus = net.minecraft.server.level.FullChunkStatus.FULL;
|
||||
}
|
||||
|
||||
public static void onChunkEntityTicking(final LevelChunk chunk, final ChunkHolder holder) {
|
||||
chunk.level.getChunkSource().entityTickingChunks.add(chunk);
|
||||
+ chunk.chunkStatus = net.minecraft.server.level.FullChunkStatus.ENTITY_TICKING;
|
||||
}
|
||||
|
||||
public static void onChunkNotEntityTicking(final LevelChunk chunk, final ChunkHolder holder) {
|
||||
chunk.level.getChunkSource().entityTickingChunks.remove(chunk);
|
||||
+ chunk.chunkStatus = net.minecraft.server.level.FullChunkStatus.BLOCK_TICKING;
|
||||
}
|
||||
|
||||
public static ChunkHolder getUnloadingChunkHolder(final ServerLevel level, final int chunkX, final int chunkZ) {
|
||||
@@ -270,23 +125,15 @@ public final class ChunkSystem {
|
||||
}
|
||||
|
||||
public static int getSendViewDistance(final ServerPlayer player) {
|
||||
@ -2328,21 +2361,20 @@ index 87ae7d64e67ebae5ab53cc239cdf6580dca31652..56c35149fd142af6ffe31434fec0064c
|
||||
private ChunkSystem() {
|
||||
diff --git a/src/main/java/io/papermc/paper/chunk/system/RegionizedPlayerChunkLoader.java b/src/main/java/io/papermc/paper/chunk/system/RegionizedPlayerChunkLoader.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..842848872b86e5335863d309af956fee74110d52
|
||||
index 0000000000000000000000000000000000000000..1b090f1e79b996e52097afc49c1cec85936653e6
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/chunk/system/RegionizedPlayerChunkLoader.java
|
||||
@@ -0,0 +1,1440 @@
|
||||
@@ -0,0 +1,1208 @@
|
||||
+package io.papermc.paper.chunk.system;
|
||||
+
|
||||
+import ca.spottedleaf.concurrentutil.collection.SRSWLinkedQueue;
|
||||
+import ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor;
|
||||
+import ca.spottedleaf.concurrentutil.util.ConcurrentUtil;
|
||||
+import io.papermc.paper.chunk.system.io.RegionFileIOThread;
|
||||
+import io.papermc.paper.chunk.system.scheduling.ChunkHolderManager;
|
||||
+import io.papermc.paper.configuration.GlobalConfiguration;
|
||||
+import io.papermc.paper.util.CoordinateUtils;
|
||||
+import io.papermc.paper.util.IntegerUtil;
|
||||
+import io.papermc.paper.util.TickThread;
|
||||
+import io.papermc.paper.util.player.SingleUserAreaMap;
|
||||
+import it.unimi.dsi.fastutil.longs.Long2ByteOpenHashMap;
|
||||
+import it.unimi.dsi.fastutil.longs.LongArrayFIFOQueue;
|
||||
+import it.unimi.dsi.fastutil.longs.LongArrayList;
|
||||
@ -2353,7 +2385,6 @@ index 0000000000000000000000000000000000000000..842848872b86e5335863d309af956fee
|
||||
+import net.minecraft.network.protocol.game.ClientboundSetChunkCacheCenterPacket;
|
||||
+import net.minecraft.network.protocol.game.ClientboundSetChunkCacheRadiusPacket;
|
||||
+import net.minecraft.network.protocol.game.ClientboundSetSimulationDistancePacket;
|
||||
+import net.minecraft.server.level.ChunkMap;
|
||||
+import net.minecraft.server.level.ChunkTrackingView;
|
||||
+import net.minecraft.server.level.ServerLevel;
|
||||
+import net.minecraft.server.level.ServerPlayer;
|
||||
@ -2365,7 +2396,6 @@ index 0000000000000000000000000000000000000000..842848872b86e5335863d309af956fee
|
||||
+import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
+import net.minecraft.world.level.chunk.LevelChunk;
|
||||
+import net.minecraft.world.level.levelgen.BelowZeroRetrogen;
|
||||
+import org.apache.commons.lang3.mutable.MutableObject;
|
||||
+import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import java.lang.invoke.VarHandle;
|
||||
@ -2845,7 +2875,7 @@ index 0000000000000000000000000000000000000000..842848872b86e5335863d309af956fee
|
||||
+ parameter.sendUnloadChunk(chunkX, chunkZ);
|
||||
+ }
|
||||
+ };
|
||||
+ private final SingleUserAreaMap<PlayerChunkLoaderData> loadTicketCleanup = new SingleUserAreaMap<>(this) {
|
||||
+ private final SingleUserAreaMap<io.papermc.paper.chunk.system.RegionizedPlayerChunkLoader.PlayerChunkLoaderData> loadTicketCleanup = new SingleUserAreaMap<>(this) {
|
||||
+ @Override
|
||||
+ protected void addCallback(final PlayerChunkLoaderData parameter, final int chunkX, final int chunkZ) {
|
||||
+ // do nothing, we only care about remove
|
||||
@ -3488,235 +3518,6 @@ index 0000000000000000000000000000000000000000..842848872b86e5335863d309af956fee
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public static abstract class SingleUserAreaMap<T> {
|
||||
+
|
||||
+ private static final int NOT_SET = Integer.MIN_VALUE;
|
||||
+
|
||||
+ private final T parameter;
|
||||
+ private int lastChunkX = NOT_SET;
|
||||
+ private int lastChunkZ = NOT_SET;
|
||||
+ private int distance = NOT_SET;
|
||||
+
|
||||
+ public SingleUserAreaMap(final T parameter) {
|
||||
+ this.parameter = parameter;
|
||||
+ }
|
||||
+
|
||||
+ /* math sign function except 0 returns 1 */
|
||||
+ protected static int sign(int val) {
|
||||
+ return 1 | (val >> (Integer.SIZE - 1));
|
||||
+ }
|
||||
+
|
||||
+ protected abstract void addCallback(final T parameter, final int chunkX, final int chunkZ);
|
||||
+
|
||||
+ protected abstract void removeCallback(final T parameter, final int chunkX, final int chunkZ);
|
||||
+
|
||||
+ private void addToNew(final T parameter, final int chunkX, final int chunkZ, final int distance) {
|
||||
+ final int maxX = chunkX + distance;
|
||||
+ final int maxZ = chunkZ + distance;
|
||||
+
|
||||
+ for (int cx = chunkX - distance; cx <= maxX; ++cx) {
|
||||
+ for (int cz = chunkZ - distance; cz <= maxZ; ++cz) {
|
||||
+ this.addCallback(parameter, cx, cz);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private void removeFromOld(final T parameter, final int chunkX, final int chunkZ, final int distance) {
|
||||
+ final int maxX = chunkX + distance;
|
||||
+ final int maxZ = chunkZ + distance;
|
||||
+
|
||||
+ for (int cx = chunkX - distance; cx <= maxX; ++cx) {
|
||||
+ for (int cz = chunkZ - distance; cz <= maxZ; ++cz) {
|
||||
+ this.removeCallback(parameter, cx, cz);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public final boolean add(final int chunkX, final int chunkZ, final int distance) {
|
||||
+ if (distance < 0) {
|
||||
+ throw new IllegalArgumentException(Integer.toString(distance));
|
||||
+ }
|
||||
+ if (this.lastChunkX != NOT_SET) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ this.lastChunkX = chunkX;
|
||||
+ this.lastChunkZ = chunkZ;
|
||||
+ this.distance = distance;
|
||||
+
|
||||
+ this.addToNew(this.parameter, chunkX, chunkZ, distance);
|
||||
+
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ public final boolean update(final int toX, final int toZ, final int newViewDistance) {
|
||||
+ if (newViewDistance < 0) {
|
||||
+ throw new IllegalArgumentException(Integer.toString(newViewDistance));
|
||||
+ }
|
||||
+ final int fromX = this.lastChunkX;
|
||||
+ final int fromZ = this.lastChunkZ;
|
||||
+ final int oldViewDistance = this.distance;
|
||||
+ if (fromX == NOT_SET) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ this.lastChunkX = toX;
|
||||
+ this.lastChunkZ = toZ;
|
||||
+ this.distance = newViewDistance;
|
||||
+
|
||||
+ final T parameter = this.parameter;
|
||||
+
|
||||
+
|
||||
+ final int dx = toX - fromX;
|
||||
+ final int dz = toZ - fromZ;
|
||||
+
|
||||
+ final int totalX = IntegerUtil.branchlessAbs(fromX - toX);
|
||||
+ final int totalZ = IntegerUtil.branchlessAbs(fromZ - toZ);
|
||||
+
|
||||
+ if (Math.max(totalX, totalZ) > (2 * Math.max(newViewDistance, oldViewDistance))) {
|
||||
+ // teleported?
|
||||
+ this.removeFromOld(parameter, fromX, fromZ, oldViewDistance);
|
||||
+ this.addToNew(parameter, toX, toZ, newViewDistance);
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ if (oldViewDistance != newViewDistance) {
|
||||
+ // remove loop
|
||||
+
|
||||
+ final int oldMinX = fromX - oldViewDistance;
|
||||
+ final int oldMinZ = fromZ - oldViewDistance;
|
||||
+ final int oldMaxX = fromX + oldViewDistance;
|
||||
+ final int oldMaxZ = fromZ + oldViewDistance;
|
||||
+ for (int currX = oldMinX; currX <= oldMaxX; ++currX) {
|
||||
+ for (int currZ = oldMinZ; currZ <= oldMaxZ; ++currZ) {
|
||||
+
|
||||
+ // only remove if we're outside the new view distance...
|
||||
+ if (Math.max(IntegerUtil.branchlessAbs(currX - toX), IntegerUtil.branchlessAbs(currZ - toZ)) > newViewDistance) {
|
||||
+ this.removeCallback(parameter, currX, currZ);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // add loop
|
||||
+
|
||||
+ final int newMinX = toX - newViewDistance;
|
||||
+ final int newMinZ = toZ - newViewDistance;
|
||||
+ final int newMaxX = toX + newViewDistance;
|
||||
+ final int newMaxZ = toZ + newViewDistance;
|
||||
+ for (int currX = newMinX; currX <= newMaxX; ++currX) {
|
||||
+ for (int currZ = newMinZ; currZ <= newMaxZ; ++currZ) {
|
||||
+
|
||||
+ // only add if we're outside the old view distance...
|
||||
+ if (Math.max(IntegerUtil.branchlessAbs(currX - fromX), IntegerUtil.branchlessAbs(currZ - fromZ)) > oldViewDistance) {
|
||||
+ this.addCallback(parameter, currX, currZ);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ // x axis is width
|
||||
+ // z axis is height
|
||||
+ // right refers to the x axis of where we moved
|
||||
+ // top refers to the z axis of where we moved
|
||||
+
|
||||
+ // same view distance
|
||||
+
|
||||
+ // used for relative positioning
|
||||
+ final int up = sign(dz); // 1 if dz >= 0, -1 otherwise
|
||||
+ final int right = sign(dx); // 1 if dx >= 0, -1 otherwise
|
||||
+
|
||||
+ // The area excluded by overlapping the two view distance squares creates four rectangles:
|
||||
+ // Two on the left, and two on the right. The ones on the left we consider the "removed" section
|
||||
+ // and on the right the "added" section.
|
||||
+ // https://i.imgur.com/MrnOBgI.png is a reference image. Note that the outside border is not actually
|
||||
+ // exclusive to the regions they surround.
|
||||
+
|
||||
+ // 4 points of the rectangle
|
||||
+ int maxX; // exclusive
|
||||
+ int minX; // inclusive
|
||||
+ int maxZ; // exclusive
|
||||
+ int minZ; // inclusive
|
||||
+
|
||||
+ if (dx != 0) {
|
||||
+ // handle right addition
|
||||
+
|
||||
+ maxX = toX + (oldViewDistance * right) + right; // exclusive
|
||||
+ minX = fromX + (oldViewDistance * right) + right; // inclusive
|
||||
+ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive
|
||||
+ minZ = toZ - (oldViewDistance * up); // inclusive
|
||||
+
|
||||
+ for (int currX = minX; currX != maxX; currX += right) {
|
||||
+ for (int currZ = minZ; currZ != maxZ; currZ += up) {
|
||||
+ this.addCallback(parameter, currX, currZ);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (dz != 0) {
|
||||
+ // handle up addition
|
||||
+
|
||||
+ maxX = toX + (oldViewDistance * right) + right; // exclusive
|
||||
+ minX = toX - (oldViewDistance * right); // inclusive
|
||||
+ maxZ = toZ + (oldViewDistance * up) + up; // exclusive
|
||||
+ minZ = fromZ + (oldViewDistance * up) + up; // inclusive
|
||||
+
|
||||
+ for (int currX = minX; currX != maxX; currX += right) {
|
||||
+ for (int currZ = minZ; currZ != maxZ; currZ += up) {
|
||||
+ this.addCallback(parameter, currX, currZ);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (dx != 0) {
|
||||
+ // handle left removal
|
||||
+
|
||||
+ maxX = toX - (oldViewDistance * right); // exclusive
|
||||
+ minX = fromX - (oldViewDistance * right); // inclusive
|
||||
+ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive
|
||||
+ minZ = toZ - (oldViewDistance * up); // inclusive
|
||||
+
|
||||
+ for (int currX = minX; currX != maxX; currX += right) {
|
||||
+ for (int currZ = minZ; currZ != maxZ; currZ += up) {
|
||||
+ this.removeCallback(parameter, currX, currZ);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (dz != 0) {
|
||||
+ // handle down removal
|
||||
+
|
||||
+ maxX = fromX + (oldViewDistance * right) + right; // exclusive
|
||||
+ minX = fromX - (oldViewDistance * right); // inclusive
|
||||
+ maxZ = toZ - (oldViewDistance * up); // exclusive
|
||||
+ minZ = fromZ - (oldViewDistance * up); // inclusive
|
||||
+
|
||||
+ for (int currX = minX; currX != maxX; currX += right) {
|
||||
+ for (int currZ = minZ; currZ != maxZ; currZ += up) {
|
||||
+ this.removeCallback(parameter, currX, currZ);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ public final boolean remove() {
|
||||
+ final int chunkX = this.lastChunkX;
|
||||
+ final int chunkZ = this.lastChunkZ;
|
||||
+ final int distance = this.distance;
|
||||
+ if (chunkX == NOT_SET) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ this.lastChunkX = this.lastChunkZ = this.distance = NOT_SET;
|
||||
+
|
||||
+ this.removeFromOld(this.parameter, chunkX, chunkZ, distance);
|
||||
+
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ static final class CountedSRSWLinkedQueue<E> {
|
||||
+
|
||||
+ private final SRSWLinkedQueue<E> queue = new SRSWLinkedQueue<>();
|
||||
@ -17710,7 +17511,7 @@ index 807a6bb1026dac2c4cd0a50afe06fd62ce23558b..2b998bdbe49bf8211b755e0eb7c1bf13
|
||||
// Paper end
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 8c84461a5711cb408b0ead397417c31cb2f4d336..ea0b82165e452b7b82d1d9a58eef6059cba30552 100644
|
||||
index b47e30e9ebe0d6a930e01aaf67c138fc345fb11e..e2510ee3f0cb93eae2452bec642855cd6c0c2974 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -118,10 +118,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@ -17745,7 +17546,7 @@ index 8c84461a5711cb408b0ead397417c31cb2f4d336..ea0b82165e452b7b82d1d9a58eef6059
|
||||
private final String storageName;
|
||||
private final PlayerMap playerMap;
|
||||
public final Int2ObjectMap<ChunkMap.TrackedEntity> entityMap;
|
||||
@@ -148,37 +143,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -148,26 +143,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
private final Queue<Runnable> unloadQueue;
|
||||
private int serverViewDistance;
|
||||
|
||||
@ -17773,34 +17574,38 @@ index 8c84461a5711cb408b0ead397417c31cb2f4d336..ea0b82165e452b7b82d1d9a58eef6059
|
||||
|
||||
// Paper start - distance maps
|
||||
private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets<ServerPlayer> pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>();
|
||||
|
||||
void addPlayerToDistanceMaps(ServerPlayer player) {
|
||||
+ this.level.playerChunkLoader.addPlayer(player); // Paper - replace chunk loader
|
||||
int chunkX = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getX());
|
||||
@@ -177,6 +153,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
int chunkZ = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getZ());
|
||||
// Note: players need to be explicitly added to distance maps before they can be updated
|
||||
this.nearbyPlayers.addPlayer(player);
|
||||
+ this.level.playerChunkLoader.addPlayer(player); // Paper - replace chunk loader
|
||||
}
|
||||
|
||||
void removePlayerFromDistanceMaps(ServerPlayer player) {
|
||||
+ this.level.playerChunkLoader.removePlayer(player); // Paper - replace chunk loader
|
||||
|
||||
}
|
||||
|
||||
@@ -186,6 +164,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
int chunkX = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getX());
|
||||
@@ -184,6 +161,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
int chunkZ = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getZ());
|
||||
// Note: players need to be explicitly added to distance maps before they can be updated
|
||||
this.nearbyPlayers.removePlayer(player);
|
||||
+ this.level.playerChunkLoader.removePlayer(player); // Paper - replace chunk loader
|
||||
}
|
||||
|
||||
void updateMaps(ServerPlayer player) {
|
||||
@@ -191,6 +169,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
int chunkZ = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getZ());
|
||||
// Note: players need to be explicitly added to distance maps before they can be updated
|
||||
this.nearbyPlayers.tickPlayer(player);
|
||||
+ this.level.playerChunkLoader.updatePlayer(player); // Paper - replace chunk loader
|
||||
}
|
||||
// Paper end
|
||||
// Paper start
|
||||
@@ -215,16 +194,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -220,17 +199,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
|
||||
public final ChunkHolder getUnloadingChunkHolder(int chunkX, int chunkZ) {
|
||||
- return this.pendingUnloads.get(io.papermc.paper.util.CoordinateUtils.getChunkKey(chunkX, chunkZ));
|
||||
+ return null; // Paper - rewrite chunk system
|
||||
}
|
||||
public final io.papermc.paper.util.player.NearbyPlayers nearbyPlayers;
|
||||
// Paper end
|
||||
|
||||
public ChunkMap(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureTemplateManager structureTemplateManager, Executor executor, BlockableEventLoop<Runnable> mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier<DimensionDataStorage> persistentStateManagerFactory, int viewDistance, boolean dsync) {
|
||||
@ -17813,7 +17618,7 @@ index 8c84461a5711cb408b0ead397417c31cb2f4d336..ea0b82165e452b7b82d1d9a58eef6059
|
||||
this.tickingGenerated = new AtomicInteger();
|
||||
this.playerMap = new PlayerMap();
|
||||
this.entityMap = new Int2ObjectOpenHashMap();
|
||||
@@ -255,19 +231,17 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -261,19 +237,17 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
|
||||
this.chunkGeneratorState = chunkGenerator.createState(iregistrycustom.lookupOrThrow(Registries.STRUCTURE_SET), this.randomState, j, world.spigotConfig); // Spigot
|
||||
this.mainThreadExecutor = mainThreadExecutor;
|
||||
@ -17838,7 +17643,7 @@ index 8c84461a5711cb408b0ead397417c31cb2f4d336..ea0b82165e452b7b82d1d9a58eef6059
|
||||
this.distanceManager = new ChunkMap.ChunkDistanceManager(executor, mainThreadExecutor);
|
||||
this.overworldDataStorage = persistentStateManagerFactory;
|
||||
this.poiManager = new PoiManager(path.resolve("poi"), dataFixer, dsync, iregistrycustom, world);
|
||||
@@ -311,23 +285,15 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -325,23 +299,15 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
|
||||
boolean isChunkTracked(ServerPlayer player, int chunkX, int chunkZ) {
|
||||
@ -17868,7 +17673,7 @@ index 8c84461a5711cb408b0ead397417c31cb2f4d336..ea0b82165e452b7b82d1d9a58eef6059
|
||||
}
|
||||
|
||||
protected ThreadedLevelLightEngine getLightEngine() {
|
||||
@@ -336,20 +302,22 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -350,20 +316,22 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
|
||||
@Nullable
|
||||
protected ChunkHolder getUpdatingChunkIfPresent(long pos) {
|
||||
@ -17898,7 +17703,7 @@ index 8c84461a5711cb408b0ead397417c31cb2f4d336..ea0b82165e452b7b82d1d9a58eef6059
|
||||
}
|
||||
|
||||
public String getChunkDebugData(ChunkPos chunkPos) {
|
||||
@@ -379,92 +347,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -393,92 +361,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
|
||||
// Paper start
|
||||
public final int getEffectiveViewDistance() {
|
||||
@ -17993,7 +17798,7 @@ index 8c84461a5711cb408b0ead397417c31cb2f4d336..ea0b82165e452b7b82d1d9a58eef6059
|
||||
}
|
||||
|
||||
public ReportedException debugFuturesAndCreateReportedException(IllegalStateException exception, String details) {
|
||||
@@ -494,263 +382,72 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -508,263 +396,72 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
|
||||
public CompletableFuture<Either<LevelChunk, ChunkHolder.ChunkLoadingFailure>> prepareEntityTickingChunk(ChunkHolder chunk) {
|
||||
@ -18277,7 +18082,7 @@ index 8c84461a5711cb408b0ead397417c31cb2f4d336..ea0b82165e452b7b82d1d9a58eef6059
|
||||
return nbt.contains("Status", 8);
|
||||
}
|
||||
|
||||
@@ -786,54 +483,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -800,54 +497,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
|
||||
private CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> scheduleChunkGeneration(ChunkHolder holder, ChunkStatus requiredStatus) {
|
||||
@ -18333,7 +18138,7 @@ index 8c84461a5711cb408b0ead397417c31cb2f4d336..ea0b82165e452b7b82d1d9a58eef6059
|
||||
}
|
||||
|
||||
protected void releaseLightTicket(ChunkPos pos) {
|
||||
@@ -844,7 +494,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -858,7 +508,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}));
|
||||
}
|
||||
|
||||
@ -18342,7 +18147,7 @@ index 8c84461a5711cb408b0ead397417c31cb2f4d336..ea0b82165e452b7b82d1d9a58eef6059
|
||||
ChunkStatus chunkstatus1;
|
||||
|
||||
if (distance == 0) {
|
||||
@@ -856,7 +506,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -870,7 +520,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
return chunkstatus1;
|
||||
}
|
||||
|
||||
@ -18351,7 +18156,7 @@ index 8c84461a5711cb408b0ead397417c31cb2f4d336..ea0b82165e452b7b82d1d9a58eef6059
|
||||
if (!nbt.isEmpty()) {
|
||||
// CraftBukkit start - these are spawned serialized (DefinedStructure) and we don't call an add event below at the moment due to ordering complexities
|
||||
world.addWorldGenChunkEntities(EntityType.loadEntitiesRecursive(nbt, world).filter((entity) -> {
|
||||
@@ -871,111 +521,27 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -885,111 +535,27 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
needsRemoval = true;
|
||||
}
|
||||
return !needsRemoval;
|
||||
@ -18468,7 +18273,7 @@ index 8c84461a5711cb408b0ead397417c31cb2f4d336..ea0b82165e452b7b82d1d9a58eef6059
|
||||
}
|
||||
|
||||
public int getTickingGenerated() {
|
||||
@@ -983,130 +549,52 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -997,130 +563,52 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
|
||||
private boolean saveChunkIfNeeded(ChunkHolder chunkHolder) {
|
||||
@ -18616,7 +18421,7 @@ index 8c84461a5711cb408b0ead397417c31cb2f4d336..ea0b82165e452b7b82d1d9a58eef6059
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -1129,30 +617,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1143,30 +631,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
|
||||
void dumpChunks(Writer writer) throws IOException {
|
||||
@ -18648,7 +18453,7 @@ index 8c84461a5711cb408b0ead397417c31cb2f4d336..ea0b82165e452b7b82d1d9a58eef6059
|
||||
}
|
||||
|
||||
private static String printFuture(CompletableFuture<Either<LevelChunk, ChunkHolder.ChunkLoadingFailure>> future) {
|
||||
@@ -1171,6 +636,35 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1185,6 +650,35 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
}
|
||||
|
||||
@ -18684,7 +18489,7 @@ index 8c84461a5711cb408b0ead397417c31cb2f4d336..ea0b82165e452b7b82d1d9a58eef6059
|
||||
private CompletableFuture<Optional<CompoundTag>> readChunk(ChunkPos chunkPos) {
|
||||
return this.read(chunkPos).thenApplyAsync((optional) -> {
|
||||
return optional.map((nbttagcompound) -> this.upgradeChunkTag(nbttagcompound, chunkPos)); // CraftBukkit
|
||||
@@ -1260,8 +754,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1274,8 +768,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
this.distanceManager.addPlayer(SectionPos.of((EntityAccess) player), player);
|
||||
}
|
||||
|
||||
@ -18694,7 +18499,7 @@ index 8c84461a5711cb408b0ead397417c31cb2f4d336..ea0b82165e452b7b82d1d9a58eef6059
|
||||
this.addPlayerToDistanceMaps(player); // Paper - distance maps
|
||||
} else {
|
||||
SectionPos sectionposition = player.getLastSectionPos();
|
||||
@@ -1272,7 +765,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1286,7 +779,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
|
||||
this.removePlayerFromDistanceMaps(player); // Paper - distance maps
|
||||
@ -18703,7 +18508,7 @@ index 8c84461a5711cb408b0ead397417c31cb2f4d336..ea0b82165e452b7b82d1d9a58eef6059
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1320,73 +813,30 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1334,73 +827,30 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
this.playerMap.unIgnorePlayer(player);
|
||||
}
|
||||
|
||||
@ -18787,7 +18592,7 @@ index 8c84461a5711cb408b0ead397417c31cb2f4d336..ea0b82165e452b7b82d1d9a58eef6059
|
||||
}
|
||||
|
||||
public void addEntity(Entity entity) {
|
||||
@@ -1450,13 +900,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1464,13 +914,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
|
||||
protected void tick() {
|
||||
@ -18802,7 +18607,7 @@ index 8c84461a5711cb408b0ead397417c31cb2f4d336..ea0b82165e452b7b82d1d9a58eef6059
|
||||
|
||||
List<ServerPlayer> list = Lists.newArrayList();
|
||||
List<ServerPlayer> list1 = this.level.players();
|
||||
@@ -1565,16 +1009,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1579,16 +1023,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
|
||||
public void waitForLightBeforeSending(ChunkPos centerPos, int radius) {
|
||||
@ -18820,7 +18625,7 @@ index 8c84461a5711cb408b0ead397417c31cb2f4d336..ea0b82165e452b7b82d1d9a58eef6059
|
||||
}
|
||||
|
||||
private class ChunkDistanceManager extends DistanceManager {
|
||||
@@ -1585,7 +1020,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1599,7 +1034,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
|
||||
@Override
|
||||
protected boolean isChunkToRemove(long pos) {
|
||||
@ -21501,10 +21306,18 @@ index 846ae3fd184a1d63b743aa25e045604576697c96..a907b79fd8291a0e92db138f37239d17
|
||||
|
||||
public int getIndex() {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index bcdaa86cfd31c2ce4aadad900c348aee0a9e3fc8..a8b2ce0debe54afeb937a4f1215d6b8955037d3d 100644
|
||||
index bcdaa86cfd31c2ce4aadad900c348aee0a9e3fc8..85b38592c87bbc071d3fc5de5db131c6626fe004 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -661,9 +661,26 @@ public class LevelChunk extends ChunkAccess {
|
||||
@@ -83,6 +83,7 @@ public class LevelChunk extends ChunkAccess {
|
||||
private final Int2ObjectMap<GameEventListenerRegistry> gameEventListenerRegistrySections;
|
||||
private final LevelChunkTicks<Block> blockTicks;
|
||||
private final LevelChunkTicks<Fluid> fluidTicks;
|
||||
+ public volatile FullChunkStatus chunkStatus = FullChunkStatus.INACCESSIBLE; // Paper - rewrite chunk system
|
||||
|
||||
public LevelChunk(Level world, ChunkPos pos) {
|
||||
this(world, pos, UpgradeData.EMPTY, new LevelChunkTicks<>(), new LevelChunkTicks<>(), 0L, (LevelChunkSection[]) null, (LevelChunk.PostLoadProcessor) null, (BlendingData) null);
|
||||
@@ -661,9 +662,26 @@ public class LevelChunk extends ChunkAccess {
|
||||
|
||||
}
|
||||
|
||||
@ -21534,7 +21347,7 @@ index bcdaa86cfd31c2ce4aadad900c348aee0a9e3fc8..a8b2ce0debe54afeb937a4f1215d6b89
|
||||
int chunkX = this.chunkPos.x;
|
||||
int chunkZ = this.chunkPos.z;
|
||||
net.minecraft.server.level.ServerChunkCache chunkProvider = this.level.getChunkSource();
|
||||
@@ -678,10 +695,55 @@ public class LevelChunk extends ChunkAccess {
|
||||
@@ -678,10 +696,55 @@ public class LevelChunk extends ChunkAccess {
|
||||
}
|
||||
}
|
||||
this.setNeighbourLoaded(0, 0, this);
|
||||
@ -21592,7 +21405,7 @@ index bcdaa86cfd31c2ce4aadad900c348aee0a9e3fc8..a8b2ce0debe54afeb937a4f1215d6b89
|
||||
if (server != null) {
|
||||
/*
|
||||
* If it's a new world, the first few chunks are generated inside
|
||||
@@ -690,6 +752,7 @@ public class LevelChunk extends ChunkAccess {
|
||||
@@ -690,6 +753,7 @@ public class LevelChunk extends ChunkAccess {
|
||||
*/
|
||||
org.bukkit.Chunk bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this);
|
||||
server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkLoadEvent(bukkitChunk, this.needsDecoration));
|
||||
@ -21600,7 +21413,7 @@ index bcdaa86cfd31c2ce4aadad900c348aee0a9e3fc8..a8b2ce0debe54afeb937a4f1215d6b89
|
||||
|
||||
if (this.needsDecoration) {
|
||||
try (co.aikar.timings.Timing ignored = this.level.timings.chunkLoadPopulate.startTiming()) { // Paper
|
||||
@@ -718,9 +781,11 @@ public class LevelChunk extends ChunkAccess {
|
||||
@@ -718,9 +782,11 @@ public class LevelChunk extends ChunkAccess {
|
||||
}
|
||||
|
||||
public void unloadCallback() {
|
||||
@ -21613,7 +21426,7 @@ index bcdaa86cfd31c2ce4aadad900c348aee0a9e3fc8..a8b2ce0debe54afeb937a4f1215d6b89
|
||||
server.getPluginManager().callEvent(unloadEvent);
|
||||
// note: saving can be prevented, but not forced if no saving is actually required
|
||||
this.mustNotSave = !unloadEvent.isSaveChunk();
|
||||
@@ -742,9 +807,26 @@ public class LevelChunk extends ChunkAccess {
|
||||
@@ -742,9 +808,26 @@ public class LevelChunk extends ChunkAccess {
|
||||
// Paper end
|
||||
}
|
||||
|
||||
@ -21641,7 +21454,7 @@ index bcdaa86cfd31c2ce4aadad900c348aee0a9e3fc8..a8b2ce0debe54afeb937a4f1215d6b89
|
||||
}
|
||||
// CraftBukkit end
|
||||
|
||||
@@ -813,7 +895,9 @@ public class LevelChunk extends ChunkAccess {
|
||||
@@ -813,7 +896,9 @@ public class LevelChunk extends ChunkAccess {
|
||||
return this.blockEntities;
|
||||
}
|
||||
|
||||
@ -21651,7 +21464,7 @@ index bcdaa86cfd31c2ce4aadad900c348aee0a9e3fc8..a8b2ce0debe54afeb937a4f1215d6b89
|
||||
ChunkPos chunkcoordintpair = this.getPos();
|
||||
|
||||
for (int i = 0; i < this.postProcessing.length; ++i) {
|
||||
@@ -834,6 +918,7 @@ public class LevelChunk extends ChunkAccess {
|
||||
@@ -834,6 +919,7 @@ public class LevelChunk extends ChunkAccess {
|
||||
BlockState iblockdata1 = Block.updateFromNeighbourShapes(iblockdata, this.level, blockposition);
|
||||
|
||||
this.level.setBlock(blockposition, iblockdata1, 20);
|
||||
@ -21659,7 +21472,7 @@ index bcdaa86cfd31c2ce4aadad900c348aee0a9e3fc8..a8b2ce0debe54afeb937a4f1215d6b89
|
||||
}
|
||||
}
|
||||
|
||||
@@ -851,6 +936,10 @@ public class LevelChunk extends ChunkAccess {
|
||||
@@ -851,6 +937,10 @@ public class LevelChunk extends ChunkAccess {
|
||||
|
||||
this.pendingBlockEntities.clear();
|
||||
this.upgradeData.upgrade(this);
|
||||
@ -21670,7 +21483,7 @@ index bcdaa86cfd31c2ce4aadad900c348aee0a9e3fc8..a8b2ce0debe54afeb937a4f1215d6b89
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -900,7 +989,7 @@ public class LevelChunk extends ChunkAccess {
|
||||
@@ -900,7 +990,7 @@ public class LevelChunk extends ChunkAccess {
|
||||
}
|
||||
|
||||
public FullChunkStatus getFullStatus() {
|
||||
|
@ -44,10 +44,10 @@ index b300d12e9e00519028b53aca9c3fb01f589eaa91..63acd109a79ed752a05df3d4f1b99309
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index a8b2ce0debe54afeb937a4f1215d6b8955037d3d..515aedcf9969b818dfdc02a16a7f7178b5bb5593 100644
|
||||
index 85b38592c87bbc071d3fc5de5db131c6626fe004..fde60133d2c5557cd8d4a4d2e3a16aa96974fcbb 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -1146,11 +1146,11 @@ public class LevelChunk extends ChunkAccess {
|
||||
@@ -1147,11 +1147,11 @@ public class LevelChunk extends ChunkAccess {
|
||||
|
||||
gameprofilerfiller.pop();
|
||||
} catch (Throwable throwable) {
|
||||
|
@ -131,7 +131,7 @@ index 5d65baba605dd83e5f74d526aeda36d8ede8c014..92e76dd39dc3575e9466031dd799080a
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index 515aedcf9969b818dfdc02a16a7f7178b5bb5593..56900156d79781f15357a3d25906d32b615366ce 100644
|
||||
index fde60133d2c5557cd8d4a4d2e3a16aa96974fcbb..d13652d5001c117582b8c470d40207a6c10cb096 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -1,6 +1,7 @@
|
||||
@ -142,7 +142,7 @@ index 515aedcf9969b818dfdc02a16a7f7178b5bb5593..56900156d79781f15357a3d25906d32b
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.UnmodifiableIterator;
|
||||
import com.mojang.logging.LogUtils;
|
||||
@@ -568,10 +569,16 @@ public class LevelChunk extends ChunkAccess {
|
||||
@@ -569,10 +570,16 @@ public class LevelChunk extends ChunkAccess {
|
||||
|
||||
// CraftBukkit start
|
||||
} else {
|
||||
@ -163,7 +163,7 @@ index 515aedcf9969b818dfdc02a16a7f7178b5bb5593..56900156d79781f15357a3d25906d32b
|
||||
// CraftBukkit end
|
||||
}
|
||||
}
|
||||
@@ -1149,6 +1156,7 @@ public class LevelChunk extends ChunkAccess {
|
||||
@@ -1150,6 +1157,7 @@ public class LevelChunk extends ChunkAccess {
|
||||
// Paper start - Prevent tile entity and entity crashes
|
||||
final String msg = String.format("BlockEntity threw exception at %s:%s,%s,%s", LevelChunk.this.getLevel().getWorld().getName(), this.getPos().getX(), this.getPos().getY(), this.getPos().getZ());
|
||||
net.minecraft.server.MinecraftServer.LOGGER.error(msg, throwable);
|
||||
|
@ -88,10 +88,10 @@ index 60e760b42dd6471a229dfd45490dcf8c51979d35..4a3ac7dedf5cb1e76f16ec4f18e82afc
|
||||
@Override
|
||||
public FluidState getFluidState(BlockPos pos) {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index 56900156d79781f15357a3d25906d32b615366ce..0eedaf7df86b7bdd22623231f9a49da8e798f204 100644
|
||||
index d13652d5001c117582b8c470d40207a6c10cb096..f6286284b95df0ab6109ff14fda33a48b163f8c2 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -295,12 +295,29 @@ public class LevelChunk extends ChunkAccess {
|
||||
@@ -296,12 +296,29 @@ public class LevelChunk extends ChunkAccess {
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,10 +11,10 @@ For people who want all chunks to be treated equally, you can chose a fixed valu
|
||||
This allows to fine-tune vanilla gameplay.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index 0eedaf7df86b7bdd22623231f9a49da8e798f204..cf910b466a4b75c0b9219abef5c9bff30793d7bf 100644
|
||||
index f6286284b95df0ab6109ff14fda33a48b163f8c2..391ef1eb8c842a1a2dbce45eec8a030f615926d6 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -280,6 +280,13 @@ public class LevelChunk extends ChunkAccess {
|
||||
@@ -281,6 +281,13 @@ public class LevelChunk extends ChunkAccess {
|
||||
return new ChunkAccess.TicksToSave(this.blockTicks, this.fluidTicks);
|
||||
}
|
||||
|
||||
|
@ -9,10 +9,10 @@ from triggering monster spawns on a server.
|
||||
Also a highly more effecient way to blanket block spawns in a world
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index ea0b82165e452b7b82d1d9a58eef6059cba30552..cdcad9e1470a0b465ee96d1f2b4b8b31e8c3d219 100644
|
||||
index e2510ee3f0cb93eae2452bec642855cd6c0c2974..c483acf248484220aaca2100c84e75f3b46fbd31 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -687,7 +687,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -701,7 +701,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.spigotConfig.viewDistance : chunkRange;
|
||||
chunkRange = (chunkRange > 8) ? 8 : chunkRange;
|
||||
|
||||
@ -23,7 +23,7 @@ index ea0b82165e452b7b82d1d9a58eef6059cba30552..cdcad9e1470a0b465ee96d1f2b4b8b31
|
||||
// Spigot end
|
||||
if (!this.distanceManager.hasPlayersNearby(chunkcoordintpair.toLong())) {
|
||||
return false;
|
||||
@@ -702,6 +704,15 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -716,6 +718,15 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
|
||||
entityplayer = (ServerPlayer) iterator.next();
|
||||
|
@ -8,10 +8,10 @@ Add -Ddebug.entities=true to your JVM flags to gain more information
|
||||
1.17: Needs to be reworked for new entity storage system
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index cdcad9e1470a0b465ee96d1f2b4b8b31e8c3d219..165daf5e4b44425974703e9f603955fa09984f1b 100644
|
||||
index c483acf248484220aaca2100c84e75f3b46fbd31..c69be9cb3f03ec50e4e57d7e1e93a83701e4cd6c 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -865,6 +865,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -879,6 +879,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
} else {
|
||||
ChunkMap.TrackedEntity playerchunkmap_entitytracker = new ChunkMap.TrackedEntity(entity, i, j, entitytypes.trackDeltas());
|
||||
|
||||
@ -19,7 +19,7 @@ index cdcad9e1470a0b465ee96d1f2b4b8b31e8c3d219..165daf5e4b44425974703e9f603955fa
|
||||
this.entityMap.put(entity.getId(), playerchunkmap_entitytracker);
|
||||
playerchunkmap_entitytracker.updatePlayers(this.level.players());
|
||||
if (entity instanceof ServerPlayer) {
|
||||
@@ -907,7 +908,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -921,7 +922,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
if (playerchunkmap_entitytracker1 != null) {
|
||||
playerchunkmap_entitytracker1.broadcastRemoved();
|
||||
}
|
||||
|
@ -8,10 +8,10 @@ This patch also adds a chunk status cache on region files (note that
|
||||
its only purpose is to cache the status on DISK)
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 165daf5e4b44425974703e9f603955fa09984f1b..a8533bbac77c6024cd6163149affe4f4733019b5 100644
|
||||
index c69be9cb3f03ec50e4e57d7e1e93a83701e4cd6c..5b7260b5a14cb9d2b90cf3c411d119e6bfa84046 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -666,9 +666,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -680,9 +680,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
// Paper end
|
||||
|
||||
private CompletableFuture<Optional<CompoundTag>> readChunk(ChunkPos chunkPos) {
|
||||
@ -28,7 +28,7 @@ index 165daf5e4b44425974703e9f603955fa09984f1b..a8533bbac77c6024cd6163149affe4f4
|
||||
}
|
||||
|
||||
// CraftBukkit start
|
||||
@@ -677,6 +681,63 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -691,6 +695,63 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
// CraftBukkit end
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ But for those who are ok with leaving this inconsistent behavior, you may use WA
|
||||
It is recommended you regenerate the entities, as these were legit entities, and deserve your love.
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/chunk/system/ChunkSystem.java b/src/main/java/io/papermc/paper/chunk/system/ChunkSystem.java
|
||||
index 56c35149fd142af6ffe31434fec0064cf6ea3be5..14e24e3bd8695c7038e8e1f4fb92ca3fd20c6258 100644
|
||||
index cbeaadaecf816070b3a37938c8e683180939afc4..95e5073a68e4dd38b70e8268daf2160922c3a12f 100644
|
||||
--- a/src/main/java/io/papermc/paper/chunk/system/ChunkSystem.java
|
||||
+++ b/src/main/java/io/papermc/paper/chunk/system/ChunkSystem.java
|
||||
@@ -74,7 +74,17 @@ public final class ChunkSystem {
|
||||
@ -56,10 +56,10 @@ index 56c35149fd142af6ffe31434fec0064cf6ea3be5..14e24e3bd8695c7038e8e1f4fb92ca3f
|
||||
|
||||
public static void onChunkHolderCreate(final ServerLevel level, final ChunkHolder holder) {
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index a8533bbac77c6024cd6163149affe4f4733019b5..de89863bae07b6e1264b0c70287c085a716862e4 100644
|
||||
index 5b7260b5a14cb9d2b90cf3c411d119e6bfa84046..0b1aadd3648f46680e4edc137de3e5ce52428383 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -520,6 +520,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -534,6 +534,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
entity.discard();
|
||||
needsRemoval = true;
|
||||
}
|
||||
@ -67,7 +67,7 @@ index a8533bbac77c6024cd6163149affe4f4733019b5..de89863bae07b6e1264b0c70287c085a
|
||||
return !needsRemoval;
|
||||
}), position); // Paper - rewrite chunk system
|
||||
// CraftBukkit end
|
||||
@@ -531,6 +532,49 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -545,6 +546,49 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
throw new UnsupportedOperationException(); // Paper - rewrite chunk system
|
||||
}
|
||||
|
||||
|
@ -8,10 +8,10 @@ Sets tracking range of watermobs to animals instead of misc and simplifies code
|
||||
Also ignores Enderdragon, defaulting it to Mojang's setting
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index de89863bae07b6e1264b0c70287c085a716862e4..ed43ade8c884f9fe7945ef20c1dd2cf5c70680d3 100644
|
||||
index 0b1aadd3648f46680e4edc137de3e5ce52428383..06e53890fab287846c8d846f1f829650a1b3c09b 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -1251,6 +1251,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1265,6 +1265,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
while (iterator.hasNext()) {
|
||||
Entity entity = (Entity) iterator.next();
|
||||
int j = entity.getType().clientTrackingRange() * 16;
|
||||
|
@ -4,309 +4,11 @@ Date: Mon, 19 Aug 2019 01:27:58 +0500
|
||||
Subject: [PATCH] implement optional per player mob spawns
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/util/PooledHashSets.java b/src/main/java/com/destroystokyo/paper/util/PooledHashSets.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..11de56afaf059b00fa5bec293516bcdce7c4b2b9
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/util/PooledHashSets.java
|
||||
@@ -0,0 +1,241 @@
|
||||
+package com.destroystokyo.paper.util;
|
||||
+
|
||||
+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
+import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet;
|
||||
+import java.lang.ref.WeakReference;
|
||||
+import java.util.Iterator;
|
||||
+
|
||||
+/** @author Spottedleaf */
|
||||
+public class PooledHashSets<E> {
|
||||
+
|
||||
+ // we really want to avoid that equals() check as much as possible...
|
||||
+ protected final Object2ObjectOpenHashMap<PooledObjectLinkedOpenHashSet<E>, PooledObjectLinkedOpenHashSet<E>> mapPool = new Object2ObjectOpenHashMap<>(64, 0.25f);
|
||||
+
|
||||
+ protected void decrementReferenceCount(final PooledObjectLinkedOpenHashSet<E> current) {
|
||||
+ if (current.referenceCount == 0) {
|
||||
+ throw new IllegalStateException("Cannot decrement reference count for " + current);
|
||||
+ }
|
||||
+ if (current.referenceCount == -1 || --current.referenceCount > 0) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ this.mapPool.remove(current);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ public PooledObjectLinkedOpenHashSet<E> findMapWith(final PooledObjectLinkedOpenHashSet<E> current, final E object) {
|
||||
+ final PooledObjectLinkedOpenHashSet<E> cached = current.getAddCache(object);
|
||||
+
|
||||
+ if (cached != null) {
|
||||
+ if (cached.referenceCount != -1) {
|
||||
+ ++cached.referenceCount;
|
||||
+ }
|
||||
+
|
||||
+ decrementReferenceCount(current);
|
||||
+
|
||||
+ return cached;
|
||||
+ }
|
||||
+
|
||||
+ if (!current.add(object)) {
|
||||
+ return current;
|
||||
+ }
|
||||
+
|
||||
+ // we use get/put since we use a different key on put
|
||||
+ PooledObjectLinkedOpenHashSet<E> ret = this.mapPool.get(current);
|
||||
+
|
||||
+ if (ret == null) {
|
||||
+ ret = new PooledObjectLinkedOpenHashSet<>(current);
|
||||
+ current.remove(object);
|
||||
+ this.mapPool.put(ret, ret);
|
||||
+ ret.referenceCount = 1;
|
||||
+ } else {
|
||||
+ if (ret.referenceCount != -1) {
|
||||
+ ++ret.referenceCount;
|
||||
+ }
|
||||
+ current.remove(object);
|
||||
+ }
|
||||
+
|
||||
+ current.updateAddCache(object, ret);
|
||||
+
|
||||
+ decrementReferenceCount(current);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ // rets null if current.size() == 1
|
||||
+ public PooledObjectLinkedOpenHashSet<E> findMapWithout(final PooledObjectLinkedOpenHashSet<E> current, final E object) {
|
||||
+ if (current.set.size() == 1) {
|
||||
+ decrementReferenceCount(current);
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ final PooledObjectLinkedOpenHashSet<E> cached = current.getRemoveCache(object);
|
||||
+
|
||||
+ if (cached != null) {
|
||||
+ if (cached.referenceCount != -1) {
|
||||
+ ++cached.referenceCount;
|
||||
+ }
|
||||
+
|
||||
+ decrementReferenceCount(current);
|
||||
+
|
||||
+ return cached;
|
||||
+ }
|
||||
+
|
||||
+ if (!current.remove(object)) {
|
||||
+ return current;
|
||||
+ }
|
||||
+
|
||||
+ // we use get/put since we use a different key on put
|
||||
+ PooledObjectLinkedOpenHashSet<E> ret = this.mapPool.get(current);
|
||||
+
|
||||
+ if (ret == null) {
|
||||
+ ret = new PooledObjectLinkedOpenHashSet<>(current);
|
||||
+ current.add(object);
|
||||
+ this.mapPool.put(ret, ret);
|
||||
+ ret.referenceCount = 1;
|
||||
+ } else {
|
||||
+ if (ret.referenceCount != -1) {
|
||||
+ ++ret.referenceCount;
|
||||
+ }
|
||||
+ current.add(object);
|
||||
+ }
|
||||
+
|
||||
+ current.updateRemoveCache(object, ret);
|
||||
+
|
||||
+ decrementReferenceCount(current);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ public static final class PooledObjectLinkedOpenHashSet<E> implements Iterable<E> {
|
||||
+
|
||||
+ private static final WeakReference NULL_REFERENCE = new WeakReference(null);
|
||||
+
|
||||
+ final ObjectLinkedOpenHashSet<E> set;
|
||||
+ int referenceCount; // -1 if special
|
||||
+ int hash; // optimize hashcode
|
||||
+
|
||||
+ // add cache
|
||||
+ WeakReference<E> lastAddObject = NULL_REFERENCE;
|
||||
+ WeakReference<PooledObjectLinkedOpenHashSet<E>> lastAddMap = NULL_REFERENCE;
|
||||
+
|
||||
+ // remove cache
|
||||
+ WeakReference<E> lastRemoveObject = NULL_REFERENCE;
|
||||
+ WeakReference<PooledObjectLinkedOpenHashSet<E>> lastRemoveMap = NULL_REFERENCE;
|
||||
+
|
||||
+ public PooledObjectLinkedOpenHashSet() {
|
||||
+ this.set = new ObjectLinkedOpenHashSet<>(2, 0.6f);
|
||||
+ }
|
||||
+
|
||||
+ public PooledObjectLinkedOpenHashSet(final E single) {
|
||||
+ this();
|
||||
+ this.referenceCount = -1;
|
||||
+ this.add(single);
|
||||
+ }
|
||||
+
|
||||
+ public PooledObjectLinkedOpenHashSet(final PooledObjectLinkedOpenHashSet<E> other) {
|
||||
+ this.set = other.set.clone();
|
||||
+ this.hash = other.hash;
|
||||
+ }
|
||||
+
|
||||
+ // from https://github.com/Spottedleaf/ConcurrentUtil/blob/master/src/main/java/ca/spottedleaf/concurrentutil/util/IntegerUtil.java
|
||||
+ // generated by https://github.com/skeeto/hash-prospector
|
||||
+ static int hash0(int x) {
|
||||
+ x *= 0x36935555;
|
||||
+ x ^= x >>> 16;
|
||||
+ return x;
|
||||
+ }
|
||||
+
|
||||
+ public PooledObjectLinkedOpenHashSet<E> getAddCache(final E element) {
|
||||
+ final E currentAdd = this.lastAddObject.get();
|
||||
+
|
||||
+ if (currentAdd == null || !(currentAdd == element || currentAdd.equals(element))) {
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ final PooledObjectLinkedOpenHashSet<E> map = this.lastAddMap.get();
|
||||
+ if (map == null || map.referenceCount == 0) {
|
||||
+ // we need to ret null if ref count is zero as calling code will assume the map is in use
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ return map;
|
||||
+ }
|
||||
+
|
||||
+ public PooledObjectLinkedOpenHashSet<E> getRemoveCache(final E element) {
|
||||
+ final E currentRemove = this.lastRemoveObject.get();
|
||||
+
|
||||
+ if (currentRemove == null || !(currentRemove == element || currentRemove.equals(element))) {
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ final PooledObjectLinkedOpenHashSet<E> map = this.lastRemoveMap.get();
|
||||
+ if (map == null || map.referenceCount == 0) {
|
||||
+ // we need to ret null if ref count is zero as calling code will assume the map is in use
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ return map;
|
||||
+ }
|
||||
+
|
||||
+ public void updateAddCache(final E element, final PooledObjectLinkedOpenHashSet<E> map) {
|
||||
+ this.lastAddObject = new WeakReference<>(element);
|
||||
+ this.lastAddMap = new WeakReference<>(map);
|
||||
+ }
|
||||
+
|
||||
+ public void updateRemoveCache(final E element, final PooledObjectLinkedOpenHashSet<E> map) {
|
||||
+ this.lastRemoveObject = new WeakReference<>(element);
|
||||
+ this.lastRemoveMap = new WeakReference<>(map);
|
||||
+ }
|
||||
+
|
||||
+ boolean add(final E element) {
|
||||
+ boolean added = this.set.add(element);
|
||||
+
|
||||
+ if (added) {
|
||||
+ this.hash += hash0(element.hashCode());
|
||||
+ }
|
||||
+
|
||||
+ return added;
|
||||
+ }
|
||||
+
|
||||
+ boolean remove(Object element) {
|
||||
+ boolean removed = this.set.remove(element);
|
||||
+
|
||||
+ if (removed) {
|
||||
+ this.hash -= hash0(element.hashCode());
|
||||
+ }
|
||||
+
|
||||
+ return removed;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Iterator<E> iterator() {
|
||||
+ return this.set.iterator();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int hashCode() {
|
||||
+ return this.hash;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean equals(final Object other) {
|
||||
+ if (!(other instanceof PooledObjectLinkedOpenHashSet)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (this.referenceCount == 0) {
|
||||
+ return other == this;
|
||||
+ } else {
|
||||
+ if (other == this) {
|
||||
+ // Unfortunately we are never equal to our own instance while in use!
|
||||
+ return false;
|
||||
+ }
|
||||
+ return this.hash == ((PooledObjectLinkedOpenHashSet)other).hash && this.set.equals(((PooledObjectLinkedOpenHashSet)other).set);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public String toString() {
|
||||
+ return "PooledHashSet: size: " + this.set.size() + ", reference count: " + this.referenceCount + ", hash: " +
|
||||
+ this.hashCode() + ", identity: " + System.identityHashCode(this) + " map: " + this.set.toString();
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index ed43ade8c884f9fe7945ef20c1dd2cf5c70680d3..1f30d06781cea0855be26784c239e71ed1a2f6c3 100644
|
||||
index 06e53890fab287846c8d846f1f829650a1b3c09b..847019bf4a81b82e6e11a19aebd69b7270d81b06 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -142,6 +142,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
private final Long2LongMap chunkSaveCooldowns;
|
||||
private final Queue<Runnable> unloadQueue;
|
||||
private int serverViewDistance;
|
||||
+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerMobDistanceMap; // Paper
|
||||
|
||||
// Paper - rewrite chunk system
|
||||
|
||||
@@ -153,11 +154,21 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
int chunkX = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getX());
|
||||
int chunkZ = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getZ());
|
||||
// Note: players need to be explicitly added to distance maps before they can be updated
|
||||
+ // Paper start - per player mob spawning
|
||||
+ if (this.playerMobDistanceMap != null) {
|
||||
+ this.playerMobDistanceMap.add(player, chunkX, chunkZ, io.papermc.paper.chunk.system.ChunkSystem.getTickViewDistance(player));
|
||||
+ }
|
||||
+ // Paper end - per player mob spawning
|
||||
}
|
||||
|
||||
void removePlayerFromDistanceMaps(ServerPlayer player) {
|
||||
this.level.playerChunkLoader.removePlayer(player); // Paper - replace chunk loader
|
||||
|
||||
+ // Paper start - per player mob spawning
|
||||
+ if (this.playerMobDistanceMap != null) {
|
||||
+ this.playerMobDistanceMap.remove(player);
|
||||
+ }
|
||||
+ // Paper end - per player mob spawning
|
||||
}
|
||||
|
||||
void updateMaps(ServerPlayer player) {
|
||||
@@ -165,6 +176,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
int chunkZ = io.papermc.paper.util.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
|
||||
+
|
||||
+ // Paper start - per player mob spawning
|
||||
+ if (this.playerMobDistanceMap != null) {
|
||||
+ this.playerMobDistanceMap.update(player, chunkX, chunkZ, io.papermc.paper.chunk.system.ChunkSystem.getTickViewDistance(player));
|
||||
+ }
|
||||
+ // Paper end - per player mob spawning
|
||||
}
|
||||
// Paper end
|
||||
// Paper start
|
||||
@@ -250,6 +267,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
this.dataRegionManager = new io.papermc.paper.chunk.SingleThreadChunkRegionManager(this.level, 2, (1.0 / 3.0), 1, 6, "Data", DataRegionData::new, DataRegionSectionData::new);
|
||||
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
|
||||
}
|
||||
|
||||
protected ChunkGenerator generator() {
|
||||
@@ -275,6 +293,31 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -289,6 +289,29 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
});
|
||||
}
|
||||
|
||||
@ -317,16 +19,14 @@ index ed43ade8c884f9fe7945ef20c1dd2cf5c70680d3..1f30d06781cea0855be26784c239e71e
|
||||
+ }
|
||||
+ int index = entity.getType().getCategory().ordinal();
|
||||
+
|
||||
+ final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> inRange = this.playerMobDistanceMap.getObjectsInRange(entity.chunkPosition());
|
||||
+ final com.destroystokyo.paper.util.maplist.ReferenceList<ServerPlayer> inRange =
|
||||
+ this.getNearbyPlayers().getPlayers(entity.chunkPosition(), io.papermc.paper.util.player.NearbyPlayers.NearbyMapType.TICK_VIEW_DISTANCE);
|
||||
+ if (inRange == null) {
|
||||
+ return;
|
||||
+ }
|
||||
+ final Object[] backingSet = inRange.getBackingSet();
|
||||
+ for (int i = 0; i < backingSet.length; i++) {
|
||||
+ if (!(backingSet[i] instanceof final ServerPlayer player)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ ++player.mobCounts[index];
|
||||
+ final Object[] backingSet = inRange.getRawData();
|
||||
+ for (int i = 0, len = inRange.size(); i < len; i++) {
|
||||
+ ++((ServerPlayer)backingSet[i]).mobCounts[index];
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
@ -339,7 +39,7 @@ index ed43ade8c884f9fe7945ef20c1dd2cf5c70680d3..1f30d06781cea0855be26784c239e71e
|
||||
double d0 = (double) SectionPos.sectionToBlockCoord(pos.x, 8);
|
||||
double d1 = (double) SectionPos.sectionToBlockCoord(pos.z, 8);
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
index 4649e597b86335b33d9e9227d966dd7ad8208096..e655cf837f7bd7d4271dca80b9c6764372336910 100644
|
||||
index 4649e597b86335b33d9e9227d966dd7ad8208096..b73d45c205db39ed3e97a127e53371db81e0d63f 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -543,7 +543,18 @@ public class ServerChunkCache extends ChunkSource {
|
||||
@ -349,45 +49,36 @@ index 4649e597b86335b33d9e9227d966dd7ad8208096..e655cf837f7bd7d4271dca80b9c67643
|
||||
- NaturalSpawner.SpawnState spawnercreature_d = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk, new LocalMobCapCalculator(this.chunkMap));
|
||||
+ // Paper start - per player mob spawning
|
||||
+ NaturalSpawner.SpawnState spawnercreature_d; // moved down
|
||||
+ if ((this.spawnFriendlies || this.spawnEnemies) && this.chunkMap.playerMobDistanceMap != null) { // don't count mobs when animals and monsters are disabled
|
||||
+ if ((this.spawnFriendlies || this.spawnEnemies) && this.level.paperConfig().entities.spawning.perPlayerMobSpawns) { // don't count mobs when animals and monsters are disabled
|
||||
+ // re-set mob counts
|
||||
+ for (ServerPlayer player : this.level.players) {
|
||||
+ Arrays.fill(player.mobCounts, 0);
|
||||
+ }
|
||||
+ spawnercreature_d = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk, null, true);
|
||||
+ } else {
|
||||
+ spawnercreature_d = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk, this.chunkMap.playerMobDistanceMap == null ? new LocalMobCapCalculator(this.chunkMap) : null, false);
|
||||
+ spawnercreature_d = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false);
|
||||
+ }
|
||||
+ // Paper end
|
||||
this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings
|
||||
|
||||
this.lastSpawnState = spawnercreature_d;
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index dcb6a1bd3774e63dd14fbd8ddd6ff09c68741379..ad34d1562131a5140c4cc83aa3ea94fab08d12da 100644
|
||||
index dcb6a1bd3774e63dd14fbd8ddd6ff09c68741379..55c3416f209178a1a100228d9b1db620c79bc288 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -246,6 +246,11 @@ public class ServerPlayer extends Player {
|
||||
@@ -246,6 +246,10 @@ public class ServerPlayer extends Player {
|
||||
public boolean queueHealthUpdatePacket = false;
|
||||
public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket;
|
||||
// Paper end
|
||||
+ // Paper start - mob spawning rework
|
||||
+ public static final int MOBCATEGORY_TOTAL_ENUMS = net.minecraft.world.entity.MobCategory.values().length;
|
||||
+ public final int[] mobCounts = new int[MOBCATEGORY_TOTAL_ENUMS]; // Paper
|
||||
+ public final com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> cachedSingleMobDistanceMap;
|
||||
+ // Paper end
|
||||
+ // Paper end - mob spawning rework
|
||||
|
||||
// CraftBukkit start
|
||||
public String displayName;
|
||||
@@ -383,6 +388,7 @@ public class ServerPlayer extends Player {
|
||||
this.adventure$displayName = net.kyori.adventure.text.Component.text(this.getScoreboardName()); // Paper
|
||||
this.bukkitPickUpLoot = true;
|
||||
this.maxHealthCache = this.getMaxHealth();
|
||||
+ this.cachedSingleMobDistanceMap = new com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper
|
||||
}
|
||||
|
||||
// Yes, this doesn't match Vanilla, but it's the best we can do for now.
|
||||
diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
||||
index fe38079d69f3e9987ad5ab077ae09d05017a681a..7983f9a21251cec4857529ad1180a62668ea5037 100644
|
||||
index fe38079d69f3e9987ad5ab077ae09d05017a681a..9df761f5cf043e8d2dffa711c20ab32fe2992331 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
||||
@@ -70,6 +70,12 @@ public final class NaturalSpawner {
|
||||
@ -421,7 +112,7 @@ index fe38079d69f3e9987ad5ab077ae09d05017a681a..7983f9a21251cec4857529ad1180a626
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -143,13 +154,37 @@ public final class NaturalSpawner {
|
||||
@@ -143,13 +154,35 @@ public final class NaturalSpawner {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -433,14 +124,12 @@ index fe38079d69f3e9987ad5ab077ae09d05017a681a..7983f9a21251cec4857529ad1180a626
|
||||
+
|
||||
+ if (world.paperConfig().entities.spawning.perPlayerMobSpawns) {
|
||||
+ int minDiff = Integer.MAX_VALUE;
|
||||
+ final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<net.minecraft.server.level.ServerPlayer> inRange = world.getChunkSource().chunkMap.playerMobDistanceMap.getObjectsInRange(chunk.getPos());
|
||||
+ final com.destroystokyo.paper.util.maplist.ReferenceList<net.minecraft.server.level.ServerPlayer> inRange =
|
||||
+ world.chunkSource.chunkMap.getNearbyPlayers().getPlayers(chunk.getPos(), io.papermc.paper.util.player.NearbyPlayers.NearbyMapType.TICK_VIEW_DISTANCE);
|
||||
+ if (inRange != null) {
|
||||
+ final Object[] backingSet = inRange.getBackingSet();
|
||||
+ for (int k = 0; k < backingSet.length; k++) {
|
||||
+ if (!(backingSet[k] instanceof final net.minecraft.server.level.ServerPlayer player)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ minDiff = Math.min(limit - world.getChunkSource().chunkMap.getMobCountNear(player, enumcreaturetype), minDiff);
|
||||
+ final Object[] backingSet = inRange.getRawData();
|
||||
+ for (int k = 0, len = inRange.size(); k < len; k++) {
|
||||
+ minDiff = Math.min(limit - world.getChunkSource().chunkMap.getMobCountNear((net.minecraft.server.level.ServerPlayer)backingSet[k], enumcreaturetype), minDiff);
|
||||
+ }
|
||||
+ }
|
||||
+ difference = (minDiff == Integer.MAX_VALUE) ? 0 : minDiff;
|
||||
@ -461,7 +150,7 @@ index fe38079d69f3e9987ad5ab077ae09d05017a681a..7983f9a21251cec4857529ad1180a626
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,11 +193,17 @@ public final class NaturalSpawner {
|
||||
@@ -158,11 +191,17 @@ public final class NaturalSpawner {
|
||||
}
|
||||
|
||||
public static void spawnCategoryForChunk(MobCategory group, ServerLevel world, LevelChunk chunk, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner) {
|
||||
@ -480,7 +169,7 @@ index fe38079d69f3e9987ad5ab077ae09d05017a681a..7983f9a21251cec4857529ad1180a626
|
||||
}
|
||||
|
||||
@VisibleForDebug
|
||||
@@ -173,15 +214,21 @@ public final class NaturalSpawner {
|
||||
@@ -173,15 +212,21 @@ public final class NaturalSpawner {
|
||||
});
|
||||
}
|
||||
|
||||
@ -503,7 +192,7 @@ index fe38079d69f3e9987ad5ab077ae09d05017a681a..7983f9a21251cec4857529ad1180a626
|
||||
int k = 0;
|
||||
|
||||
while (k < 3) {
|
||||
@@ -223,14 +270,14 @@ public final class NaturalSpawner {
|
||||
@@ -223,14 +268,14 @@ public final class NaturalSpawner {
|
||||
// Paper start
|
||||
PreSpawnStatus doSpawning = isValidSpawnPostitionForType(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2);
|
||||
if (doSpawning == PreSpawnStatus.ABORT) {
|
||||
@ -520,7 +209,7 @@ index fe38079d69f3e9987ad5ab077ae09d05017a681a..7983f9a21251cec4857529ad1180a626
|
||||
}
|
||||
|
||||
entityinsentient.moveTo(d0, (double) i, d1, world.random.nextFloat() * 360.0F, 0.0F);
|
||||
@@ -243,10 +290,15 @@ public final class NaturalSpawner {
|
||||
@@ -243,10 +288,15 @@ public final class NaturalSpawner {
|
||||
++j;
|
||||
++k1;
|
||||
runner.run(entityinsentient, chunk);
|
||||
@ -538,7 +227,7 @@ index fe38079d69f3e9987ad5ab077ae09d05017a681a..7983f9a21251cec4857529ad1180a626
|
||||
}
|
||||
|
||||
if (entityinsentient.isMaxGroupSizeReached(k1)) {
|
||||
@@ -268,6 +320,7 @@ public final class NaturalSpawner {
|
||||
@@ -268,6 +318,7 @@ public final class NaturalSpawner {
|
||||
}
|
||||
|
||||
}
|
||||
@ -546,7 +235,7 @@ index fe38079d69f3e9987ad5ab077ae09d05017a681a..7983f9a21251cec4857529ad1180a626
|
||||
}
|
||||
|
||||
private static boolean isRightDistanceToPlayerAndSpawnPoint(ServerLevel world, ChunkAccess chunk, BlockPos.MutableBlockPos pos, double squaredDistance) {
|
||||
@@ -567,7 +620,7 @@ public final class NaturalSpawner {
|
||||
@@ -567,7 +618,7 @@ public final class NaturalSpawner {
|
||||
MobCategory enumcreaturetype = entitytypes.getCategory();
|
||||
|
||||
this.mobCategoryCounts.addTo(enumcreaturetype, 1);
|
||||
@ -555,7 +244,7 @@ index fe38079d69f3e9987ad5ab077ae09d05017a681a..7983f9a21251cec4857529ad1180a626
|
||||
}
|
||||
|
||||
public int getSpawnableChunkCount() {
|
||||
@@ -583,6 +636,7 @@ public final class NaturalSpawner {
|
||||
@@ -583,6 +634,7 @@ public final class NaturalSpawner {
|
||||
int i = limit * this.spawnableChunkCount / NaturalSpawner.MAGIC_NUMBER;
|
||||
// CraftBukkit end
|
||||
|
||||
|
@ -1213,10 +1213,10 @@ index 525c89bc926f13af6f94fc46c897525e37477eca..8b96d1b7548d354fbcabe6d1b5e9d6c3
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index cf910b466a4b75c0b9219abef5c9bff30793d7bf..1bb82df6602bddd3f5785c800124d2a3096c0f8d 100644
|
||||
index 391ef1eb8c842a1a2dbce45eec8a030f615926d6..abb75d8bea8f975c5b04c9a9fff7187a3520ac26 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -90,7 +90,7 @@ public class LevelChunk extends ChunkAccess {
|
||||
@@ -91,7 +91,7 @@ public class LevelChunk extends ChunkAccess {
|
||||
}
|
||||
|
||||
public LevelChunk(Level world, ChunkPos pos, UpgradeData upgradeData, LevelChunkTicks<Block> blockTickScheduler, LevelChunkTicks<Fluid> fluidTickScheduler, long inhabitedTime, @Nullable LevelChunkSection[] sectionArrayInitializer, @Nullable LevelChunk.PostLoadProcessor entityLoader, @Nullable BlendingData blendingData) {
|
||||
|
@ -7,7 +7,7 @@ bypass the need to get a player chunk, then get the either,
|
||||
then unwrap it...
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
index e655cf837f7bd7d4271dca80b9c6764372336910..2d44b8a98216f879f2bc89fba1dad53cd5558ff9 100644
|
||||
index b73d45c205db39ed3e97a127e53371db81e0d63f..ab1a45f30930408a3e3c7172169ff648643ba54d 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -270,6 +270,12 @@ public class ServerChunkCache extends ChunkSource {
|
||||
|
@ -300,7 +300,7 @@ index 0000000000000000000000000000000000000000..95d6022c9cfb2e36ec5a71be6e343540
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
index 2d44b8a98216f879f2bc89fba1dad53cd5558ff9..7881a34e01dd6c8e31b55577bb9323a0171d24bf 100644
|
||||
index ab1a45f30930408a3e3c7172169ff648643ba54d..a8c1620ec48adcd2bb116d48f8bb2d4af50f5f43 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -294,6 +294,7 @@ public class ServerChunkCache extends ChunkSource {
|
||||
|
@ -8,10 +8,10 @@ faster on its own, however removing the try catch makes it
|
||||
easier to inline due to code size
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index 1bb82df6602bddd3f5785c800124d2a3096c0f8d..95531e115f69f52cb6ec55c6e4bc34fb109758c4 100644
|
||||
index abb75d8bea8f975c5b04c9a9fff7187a3520ac26..d2cdb8100fbbdc3d92eb7a61748340c40de343f7 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -380,18 +380,20 @@ public class LevelChunk extends ChunkAccess {
|
||||
@@ -381,18 +381,20 @@ public class LevelChunk extends ChunkAccess {
|
||||
}
|
||||
|
||||
public FluidState getFluidState(int x, int y, int z) {
|
||||
@ -38,7 +38,7 @@ index 1bb82df6602bddd3f5785c800124d2a3096c0f8d..95531e115f69f52cb6ec55c6e4bc34fb
|
||||
} catch (Throwable throwable) {
|
||||
CrashReport crashreport = CrashReport.forThrowable(throwable, "Getting fluid state");
|
||||
CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block being got");
|
||||
@@ -401,6 +403,7 @@ public class LevelChunk extends ChunkAccess {
|
||||
@@ -402,6 +404,7 @@ public class LevelChunk extends ChunkAccess {
|
||||
});
|
||||
throw new ReportedException(crashreport);
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ When not per player it will use the Vanilla mechanic of one delay per
|
||||
world and the world age for the start day.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index ad34d1562131a5140c4cc83aa3ea94fab08d12da..a6b9f246ed2d59122c31ff212d99adc0602ef35b 100644
|
||||
index 55c3416f209178a1a100228d9b1db620c79bc288..5c0b406214b7da3b33acf1f545105d4ecae1f783 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -242,6 +242,7 @@ public class ServerPlayer extends Player {
|
||||
|
@ -7,10 +7,10 @@ Suspected case would be around the technique used in .stopRiding
|
||||
Stack will identify any causer of this and warn instead of crashing.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 1f30d06781cea0855be26784c239e71ed1a2f6c3..91373583904a22bc28c82cf3dfec9f60aebee9a3 100644
|
||||
index 847019bf4a81b82e6e11a19aebd69b7270d81b06..41a6712d4c55907df1274f5a825e86d7fedb42bb 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -1000,6 +1000,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -994,6 +994,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
|
||||
public void addEntity(Entity entity) {
|
||||
org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot
|
||||
|
@ -7,10 +7,10 @@ Causes sync chunk loads and who knows what all else.
|
||||
This is safe because Spectators are skipped in unloaded chunks too in vanilla.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index a6b9f246ed2d59122c31ff212d99adc0602ef35b..88152bb21f42f705f6d321f0f088e7f83ac66e62 100644
|
||||
index 5c0b406214b7da3b33acf1f545105d4ecae1f783..40709c98687334b5383ad9d412d5b6ff7748b02b 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -727,7 +727,7 @@ public class ServerPlayer extends Player {
|
||||
@@ -725,7 +725,7 @@ public class ServerPlayer extends Player {
|
||||
|
||||
public void doTick() {
|
||||
try {
|
||||
|
@ -13,10 +13,10 @@ By skipping this, we avoid potential for a large spike on server start.
|
||||
public net.minecraft.server.level.ServerPlayer fudgeSpawnLocation(Lnet/minecraft/server/level/ServerLevel;)V
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 88152bb21f42f705f6d321f0f088e7f83ac66e62..99cabb83c54106ff39e89f9f138548aa734ccac3 100644
|
||||
index 40709c98687334b5383ad9d412d5b6ff7748b02b..de8121b1e4a30e091ce6eb7d3e5beb6029fd95d8 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -379,7 +379,7 @@ public class ServerPlayer extends Player {
|
||||
@@ -378,7 +378,7 @@ public class ServerPlayer extends Player {
|
||||
this.stats = server.getPlayerList().getPlayerStats(this);
|
||||
this.advancements = server.getPlayerList().getPlayerAdvancements(this);
|
||||
this.setMaxUpStep(1.0F);
|
||||
@ -25,7 +25,7 @@ index 88152bb21f42f705f6d321f0f088e7f83ac66e62..99cabb83c54106ff39e89f9f138548aa
|
||||
this.updateOptions(clientOptions);
|
||||
|
||||
this.cachedSingleHashSet = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper
|
||||
@@ -614,7 +614,7 @@ public class ServerPlayer extends Player {
|
||||
@@ -612,7 +612,7 @@ public class ServerPlayer extends Player {
|
||||
position = Vec3.atCenterOf(world.getSharedSpawnPos());
|
||||
}
|
||||
this.setLevel(world);
|
||||
|
@ -308,10 +308,10 @@ index 7a1886585bd00dc8213ce22130b8b6fea52c5cf6..52a44510d0499df56d2ebef0963fe816
|
||||
final String msg = String.format("Entity threw exception at %s:%s,%s,%s", entity.level().getWorld().getName(), entity.getX(), entity.getY(), entity.getZ());
|
||||
MinecraftServer.LOGGER.error(msg, throwable);
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index 95531e115f69f52cb6ec55c6e4bc34fb109758c4..cd725cdfe37eb53eea78f110d5d3ca00342781c5 100644
|
||||
index d2cdb8100fbbdc3d92eb7a61748340c40de343f7..535e71bdb2531432974dc91ec9d5edb2b3ebc744 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -1180,6 +1180,7 @@ public class LevelChunk extends ChunkAccess {
|
||||
@@ -1181,6 +1181,7 @@ public class LevelChunk extends ChunkAccess {
|
||||
|
||||
gameprofilerfiller.pop();
|
||||
} catch (Throwable throwable) {
|
||||
|
@ -5,10 +5,10 @@ Subject: [PATCH] Prevent opening inventories when frozen
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 99cabb83c54106ff39e89f9f138548aa734ccac3..1ff911085da7d1a2a378c60c66f8e5364b9774b4 100644
|
||||
index de8121b1e4a30e091ce6eb7d3e5beb6029fd95d8..0bab5208a38e8e7c848e9162396df535eb7e5711 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -696,7 +696,7 @@ public class ServerPlayer extends Player {
|
||||
@@ -694,7 +694,7 @@ public class ServerPlayer extends Player {
|
||||
containerUpdateDelay = this.level().paperConfig().tickRates.containerUpdate;
|
||||
}
|
||||
// Paper end
|
||||
@ -17,7 +17,7 @@ index 99cabb83c54106ff39e89f9f138548aa734ccac3..1ff911085da7d1a2a378c60c66f8e536
|
||||
this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper
|
||||
this.containerMenu = this.inventoryMenu;
|
||||
}
|
||||
@@ -1545,7 +1545,7 @@ public class ServerPlayer extends Player {
|
||||
@@ -1543,7 +1543,7 @@ public class ServerPlayer extends Player {
|
||||
} else {
|
||||
// CraftBukkit start
|
||||
this.containerMenu = container;
|
||||
|
@ -87,10 +87,10 @@ index 0000000000000000000000000000000000000000..b6f4400df3d8ec7e06a996de54f8cabb
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 1ff911085da7d1a2a378c60c66f8e5364b9774b4..c13f088a74448f80e111bdeeb712087a238ed2b8 100644
|
||||
index 0bab5208a38e8e7c848e9162396df535eb7e5711..baec871645598c36cefda7478e91b560bdfdf6fe 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -1952,7 +1952,23 @@ public class ServerPlayer extends Player {
|
||||
@@ -1950,7 +1950,23 @@ public class ServerPlayer extends Player {
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,10 +31,10 @@ delays anymore.
|
||||
public net.minecraft.server.level.ChunkMap addEntity(Lnet/minecraft/world/entity/Entity;)V
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 91373583904a22bc28c82cf3dfec9f60aebee9a3..463a82f08b7848a4b8a4eb89b201a6e8424c6831 100644
|
||||
index 41a6712d4c55907df1274f5a825e86d7fedb42bb..c10ef2e6af3e6c52eeb8c96cdbf5352d9dd25dd2 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -1006,6 +1006,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1000,6 +1000,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
+ ": " + entity + (this.entityMap.containsKey(entity.getId()) ? " ALREADY CONTAINED (This would have crashed your server)" : ""), new Throwable());
|
||||
return;
|
||||
}
|
||||
@ -43,10 +43,10 @@ index 91373583904a22bc28c82cf3dfec9f60aebee9a3..463a82f08b7848a4b8a4eb89b201a6e8
|
||||
if (!(entity instanceof EnderDragonPart)) {
|
||||
EntityType<?> entitytypes = entity.getType();
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index c13f088a74448f80e111bdeeb712087a238ed2b8..db722b6c6d6d7c5b973f56a2da624514a76b53cd 100644
|
||||
index baec871645598c36cefda7478e91b560bdfdf6fe..d31670aecc2ebe67bf6071c67126ce4142b93053 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -265,6 +265,7 @@ public class ServerPlayer extends Player {
|
||||
@@ -264,6 +264,7 @@ public class ServerPlayer extends Player {
|
||||
public double maxHealthCache;
|
||||
public boolean joining = true;
|
||||
public boolean sentListPacket = false;
|
||||
|
@ -612,10 +612,10 @@ index 5db27d7bcaaa2eeaeeb08401513d8d23f6cb63c7..ce43cb0152ba07c6c21e08142d65813d
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index cd725cdfe37eb53eea78f110d5d3ca00342781c5..c4d2036d51fe16b640605ae26a2b71323758cc26 100644
|
||||
index 535e71bdb2531432974dc91ec9d5edb2b3ebc744..4abec88caab4116cfa318f7b66c6b1a8346a7401 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -603,7 +603,7 @@ public class LevelChunk extends ChunkAccess {
|
||||
@@ -604,7 +604,7 @@ public class LevelChunk extends ChunkAccess {
|
||||
+ " (" + getBlockState(blockposition) + ") where there was no entity tile!\n" +
|
||||
"Chunk coordinates: " + (this.chunkPos.x * 16) + "," + (this.chunkPos.z * 16) +
|
||||
"\nWorld: " + level.getLevel().dimension().location());
|
||||
|
@ -76,10 +76,10 @@ index 1f8dcc331505890ba72777b5d0cda2427e0ccfd1..a661f8a83d4e57ca48bbf28dc668f8ff
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index db722b6c6d6d7c5b973f56a2da624514a76b53cd..7b5496d3a21316a7410dfbfbf9335a432b466560 100644
|
||||
index d31670aecc2ebe67bf6071c67126ce4142b93053..6de4e9f379fe0cb44f14fe68ae1dee55a73d2d99 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -1206,7 +1206,7 @@ public class ServerPlayer extends Player {
|
||||
@@ -1204,7 +1204,7 @@ public class ServerPlayer extends Player {
|
||||
this.isChangingDimension = true; // CraftBukkit - Set teleport invulnerability only if player changing worlds
|
||||
|
||||
this.connection.send(new ClientboundRespawnPacket(this.createCommonSpawnInfo(worldserver), (byte) 3));
|
||||
|
@ -53,7 +53,7 @@ index a106f5f573c9eec1f56fa88f7398ac28d231b5e5..04258e07f806acd9a0d659b682e0119a
|
||||
// Paper start - move executeAll() into full server tick timing
|
||||
try (co.aikar.timings.Timing ignored = MinecraftTimings.processTasksTimer.startTiming()) {
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
index 7881a34e01dd6c8e31b55577bb9323a0171d24bf..7b5851cd4f5a91bf7609464d7d6c4bb5a3da14bf 100644
|
||||
index a8c1620ec48adcd2bb116d48f8bb2d4af50f5f43..7d7dc8246f44d6ffd46b05f917ffbdb9cc24372b 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -452,6 +452,15 @@ public class ServerChunkCache extends ChunkSource {
|
||||
@ -115,7 +115,7 @@ index 8467ea174dd48010b94b3f3c84ce097ecbb2ef14..5826536978724b54080d7d4ee61aa798
|
||||
// Paper start - rewrite chunk system - add close param
|
||||
this.save(progressListener, flush, savingDisabled, false);
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 7b5496d3a21316a7410dfbfbf9335a432b466560..4d96b44533d39962b60ee43c232d5aa80b88e185 100644
|
||||
index 6de4e9f379fe0cb44f14fe68ae1dee55a73d2d99..4a4002b666c70c7065cad0743377cd13e443aa37 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -184,6 +184,7 @@ import org.bukkit.inventory.MainHand;
|
||||
|
@ -25,10 +25,10 @@ index b9d1eefb2afbf24bdc902c6dea06e911e835d698..4f5216cb3ac323de1a79c2b9c4d2ddd7
|
||||
Connection.LOGGER.debug("Failed to sent packet", throwable);
|
||||
if (this.getSending() == PacketFlow.CLIENTBOUND) {
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 4d96b44533d39962b60ee43c232d5aa80b88e185..c70a7feab56fd63354ac2dd887a5d6157eaf8407 100644
|
||||
index 4a4002b666c70c7065cad0743377cd13e443aa37..576fe4a114c7ad0edde3ce7b2cf1b397a287adcd 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -272,6 +272,7 @@ public class ServerPlayer extends Player {
|
||||
@@ -271,6 +271,7 @@ public class ServerPlayer extends Player {
|
||||
public boolean isRealPlayer; // Paper
|
||||
public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> cachedSingleHashSet; // Paper
|
||||
public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper
|
||||
|
@ -5,10 +5,10 @@ Subject: [PATCH] Reset shield blocking on dimension change
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index c70a7feab56fd63354ac2dd887a5d6157eaf8407..cb2f86e0ad0edc54711826215df4406c5725f29c 100644
|
||||
index 576fe4a114c7ad0edde3ce7b2cf1b397a287adcd..717e7d0cd5fd62058d5308fc15070bdf72a03bc4 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -1243,6 +1243,11 @@ public class ServerPlayer extends Player {
|
||||
@@ -1241,6 +1241,11 @@ public class ServerPlayer extends Player {
|
||||
this.level().getCraftServer().getPluginManager().callEvent(changeEvent);
|
||||
// CraftBukkit end
|
||||
}
|
||||
|
@ -45,10 +45,10 @@ index aee8618e27b893b72931e925724dd683d2e6d2aa..5cb15e2209d7b315904a1fc6d650ce1e
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index cb2f86e0ad0edc54711826215df4406c5725f29c..0abc9dfd73b3cb16b29bdbcc40f0d0ea1c022f34 100644
|
||||
index 717e7d0cd5fd62058d5308fc15070bdf72a03bc4..327307404d336d0e66a265e79448f2342cc36220 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -1888,8 +1888,16 @@ public class ServerPlayer extends Player {
|
||||
@@ -1886,8 +1886,16 @@ public class ServerPlayer extends Player {
|
||||
}
|
||||
|
||||
public boolean setGameMode(GameType gameMode) {
|
||||
@ -67,7 +67,7 @@ index cb2f86e0ad0edc54711826215df4406c5725f29c..0abc9dfd73b3cb16b29bdbcc40f0d0ea
|
||||
} else {
|
||||
this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.CHANGE_GAME_MODE, (float) gameMode.getId()));
|
||||
if (gameMode == GameType.SPECTATOR) {
|
||||
@@ -1901,7 +1909,7 @@ public class ServerPlayer extends Player {
|
||||
@@ -1899,7 +1907,7 @@ public class ServerPlayer extends Player {
|
||||
|
||||
this.onUpdateAbilities();
|
||||
this.updateEffectVisibility();
|
||||
@ -76,7 +76,7 @@ index cb2f86e0ad0edc54711826215df4406c5725f29c..0abc9dfd73b3cb16b29bdbcc40f0d0ea
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2305,6 +2313,16 @@ public class ServerPlayer extends Player {
|
||||
@@ -2303,6 +2311,16 @@ public class ServerPlayer extends Player {
|
||||
}
|
||||
|
||||
public void loadGameTypes(@Nullable CompoundTag nbt) {
|
||||
|
@ -5,10 +5,10 @@ Subject: [PATCH] Fix PlayerDropItemEvent using wrong item
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 0abc9dfd73b3cb16b29bdbcc40f0d0ea1c022f34..2265259b24ae27a85beea1d47ec2c1bae6baa2a7 100644
|
||||
index 327307404d336d0e66a265e79448f2342cc36220..1d8328bc7acde64f3a0cff4d20bdca44baddd409 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -2282,7 +2282,7 @@ public class ServerPlayer extends Player {
|
||||
@@ -2280,7 +2280,7 @@ public class ServerPlayer extends Player {
|
||||
|
||||
if (retainOwnership) {
|
||||
if (!itemstack1.isEmpty()) {
|
||||
|
@ -5,10 +5,10 @@ Subject: [PATCH] Fixes kick event leave message not being sent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 2265259b24ae27a85beea1d47ec2c1bae6baa2a7..552d64e47f17d916a4e374b877d12ff7a583a9e7 100644
|
||||
index 1d8328bc7acde64f3a0cff4d20bdca44baddd409..a75377cf94c70011a967e7ede93f903aae4f9f05 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -267,7 +267,6 @@ public class ServerPlayer extends Player {
|
||||
@@ -266,7 +266,6 @@ public class ServerPlayer extends Player {
|
||||
public boolean joining = true;
|
||||
public boolean sentListPacket = false;
|
||||
public boolean supressTrackerForLogin = false; // Paper
|
||||
|
@ -11,7 +11,7 @@ It does not make a lot of sense to damage players if they get crammed,
|
||||
For those who really want it a config option is provided.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 552d64e47f17d916a4e374b877d12ff7a583a9e7..a59ac2011b85ff9b1185a14eca4d2796b2666df1 100644
|
||||
index a75377cf94c70011a967e7ede93f903aae4f9f05..b8f60c2deb7e46f654d0169751c793b3b3408748 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -95,6 +95,7 @@ import net.minecraft.util.Mth;
|
||||
@ -22,7 +22,7 @@ index 552d64e47f17d916a4e374b877d12ff7a583a9e7..a59ac2011b85ff9b1185a14eca4d2796
|
||||
import net.minecraft.world.effect.MobEffectInstance;
|
||||
import net.minecraft.world.effect.MobEffects;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
@@ -1475,7 +1476,7 @@ public class ServerPlayer extends Player {
|
||||
@@ -1473,7 +1474,7 @@ public class ServerPlayer extends Player {
|
||||
|
||||
@Override
|
||||
public boolean isInvulnerableTo(DamageSource damageSource) {
|
||||
|
@ -49,10 +49,10 @@ index a2d0699e8427b2262a2396495111125eccafbb66..d797637f61bdf8a424f56fbb48e28b7c
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index a59ac2011b85ff9b1185a14eca4d2796b2666df1..c2b535c5b1d05d70a16e15283ff5c9e45c59d8e3 100644
|
||||
index b8f60c2deb7e46f654d0169751c793b3b3408748..39515b81fd753c8c6d50d1efa4c5792f9f0abda9 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -1352,7 +1352,7 @@ public class ServerPlayer extends Player {
|
||||
@@ -1350,7 +1350,7 @@ public class ServerPlayer extends Player {
|
||||
} else if (this.bedBlocked(blockposition, enumdirection)) {
|
||||
return Either.left(Player.BedSleepingProblem.OBSTRUCTED);
|
||||
} else {
|
||||
@ -61,7 +61,7 @@ index a59ac2011b85ff9b1185a14eca4d2796b2666df1..c2b535c5b1d05d70a16e15283ff5c9e4
|
||||
if (this.level().isDay()) {
|
||||
return Either.left(Player.BedSleepingProblem.NOT_POSSIBLE_NOW);
|
||||
} else {
|
||||
@@ -2202,44 +2202,50 @@ public class ServerPlayer extends Player {
|
||||
@@ -2200,44 +2200,50 @@ public class ServerPlayer extends Player {
|
||||
return this.respawnForced;
|
||||
}
|
||||
|
||||
@ -145,7 +145,7 @@ index a59ac2011b85ff9b1185a14eca4d2796b2666df1..c2b535c5b1d05d70a16e15283ff5c9e4
|
||||
} else {
|
||||
this.respawnPosition = null;
|
||||
this.respawnDimension = Level.OVERWORLD;
|
||||
@@ -2247,6 +2253,7 @@ public class ServerPlayer extends Player {
|
||||
@@ -2245,6 +2251,7 @@ public class ServerPlayer extends Player {
|
||||
this.respawnForced = false;
|
||||
}
|
||||
|
||||
|
@ -28,10 +28,10 @@ index a11bd2d9f5b2fb248cc322ea61886050fa2e73a9..80f2a1204bee79daf0cae9310ce8d552
|
||||
}
|
||||
// Spigot End
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index c2b535c5b1d05d70a16e15283ff5c9e45c59d8e3..de9248f622834dc6df4af7016f0ddab864ed0264 100644
|
||||
index 39515b81fd753c8c6d50d1efa4c5792f9f0abda9..5f0ff1b2466469eff0bf78042b9cdd2fcf747dc7 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -1618,6 +1618,18 @@ public class ServerPlayer extends Player {
|
||||
@@ -1616,6 +1616,18 @@ public class ServerPlayer extends Player {
|
||||
this.connection.send(new ClientboundContainerClosePacket(this.containerMenu.containerId));
|
||||
this.doCloseContainer();
|
||||
}
|
||||
|
@ -257,10 +257,10 @@ index 0000000000000000000000000000000000000000..d3b39d88a72ca25057fd8574d32f28db
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
||||
index 7983f9a21251cec4857529ad1180a62668ea5037..e1c4cf4b60b810837526c888ec82acbfc8fe540c 100644
|
||||
index 9df761f5cf043e8d2dffa711c20ab32fe2992331..d08c7b0b52065980f1f13c5533ff6355028322db 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
||||
@@ -192,6 +192,16 @@ public final class NaturalSpawner {
|
||||
@@ -190,6 +190,16 @@ public final class NaturalSpawner {
|
||||
world.getProfiler().pop();
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,7 @@ index 7e4f3b7a5790292b3b8439fb4696d9d6cfec0167..6c02d5233c782b0e5049afdf84250687
|
||||
+ // Paper end - execute chunk tasks mid tick
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
index 7b5851cd4f5a91bf7609464d7d6c4bb5a3da14bf..50da1f746edeff63f723776b8e30b041c8de0138 100644
|
||||
index 7d7dc8246f44d6ffd46b05f917ffbdb9cc24372b..dbedc73039f53ddf042999524eec62f032a20d5d 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -571,6 +571,7 @@ public class ServerChunkCache extends ChunkSource {
|
||||
|
@ -7,10 +7,10 @@ Reference2BooleanOpenHashMap is going to have
|
||||
better lookups than HashMap.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 463a82f08b7848a4b8a4eb89b201a6e8424c6831..93a2dfca4484d1bdfa00dfb2cf8d94314123aeb8 100644
|
||||
index c10ef2e6af3e6c52eeb8c96cdbf5352d9dd25dd2..c16e84ee54bf2a65d8bd41f8156b7a4edee5e941 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -1210,7 +1210,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1204,7 +1204,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
final Entity entity;
|
||||
private final int range;
|
||||
SectionPos lastSectionPos;
|
||||
|
@ -5,10 +5,10 @@ Subject: [PATCH] Ensure valid vehicle status
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index de9248f622834dc6df4af7016f0ddab864ed0264..e498d339830d8fa6dcf0eeee4a27b6295c84ee2e 100644
|
||||
index 5f0ff1b2466469eff0bf78042b9cdd2fcf747dc7..981a2b55a58f85f551991945adc7a202b4a4ec72 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -570,7 +570,7 @@ public class ServerPlayer extends Player {
|
||||
@@ -568,7 +568,7 @@ public class ServerPlayer extends Player {
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2204,10 +2204,10 @@ index d0a8092bf57a29ab7c00ec0ddf52a9fdb2a33267..392406722b0a040c1d41fdc1154d75d3
|
||||
private Direction(int id, int idOpposite, int idHorizontal, String name, Direction.AxisDirection direction, Direction.Axis axis, Vec3i vector) {
|
||||
this.data3d = id;
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index e498d339830d8fa6dcf0eeee4a27b6295c84ee2e..6a33fbfb4f7dbe4a54044ccc408e196e537d96fa 100644
|
||||
index 981a2b55a58f85f551991945adc7a202b4a4ec72..24deceb51bc2892231dcd1745082d7f766eed4b5 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -463,7 +463,7 @@ public class ServerPlayer extends Player {
|
||||
@@ -461,7 +461,7 @@ public class ServerPlayer extends Player {
|
||||
|
||||
if (blockposition1 != null) {
|
||||
this.moveTo(blockposition1, 0.0F, 0.0F);
|
||||
@ -2216,7 +2216,7 @@ index e498d339830d8fa6dcf0eeee4a27b6295c84ee2e..6a33fbfb4f7dbe4a54044ccc408e196e
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -471,7 +471,7 @@ public class ServerPlayer extends Player {
|
||||
@@ -469,7 +469,7 @@ public class ServerPlayer extends Player {
|
||||
} else {
|
||||
this.moveTo(blockposition, 0.0F, 0.0F);
|
||||
|
||||
|
@ -5,10 +5,10 @@ Subject: [PATCH] fix player loottables running when mob loot gamerule is false
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 6a33fbfb4f7dbe4a54044ccc408e196e537d96fa..6a9e1b3fd1d7d1964835c78808f5c71ba8a82af7 100644
|
||||
index 24deceb51bc2892231dcd1745082d7f766eed4b5..d865907d4c5d1428d85e4bb63eb45529802d0c0d 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -918,12 +918,14 @@ public class ServerPlayer extends Player {
|
||||
@@ -916,12 +916,14 @@ public class ServerPlayer extends Player {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,10 +24,10 @@ index d4a673a9fb604876c554f955ed13ad31a2adb217..e75b3df4db9cb618aef4837acb8cde92
|
||||
} else {
|
||||
BlockPos blockPos = BlockPos.containing(x, y, z);
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 6a9e1b3fd1d7d1964835c78808f5c71ba8a82af7..b3fa0a7e75a7f367ab491ffad22facb985d8085a 100644
|
||||
index d865907d4c5d1428d85e4bb63eb45529802d0c0d..fc70531c97ce292a9964512008278bcf9377feb6 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -1317,6 +1317,12 @@ public class ServerPlayer extends Player {
|
||||
@@ -1315,6 +1315,12 @@ public class ServerPlayer extends Player {
|
||||
ResourceKey<Level> maindimensionkey = CraftDimensionUtil.getMainDimensionKey(origin);
|
||||
ResourceKey<Level> maindimensionkey1 = CraftDimensionUtil.getMainDimensionKey(this.level());
|
||||
|
||||
|
@ -111,10 +111,10 @@ index 6cd6d69a20e95e344fc18ab67dc300824537a59b..2e2a7c2cf3081187da817479a9da3eb1
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 93a2dfca4484d1bdfa00dfb2cf8d94314123aeb8..8cda789284a30dab012bfda8f97409bdde861c7e 100644
|
||||
index c16e84ee54bf2a65d8bd41f8156b7a4edee5e941..d7dcffde09e099ee2554ec201f553ee079f12274 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -825,7 +825,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -819,7 +819,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
// Paper end
|
||||
|
||||
|
@ -5,10 +5,10 @@ Subject: [PATCH] Add PlayerInventorySlotChangeEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index b3fa0a7e75a7f367ab491ffad22facb985d8085a..3e37684e3fbbb01ad006f2ae7f1e38ed63acc2b8 100644
|
||||
index fc70531c97ce292a9964512008278bcf9377feb6..d882295abf739967fa5f8621945a5dcd0b730ee4 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -372,6 +372,25 @@ public class ServerPlayer extends Player {
|
||||
@@ -371,6 +371,25 @@ public class ServerPlayer extends Player {
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -8,10 +8,10 @@ offhand slot isn't sent. This is not correct because you *can* put stuff into th
|
||||
by pressing the offhand swap item
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 3e37684e3fbbb01ad006f2ae7f1e38ed63acc2b8..215786e3991942ad5773306a68519946372e94d4 100644
|
||||
index d882295abf739967fa5f8621945a5dcd0b730ee4..1021872e3ee489bc38e64bdea8bbe53284c87183 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -341,6 +341,13 @@ public class ServerPlayer extends Player {
|
||||
@@ -340,6 +340,13 @@ public class ServerPlayer extends Player {
|
||||
|
||||
}
|
||||
|
||||
|
@ -5,10 +5,10 @@ Subject: [PATCH] Player Entity Tracking Events
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 8cda789284a30dab012bfda8f97409bdde861c7e..3d5f992c2f4a8df1cf0db1c209e2cce19e214b8a 100644
|
||||
index d7dcffde09e099ee2554ec201f553ee079f12274..160e8175fcae33c6643c2f731cc20b397ee86be9 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -1282,9 +1282,18 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1276,9 +1276,18 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
// CraftBukkit end
|
||||
if (flag) {
|
||||
if (this.seenBy.add(player.connection)) {
|
||||
|
@ -6,10 +6,10 @@ Subject: [PATCH] Improve cancelling PreCreatureSpawnEvent with per player mob
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 3d5f992c2f4a8df1cf0db1c209e2cce19e214b8a..91549ce95c4829f2262ccddf51372b1c858da15c 100644
|
||||
index 160e8175fcae33c6643c2f731cc20b397ee86be9..1e5ea1db14d7ae4ce25ba91e0bcd5245204af78b 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -313,8 +313,27 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -307,8 +307,26 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,15 +19,14 @@ index 3d5f992c2f4a8df1cf0db1c209e2cce19e214b8a..91549ce95c4829f2262ccddf51372b1c
|
||||
+ return;
|
||||
+ }
|
||||
+ int idx = mobCategory.ordinal();
|
||||
+ final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> inRange = this.playerMobDistanceMap.getObjectsInRange(chunkX, chunkZ);
|
||||
+ if (inRange != null) {
|
||||
+ final Object[] set = inRange.getBackingSet();
|
||||
+ for (int i = 0; i < set.length; i++) {
|
||||
+ if (!(set[i] instanceof ServerPlayer serverPlayer)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ ++serverPlayer.mobBackoffCounts[idx];
|
||||
+ }
|
||||
+ final com.destroystokyo.paper.util.maplist.ReferenceList<ServerPlayer> inRange =
|
||||
+ this.getNearbyPlayers().getPlayersByChunk(chunkX, chunkZ, io.papermc.paper.util.player.NearbyPlayers.NearbyMapType.TICK_VIEW_DISTANCE);
|
||||
+ if (inRange == null) {
|
||||
+ return;
|
||||
+ }
|
||||
+ final Object[] backingSet = inRange.getRawData();
|
||||
+ for (int i = 0, len = inRange.size(); i < len; i++) {
|
||||
+ ++((ServerPlayer)backingSet[i]).mobBackoffCounts[idx];
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - per player mob count backoff
|
||||
@ -39,11 +38,11 @@ index 3d5f992c2f4a8df1cf0db1c209e2cce19e214b8a..91549ce95c4829f2262ccddf51372b1c
|
||||
// Paper end
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
index 50da1f746edeff63f723776b8e30b041c8de0138..2ab16e10323982e193e647246bd116e31f17bad2 100644
|
||||
index dbedc73039f53ddf042999524eec62f032a20d5d..aaaf3a60696389b4e27a45de69743311c58e5829 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -532,7 +532,17 @@ public class ServerChunkCache extends ChunkSource {
|
||||
if ((this.spawnFriendlies || this.spawnEnemies) && this.chunkMap.playerMobDistanceMap != null) { // don't count mobs when animals and monsters are disabled
|
||||
if ((this.spawnFriendlies || this.spawnEnemies) && this.level.paperConfig().entities.spawning.perPlayerMobSpawns) { // don't count mobs when animals and monsters are disabled
|
||||
// re-set mob counts
|
||||
for (ServerPlayer player : this.level.players) {
|
||||
- Arrays.fill(player.mobCounts, 0);
|
||||
@ -62,22 +61,22 @@ index 50da1f746edeff63f723776b8e30b041c8de0138..2ab16e10323982e193e647246bd116e3
|
||||
spawnercreature_d = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk, null, true);
|
||||
} else {
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 215786e3991942ad5773306a68519946372e94d4..50dcbace6fea4669af904000df08ee6d13df77f8 100644
|
||||
index 1021872e3ee489bc38e64bdea8bbe53284c87183..d2729c381632bc32ca915bf60614847db07e488b 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -252,6 +252,7 @@ public class ServerPlayer extends Player {
|
||||
// Paper start - mob spawning rework
|
||||
@@ -253,6 +253,7 @@ public class ServerPlayer extends Player {
|
||||
public static final int MOBCATEGORY_TOTAL_ENUMS = net.minecraft.world.entity.MobCategory.values().length;
|
||||
public final int[] mobCounts = new int[MOBCATEGORY_TOTAL_ENUMS]; // Paper
|
||||
// Paper end - mob spawning rework
|
||||
+ public final int[] mobBackoffCounts = new int[MOBCATEGORY_TOTAL_ENUMS]; // Paper - per player mob count backoff
|
||||
public final com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> cachedSingleMobDistanceMap;
|
||||
// Paper end
|
||||
|
||||
// CraftBukkit start
|
||||
public String displayName;
|
||||
diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
||||
index e1c4cf4b60b810837526c888ec82acbfc8fe540c..64656c384863a6430e933e506d965ee628f08669 100644
|
||||
index d08c7b0b52065980f1f13c5533ff6355028322db..3cdddda9c0618e95288b81b975d499c8dd30c05f 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
||||
@@ -279,6 +279,11 @@ public final class NaturalSpawner {
|
||||
@@ -277,6 +277,11 @@ public final class NaturalSpawner {
|
||||
|
||||
// Paper start
|
||||
PreSpawnStatus doSpawning = isValidSpawnPostitionForType(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2);
|
||||
|
@ -6,10 +6,10 @@ Subject: [PATCH] Configurable entity tracking range by Y coordinate
|
||||
Options to configure entity tracking by Y coordinate, also for each entity category.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 91549ce95c4829f2262ccddf51372b1c858da15c..dcf12bea1759d851d663896938ea101303ab63a5 100644
|
||||
index 1e5ea1db14d7ae4ce25ba91e0bcd5245204af78b..edbd5d4e2dcf5112148dc3d7a9173bb4d0a5d445 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -1293,6 +1293,15 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1286,6 +1286,15 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
double d1 = vec3d.x * vec3d.x + vec3d.z * vec3d.z;
|
||||
double d2 = d0 * d0;
|
||||
boolean flag = d1 <= d2 && this.entity.broadcastToPlayer(player) && ChunkMap.this.isChunkTracked(player, this.entity.chunkPosition().x, this.entity.chunkPosition().z);
|
||||
|
@ -5,10 +5,10 @@ Subject: [PATCH] Add titleOverride to InventoryOpenEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 50dcbace6fea4669af904000df08ee6d13df77f8..6a11b262a6f1cd5eba96471666098c82978027ff 100644
|
||||
index d2729c381632bc32ca915bf60614847db07e488b..261d0cc1812831fa99358ec1c6438a4e89629bde 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -1561,12 +1561,17 @@ public class ServerPlayer extends Player {
|
||||
@@ -1559,12 +1559,17 @@ public class ServerPlayer extends Player {
|
||||
this.nextContainerCounter();
|
||||
AbstractContainerMenu container = factory.createMenu(this.containerCounter, this.getInventory(), this);
|
||||
|
||||
@ -27,7 +27,7 @@ index 50dcbace6fea4669af904000df08ee6d13df77f8..6a11b262a6f1cd5eba96471666098c82
|
||||
if (container == null && !cancelled) { // Let pre-cancelled events fall through
|
||||
// SPIGOT-5263 - close chest if cancelled
|
||||
if (factory instanceof Container) {
|
||||
@@ -1588,7 +1593,7 @@ public class ServerPlayer extends Player {
|
||||
@@ -1586,7 +1591,7 @@ public class ServerPlayer extends Player {
|
||||
} else {
|
||||
// CraftBukkit start
|
||||
this.containerMenu = container;
|
||||
|
374
patches/server/1029-Optimise-chunk-tick-iteration.patch
Normal file
374
patches/server/1029-Optimise-chunk-tick-iteration.patch
Normal file
@ -0,0 +1,374 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Sat, 23 Sep 2023 21:36:36 -0700
|
||||
Subject: [PATCH] Optimise chunk tick iteration
|
||||
|
||||
When per-player mob spawning is enabled we do not need to randomly
|
||||
shuffle the chunk list. Additionally, we can use the NearbyPlayers
|
||||
class to quickly retrieve nearby players instead of possible
|
||||
searching all players on the server.
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/util/player/NearbyPlayers.java b/src/main/java/io/papermc/paper/util/player/NearbyPlayers.java
|
||||
index 60c7680d678f9dc6a6a3109b1f6af8150ccd9100..d05195358a00e498e0184ab105ebb3dc7a39e15a 100644
|
||||
--- a/src/main/java/io/papermc/paper/util/player/NearbyPlayers.java
|
||||
+++ b/src/main/java/io/papermc/paper/util/player/NearbyPlayers.java
|
||||
@@ -17,7 +17,8 @@ public final class NearbyPlayers {
|
||||
GENERAL_SMALL,
|
||||
GENERAL_REALLY_SMALL,
|
||||
TICK_VIEW_DISTANCE,
|
||||
- VIEW_DISTANCE;
|
||||
+ VIEW_DISTANCE, // Paper - optimise chunk iteration
|
||||
+ SPAWN_RANGE, // Paper - optimise chunk iteration
|
||||
}
|
||||
|
||||
private static final NearbyMapType[] MOB_TYPES = NearbyMapType.values();
|
||||
@@ -26,10 +27,12 @@ public final class NearbyPlayers {
|
||||
private static final int GENERAL_AREA_VIEW_DISTANCE = 33;
|
||||
private static final int GENERAL_SMALL_VIEW_DISTANCE = 10;
|
||||
private static final int GENERAL_REALLY_SMALL_VIEW_DISTANCE = 3;
|
||||
+ private static final int SPAWN_RANGE_VIEW_DISTANCE = net.minecraft.server.level.DistanceManager.MOB_SPAWN_RANGE; // Paper - optimise chunk iteration
|
||||
|
||||
public static final int GENERAL_AREA_VIEW_DISTANCE_BLOCKS = (GENERAL_AREA_VIEW_DISTANCE << 4);
|
||||
public static final int GENERAL_SMALL_AREA_VIEW_DISTANCE_BLOCKS = (GENERAL_SMALL_VIEW_DISTANCE << 4);
|
||||
public static final int GENERAL_REALLY_SMALL_AREA_VIEW_DISTANCE_BLOCKS = (GENERAL_REALLY_SMALL_VIEW_DISTANCE << 4);
|
||||
+ public static final int SPAWN_RANGE_VIEW_DISTANCE_BLOCKS = (SPAWN_RANGE_VIEW_DISTANCE << 4); // Paper - optimise chunk iteration
|
||||
|
||||
private final ServerLevel world;
|
||||
private final Reference2ReferenceOpenHashMap<ServerPlayer, TrackedPlayer[]> players = new Reference2ReferenceOpenHashMap<>();
|
||||
@@ -80,6 +83,7 @@ public final class NearbyPlayers {
|
||||
players[NearbyMapType.GENERAL_REALLY_SMALL.ordinal()].update(chunk.x, chunk.z, GENERAL_REALLY_SMALL_VIEW_DISTANCE);
|
||||
players[NearbyMapType.TICK_VIEW_DISTANCE.ordinal()].update(chunk.x, chunk.z, ChunkSystem.getTickViewDistance(player));
|
||||
players[NearbyMapType.VIEW_DISTANCE.ordinal()].update(chunk.x, chunk.z, ChunkSystem.getLoadViewDistance(player));
|
||||
+ players[NearbyMapType.SPAWN_RANGE.ordinal()].update(chunk.x, chunk.z, SPAWN_RANGE_VIEW_DISTANCE);
|
||||
}
|
||||
|
||||
public TrackedChunk getChunk(final ChunkPos pos) {
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
index 2b998bdbe49bf8211b755e0eb7c1bf13ac280eab..5afeb59ff25fed2d565407acacffec8383398006 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
@@ -79,11 +79,19 @@ public class ChunkHolder {
|
||||
|
||||
// Paper start
|
||||
public void onChunkAdd() {
|
||||
-
|
||||
+ // Paper start - optimise chunk tick iteration
|
||||
+ if (this.needsBroadcastChanges()) {
|
||||
+ this.chunkMap.needsChangeBroadcasting.add(this);
|
||||
+ }
|
||||
+ // Paper end - optimise chunk tick iteration
|
||||
}
|
||||
|
||||
public void onChunkRemove() {
|
||||
-
|
||||
+ // Paper start - optimise chunk tick iteration
|
||||
+ if (this.needsBroadcastChanges()) {
|
||||
+ this.chunkMap.needsChangeBroadcasting.remove(this);
|
||||
+ }
|
||||
+ // Paper end - optimise chunk tick iteration
|
||||
}
|
||||
// Paper end
|
||||
|
||||
@@ -230,7 +238,7 @@ public class ChunkHolder {
|
||||
|
||||
if (i < 0 || i >= this.changedBlocksPerSection.length) return; // CraftBukkit - SPIGOT-6086, SPIGOT-6296
|
||||
if (this.changedBlocksPerSection[i] == null) {
|
||||
- this.hasChangedSections = true;
|
||||
+ this.hasChangedSections = true; this.addToBroadcastMap(); // Paper - optimise chunk tick iteration
|
||||
this.changedBlocksPerSection[i] = new ShortOpenHashSet();
|
||||
}
|
||||
|
||||
@@ -254,6 +262,7 @@ public class ChunkHolder {
|
||||
int k = this.lightEngine.getMaxLightSection();
|
||||
|
||||
if (y >= j && y <= k) {
|
||||
+ this.addToBroadcastMap(); // Paper - optimise chunk tick iteration
|
||||
int l = y - j;
|
||||
|
||||
if (lightType == LightLayer.SKY) {
|
||||
@@ -268,8 +277,19 @@ public class ChunkHolder {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start - optimise chunk tick iteration
|
||||
+ public final boolean needsBroadcastChanges() {
|
||||
+ return this.hasChangedSections || !this.skyChangedLightSectionFilter.isEmpty() || !this.blockChangedLightSectionFilter.isEmpty();
|
||||
+ }
|
||||
+
|
||||
+ private void addToBroadcastMap() {
|
||||
+ io.papermc.paper.util.TickThread.ensureTickThread(this.chunkMap.level, this.pos, "Asynchronous ChunkHolder update is not allowed");
|
||||
+ this.chunkMap.needsChangeBroadcasting.add(this);
|
||||
+ }
|
||||
+ // Paper end - optimise chunk tick iteration
|
||||
+
|
||||
public void broadcastChanges(LevelChunk chunk) {
|
||||
- if (this.hasChangedSections || !this.skyChangedLightSectionFilter.isEmpty() || !this.blockChangedLightSectionFilter.isEmpty()) {
|
||||
+ if (this.needsBroadcastChanges()) { // Paper - moved into above, other logic needs to call
|
||||
Level world = chunk.getLevel();
|
||||
List list;
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index edbd5d4e2dcf5112148dc3d7a9173bb4d0a5d445..0c2617574e21037d94ac56ad08b490f9bca5c5af 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -162,6 +162,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
// Note: players need to be explicitly added to distance maps before they can be updated
|
||||
this.nearbyPlayers.removePlayer(player);
|
||||
this.level.playerChunkLoader.removePlayer(player); // Paper - replace chunk loader
|
||||
+ this.playerMobSpawnMap.remove(player); // Paper - optimise chunk tick iteration
|
||||
}
|
||||
|
||||
void updateMaps(ServerPlayer player) {
|
||||
@@ -203,6 +204,10 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
public final io.papermc.paper.util.player.NearbyPlayers nearbyPlayers;
|
||||
// Paper end
|
||||
+ // Paper start - optimise chunk tick iteration
|
||||
+ public final it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<ChunkHolder> needsChangeBroadcasting = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>();
|
||||
+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerMobSpawnMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets);
|
||||
+ // Paper end - optimise chunk tick iteration
|
||||
|
||||
public ChunkMap(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureTemplateManager structureTemplateManager, Executor executor, BlockableEventLoop<Runnable> mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier<DimensionDataStorage> persistentStateManagerFactory, int viewDistance, boolean dsync) {
|
||||
super(session.getDimensionPath(world.dimension()).resolve("region"), dataFixer, dsync);
|
||||
@@ -330,7 +335,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
// Paper end
|
||||
|
||||
- private static double euclideanDistanceSquared(ChunkPos pos, Entity entity) {
|
||||
+ public static double euclideanDistanceSquared(ChunkPos pos, Entity entity) { // Paper - optimise chunk iteration - public
|
||||
double d0 = (double) SectionPos.sectionToBlockCoord(pos.x, 8);
|
||||
double d1 = (double) SectionPos.sectionToBlockCoord(pos.z, 8);
|
||||
double d2 = d0 - entity.getX();
|
||||
diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java
|
||||
index 68550d4497a5f10bf653482f79be77373df53f27..55f96545d6db95e3e657502a7910d96fded1113e 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 - optimise chunk tick iteration
|
||||
// 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 - optimise chunk tick iteration
|
||||
//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 - optimise chunk tick iteration
|
||||
//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,11 @@ public abstract class DistanceManager {
|
||||
}
|
||||
|
||||
public int getNaturalSpawnChunkCount() {
|
||||
- this.naturalSpawnChunkCounter.runAllUpdates();
|
||||
- return this.naturalSpawnChunkCounter.chunks.size();
|
||||
+ return this.chunkMap.playerMobSpawnMap.size(); // Paper - optimise chunk tick iteration
|
||||
}
|
||||
|
||||
public boolean hasPlayersNearby(long chunkPos) {
|
||||
- this.naturalSpawnChunkCounter.runAllUpdates();
|
||||
- return this.naturalSpawnChunkCounter.chunks.containsKey(chunkPos);
|
||||
+ return this.chunkMap.playerMobSpawnMap.getObjectsInRange(chunkPos) != null; // Paper - optimise chunk tick iteration
|
||||
}
|
||||
|
||||
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 aaaf3a60696389b4e27a45de69743311c58e5829..17b6925b46f8386dcfc561483693de516465ec12 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -553,52 +553,114 @@ public class ServerChunkCache extends ChunkSource {
|
||||
|
||||
this.lastSpawnState = spawnercreature_d;
|
||||
gameprofilerfiller.popPush("filteringLoadedChunks");
|
||||
- List<ServerChunkCache.ChunkAndHolder> list = Lists.newArrayListWithCapacity(l);
|
||||
- Iterator iterator = this.chunkMap.getChunks().iterator();
|
||||
+ // Paper - optimise chunk tick iteration
|
||||
+ // Paper - optimise chunk tick iteration
|
||||
this.level.timings.chunkTicks.startTiming(); // Paper
|
||||
|
||||
- while (iterator.hasNext()) {
|
||||
- ChunkHolder playerchunk = (ChunkHolder) iterator.next();
|
||||
- LevelChunk chunk = playerchunk.getTickingChunk();
|
||||
-
|
||||
- if (chunk != null) {
|
||||
- list.add(new ServerChunkCache.ChunkAndHolder(chunk, playerchunk));
|
||||
- }
|
||||
- }
|
||||
+ // Paper - optimise chunk tick iteration
|
||||
|
||||
gameprofilerfiller.popPush("spawnAndTick");
|
||||
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
|
||||
- Iterator iterator1 = list.iterator();
|
||||
+ // Paper start - optimise chunk tick iteration
|
||||
+ ChunkMap playerChunkMap = this.chunkMap;
|
||||
+ for (ServerPlayer player : this.level.players) {
|
||||
+ if (!player.affectsSpawning || player.isSpectator()) {
|
||||
+ playerChunkMap.playerMobSpawnMap.remove(player);
|
||||
+ player.playerNaturallySpawnedEvent = null;
|
||||
+ player.lastEntitySpawnRadiusSquared = -1.0;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ int viewDistance = io.papermc.paper.chunk.system.ChunkSystem.getTickViewDistance(player);
|
||||
+
|
||||
+ // copied and modified from isOutisdeRange
|
||||
+ int chunkRange = (int)level.spigotConfig.mobSpawnRange;
|
||||
+ chunkRange = (chunkRange > viewDistance) ? 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.playerMobSpawnMap.remove(player);
|
||||
+ player.playerNaturallySpawnedEvent = null;
|
||||
+ player.lastEntitySpawnRadiusSquared = -1.0;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ int range = Math.min(event.getSpawnRadius(), DistanceManager.MOB_SPAWN_RANGE); // limit to max spawn range
|
||||
+ int chunkX = io.papermc.paper.util.CoordinateUtils.getChunkCoordinate(player.getX());
|
||||
+ int chunkZ = io.papermc.paper.util.CoordinateUtils.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 - optimise chunk tick iteration
|
||||
|
||||
int chunksTicked = 0; // Paper
|
||||
+ // Paper start - optimise chunk tick iteration
|
||||
+ io.papermc.paper.util.player.NearbyPlayers nearbyPlayers = this.chunkMap.getNearbyPlayers(); // Paper - optimise chunk tick iteration
|
||||
+ Iterator<LevelChunk> iterator1;
|
||||
+ if (this.level.paperConfig().entities.spawning.perPlayerMobSpawns) {
|
||||
+ iterator1 = this.tickingChunks.iterator();
|
||||
+ } else {
|
||||
+ iterator1 = this.tickingChunks.unsafeIterator();
|
||||
+ List<LevelChunk> shuffled = Lists.newArrayListWithCapacity(this.tickingChunks.size());
|
||||
+ while (iterator1.hasNext()) {
|
||||
+ shuffled.add(iterator1.next());
|
||||
+ }
|
||||
+ Collections.shuffle(shuffled);
|
||||
+ iterator1 = shuffled.iterator();
|
||||
+ }
|
||||
+ try {
|
||||
+ // Paper end - optimise chunk tick iteration
|
||||
while (iterator1.hasNext()) {
|
||||
- ServerChunkCache.ChunkAndHolder chunkproviderserver_a = (ServerChunkCache.ChunkAndHolder) iterator1.next();
|
||||
- LevelChunk chunk1 = chunkproviderserver_a.chunk;
|
||||
+ LevelChunk chunk1 = iterator1.next(); // Paper - optimise chunk tick iteration
|
||||
ChunkPos chunkcoordintpair = chunk1.getPos();
|
||||
|
||||
- if (this.level.isNaturalSpawningAllowed(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkcoordintpair)) {
|
||||
+ // Paper start - optimise chunk tick iteration
|
||||
+ com.destroystokyo.paper.util.maplist.ReferenceList<ServerPlayer> playersNearby
|
||||
+ = nearbyPlayers.getPlayers(chunkcoordintpair, io.papermc.paper.util.player.NearbyPlayers.NearbyMapType.SPAWN_RANGE);
|
||||
+ if (playersNearby == null) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ Object[] rawData = playersNearby.getRawData();
|
||||
+ boolean spawn = false;
|
||||
+ boolean tick = false;
|
||||
+ for (int itr = 0, len = playersNearby.size(); itr < len; ++itr) {
|
||||
+ ServerPlayer player = (ServerPlayer)rawData[itr];
|
||||
+ if (player.isSpectator()) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ double distance = ChunkMap.euclideanDistanceSquared(chunkcoordintpair, player);
|
||||
+ spawn |= player.lastEntitySpawnRadiusSquared >= distance;
|
||||
+ tick |= ((double)io.papermc.paper.util.player.NearbyPlayers.SPAWN_RANGE_VIEW_DISTANCE_BLOCKS) * ((double)io.papermc.paper.util.player.NearbyPlayers.SPAWN_RANGE_VIEW_DISTANCE_BLOCKS) >= distance;
|
||||
+ if (spawn & tick) {
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - optimise chunk tick iteration
|
||||
+ if (tick && chunk1.chunkStatus.isOrAfter(net.minecraft.server.level.FullChunkStatus.ENTITY_TICKING)) { // Paper - optimise chunk tick iteration
|
||||
chunk1.incrementInhabitedTime(j);
|
||||
- if (flag2 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkcoordintpair, true)) { // Spigot
|
||||
+ if (spawn && flag2 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair)) { // Spigot // Paper - optimise chunk tick iteration
|
||||
NaturalSpawner.spawnForChunk(this.level, chunk1, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag1);
|
||||
}
|
||||
|
||||
- if (this.level.shouldTickBlocksAt(chunkcoordintpair.toLong())) {
|
||||
+ if (true || this.level.shouldTickBlocksAt(chunkcoordintpair.toLong())) { // Paper - optimise chunk tick iteration
|
||||
this.level.tickChunk(chunk1, k);
|
||||
if ((chunksTicked++ & 1) == 0) net.minecraft.server.MinecraftServer.getServer().executeMidTickTasks(); // Paper
|
||||
}
|
||||
}
|
||||
}
|
||||
+ // Paper start - optimise chunk tick iteration
|
||||
+ } finally {
|
||||
+ if (iterator1 instanceof io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet.Iterator safeIterator) {
|
||||
+ safeIterator.finishedIterating();
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - optimise chunk tick iteration
|
||||
this.level.timings.chunkTicks.stopTiming(); // Paper
|
||||
gameprofilerfiller.popPush("customSpawners");
|
||||
if (flag2) {
|
||||
@@ -608,11 +670,23 @@ public class ServerChunkCache extends ChunkSource {
|
||||
}
|
||||
|
||||
gameprofilerfiller.popPush("broadcast");
|
||||
- list.forEach((chunkproviderserver_a1) -> {
|
||||
+ // Paper - optimise chunk tick iteration
|
||||
this.level.timings.broadcastChunkUpdates.startTiming(); // Paper - timing
|
||||
- chunkproviderserver_a1.holder.broadcastChanges(chunkproviderserver_a1.chunk);
|
||||
+ // Paper start - optimise chunk tick iteration
|
||||
+ if (!this.chunkMap.needsChangeBroadcasting.isEmpty()) {
|
||||
+ it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<ChunkHolder> copy = this.chunkMap.needsChangeBroadcasting.clone();
|
||||
+ this.chunkMap.needsChangeBroadcasting.clear();
|
||||
+ for (ChunkHolder holder : copy) {
|
||||
+ holder.broadcastChanges(holder.getFullChunkNowUnchecked()); // LevelChunks are NEVER unloaded
|
||||
+ if (holder.needsBroadcastChanges()) {
|
||||
+ // I DON'T want to KNOW what DUMB plugins might be doing.
|
||||
+ this.chunkMap.needsChangeBroadcasting.add(holder);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - optimise chunk tick iteration
|
||||
this.level.timings.broadcastChunkUpdates.stopTiming(); // Paper - timing
|
||||
- });
|
||||
+ // Paper - optimise chunk tick iteration
|
||||
gameprofilerfiller.pop();
|
||||
gameprofilerfiller.pop();
|
||||
this.chunkMap.tick();
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 261d0cc1812831fa99358ec1c6438a4e89629bde..d4aec99cac3f83d764e21946cc904c00e084704e 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -317,6 +317,9 @@ public class ServerPlayer extends Player {
|
||||
});
|
||||
}
|
||||
// Paper end - replace player chunk loader
|
||||
+ // Paper start - optimise chunk tick iteration
|
||||
+ public double lastEntitySpawnRadiusSquared = -1.0;
|
||||
+ // Paper end - optimise chunk tick iteration
|
||||
|
||||
public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ClientInformation clientOptions) {
|
||||
super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile);
|
Loading…
Reference in New Issue
Block a user