diff --git a/paper-server/patches/sources/net/minecraft/server/level/ChunkMap.java.patch b/paper-server/patches/sources/net/minecraft/server/level/ChunkMap.java.patch index 7a92584e06..8f4f6b63a8 100644 --- a/paper-server/patches/sources/net/minecraft/server/level/ChunkMap.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/level/ChunkMap.java.patch @@ -11,10 +11,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider, GeneratingChunkMap { private static final ChunkResult> UNLOADED_CHUNK_LIST_RESULT = ChunkResult.error("Unloaded chunks found in range"); -@@ -149,6 +153,27 @@ +@@ -148,6 +152,27 @@ + private final AtomicInteger activeChunkWrites; public int serverViewDistance; private final WorldGenContext worldGenContext; - ++ + // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback() + public final CallbackExecutor callbackExecutor = new CallbackExecutor(); + public static final class CallbackExecutor implements java.util.concurrent.Executor, Runnable { @@ -35,10 +36,9 @@ + } + }; + // CraftBukkit end -+ + public ChunkMap(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureTemplateManager structureTemplateManager, Executor executor, BlockableEventLoop mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier persistentStateManagerFactory, int viewDistance, boolean dsync) { super(new RegionStorageInfo(session.getLevelId(), world.dimension(), "chunk"), session.getDimensionPath(world.dimension()).resolve("region"), dataFixer, dsync); - this.visibleChunkMap = this.updatingChunkMap.clone(); @@ -170,7 +195,13 @@ RegistryAccess iregistrycustom = world.registryAccess(); long j = world.getSeed(); @@ -165,7 +165,7 @@ } } -@@ -1215,6 +1266,7 @@ +@@ -1215,9 +1266,11 @@ } public void addEntity(Entity entity) { @@ -173,7 +173,11 @@ if (!(entity instanceof EnderDragonPart)) { EntityType entitytypes = entity.getType(); int i = entitytypes.clientTrackingRange() * 16; -@@ -1250,6 +1302,7 @@ ++ i = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, i); // Spigot + + if (i != 0) { + int j = entitytypes.updateInterval(); +@@ -1250,6 +1303,7 @@ } protected void removeEntity(Entity entity) { @@ -181,7 +185,7 @@ if (entity instanceof ServerPlayer entityplayer) { this.updatePlayerStatus(entityplayer, false); ObjectIterator objectiterator = this.entityMap.values().iterator(); -@@ -1424,7 +1477,7 @@ +@@ -1424,7 +1478,7 @@ public final Set seenBy = Sets.newIdentityHashSet(); public TrackedEntity(final Entity entity, final int i, final int j, final boolean flag) { @@ -190,7 +194,7 @@ this.entity = entity; this.range = i; this.lastSectionPos = SectionPos.of((EntityAccess) entity); -@@ -1469,6 +1522,7 @@ +@@ -1469,6 +1523,7 @@ } public void removePlayer(ServerPlayer player) { @@ -198,7 +202,7 @@ if (this.seenBy.remove(player.connection)) { this.serverEntity.removePairing(player); } -@@ -1476,6 +1530,7 @@ +@@ -1476,6 +1531,7 @@ } public void updatePlayer(ServerPlayer player) { @@ -206,7 +210,7 @@ if (player != this.entity) { Vec3 vec3d = player.position().subtract(this.entity.position()); int i = ChunkMap.this.getPlayerViewDistance(player); -@@ -1484,6 +1539,11 @@ +@@ -1484,6 +1540,11 @@ double d2 = d0 * d0; boolean flag = d1 <= d2 && this.entity.broadcastToPlayer(player) && ChunkMap.this.isChunkTracked(player, this.entity.chunkPosition().x, this.entity.chunkPosition().z); diff --git a/paper-server/src/main/java/org/spigotmc/SpigotWorldConfig.java b/paper-server/src/main/java/org/spigotmc/SpigotWorldConfig.java index da22dbeaad..216db4fc5f 100644 --- a/paper-server/src/main/java/org/spigotmc/SpigotWorldConfig.java +++ b/paper-server/src/main/java/org/spigotmc/SpigotWorldConfig.java @@ -211,4 +211,21 @@ public class SpigotWorldConfig this.ignoreSpectatorActivation = this.getBoolean( "entity-activation-range.ignore-spectators", this.ignoreSpectatorActivation ); this.log( "Entity Activation Range: An " + this.animalActivationRange + " / Mo " + this.monsterActivationRange + " / Ra " + this.raiderActivationRange + " / Mi " + this.miscActivationRange + " / Tiv " + this.tickInactiveVillagers + " / Isa " + this.ignoreSpectatorActivation ); } + + public int playerTrackingRange = 48; + public int animalTrackingRange = 48; + public int monsterTrackingRange = 48; + public int miscTrackingRange = 32; + public int displayTrackingRange = 128; + public int otherTrackingRange = 64; + private void trackingRange() + { + this.playerTrackingRange = this.getInt( "entity-tracking-range.players", this.playerTrackingRange ); + this.animalTrackingRange = this.getInt( "entity-tracking-range.animals", this.animalTrackingRange ); + this.monsterTrackingRange = this.getInt( "entity-tracking-range.monsters", this.monsterTrackingRange ); + this.miscTrackingRange = this.getInt( "entity-tracking-range.misc", this.miscTrackingRange ); + this.displayTrackingRange = this.getInt( "entity-tracking-range.display", this.displayTrackingRange ); + this.otherTrackingRange = this.getInt( "entity-tracking-range.other", this.otherTrackingRange ); + this.log( "Entity Tracking Range: Pl " + this.playerTrackingRange + " / An " + this.animalTrackingRange + " / Mo " + this.monsterTrackingRange + " / Mi " + this.miscTrackingRange + " / Di " + this.displayTrackingRange + " / Other " + this.otherTrackingRange ); + } } diff --git a/paper-server/src/main/java/org/spigotmc/TrackingRange.java b/paper-server/src/main/java/org/spigotmc/TrackingRange.java new file mode 100644 index 0000000000..73f9563551 --- /dev/null +++ b/paper-server/src/main/java/org/spigotmc/TrackingRange.java @@ -0,0 +1,59 @@ +package org.spigotmc; + +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.Display; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.ExperienceOrb; +import net.minecraft.world.entity.decoration.ItemFrame; +import net.minecraft.world.entity.decoration.Painting; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.monster.Ghast; + +public class TrackingRange +{ + + /** + * Gets the range an entity should be 'tracked' by players and visible in + * the client. + * + * @param entity + * @param defaultRange Default range defined by Mojang + * @return + */ + public static int getEntityTrackingRange(Entity entity, int defaultRange) + { + if ( defaultRange == 0 ) + { + return defaultRange; + } + SpigotWorldConfig config = entity.level().spigotConfig; + if ( entity instanceof ServerPlayer ) + { + return config.playerTrackingRange; + } else if ( entity.activationType == ActivationRange.ActivationType.MONSTER || entity.activationType == ActivationRange.ActivationType.RAIDER ) + { + return config.monsterTrackingRange; + } else if ( entity instanceof Ghast ) + { + if ( config.monsterTrackingRange > config.monsterActivationRange ) + { + return config.monsterTrackingRange; + } else + { + return config.monsterActivationRange; + } + } else if ( entity.activationType == ActivationRange.ActivationType.ANIMAL ) + { + return config.animalTrackingRange; + } else if ( entity instanceof ItemFrame || entity instanceof Painting || entity instanceof ItemEntity || entity instanceof ExperienceOrb ) + { + return config.miscTrackingRange; + } else if ( entity instanceof Display ) + { + return config.displayTrackingRange; + } else + { + return config.otherTrackingRange; + } + } +}