mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-30 16:19:03 +01:00
Entity Tracking Ranges
This will let you configure how far to track entities in range from players, so that the entity does not render on the client if out of this range. This has multiple benefits: 1) Less bandwidth. Not sending update packets for entities that are not even close to a player, or even close enough to clearly see. 2) Less lag by maps in item frames - Default range is 160 blocks... Many players can track that item frame and cause lag and not even see it. 3) Less lag in general - Less work for the server to do 4) Less client lag - Not trying to render distant item frames and paintings and entities will reduce entity count on the client, which is major for shop/town worlds which may use tons of item frames. By: Aikar <aikar@aikar.co>
This commit is contained in:
parent
94ccdc0d40
commit
831bf8fb7e
3 changed files with 90 additions and 10 deletions
|
@ -11,10 +11,11 @@
|
||||||
public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider, GeneratingChunkMap {
|
public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider, GeneratingChunkMap {
|
||||||
|
|
||||||
private static final ChunkResult<List<ChunkAccess>> UNLOADED_CHUNK_LIST_RESULT = ChunkResult.error("Unloaded chunks found in range");
|
private static final ChunkResult<List<ChunkAccess>> 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;
|
public int serverViewDistance;
|
||||||
private final WorldGenContext worldGenContext;
|
private final WorldGenContext worldGenContext;
|
||||||
|
+
|
||||||
+ // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback()
|
+ // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback()
|
||||||
+ public final CallbackExecutor callbackExecutor = new CallbackExecutor();
|
+ public final CallbackExecutor callbackExecutor = new CallbackExecutor();
|
||||||
+ public static final class CallbackExecutor implements java.util.concurrent.Executor, Runnable {
|
+ public static final class CallbackExecutor implements java.util.concurrent.Executor, Runnable {
|
||||||
|
@ -35,10 +36,9 @@
|
||||||
+ }
|
+ }
|
||||||
+ };
|
+ };
|
||||||
+ // CraftBukkit end
|
+ // CraftBukkit 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) {
|
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(new RegionStorageInfo(session.getLevelId(), world.dimension(), "chunk"), session.getDimensionPath(world.dimension()).resolve("region"), dataFixer, 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 @@
|
@@ -170,7 +195,13 @@
|
||||||
RegistryAccess iregistrycustom = world.registryAccess();
|
RegistryAccess iregistrycustom = world.registryAccess();
|
||||||
long j = world.getSeed();
|
long j = world.getSeed();
|
||||||
|
@ -165,7 +165,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1215,6 +1266,7 @@
|
@@ -1215,9 +1266,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addEntity(Entity entity) {
|
public void addEntity(Entity entity) {
|
||||||
|
@ -173,7 +173,11 @@
|
||||||
if (!(entity instanceof EnderDragonPart)) {
|
if (!(entity instanceof EnderDragonPart)) {
|
||||||
EntityType<?> entitytypes = entity.getType();
|
EntityType<?> entitytypes = entity.getType();
|
||||||
int i = entitytypes.clientTrackingRange() * 16;
|
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) {
|
protected void removeEntity(Entity entity) {
|
||||||
|
@ -181,7 +185,7 @@
|
||||||
if (entity instanceof ServerPlayer entityplayer) {
|
if (entity instanceof ServerPlayer entityplayer) {
|
||||||
this.updatePlayerStatus(entityplayer, false);
|
this.updatePlayerStatus(entityplayer, false);
|
||||||
ObjectIterator objectiterator = this.entityMap.values().iterator();
|
ObjectIterator objectiterator = this.entityMap.values().iterator();
|
||||||
@@ -1424,7 +1477,7 @@
|
@@ -1424,7 +1478,7 @@
|
||||||
public final Set<ServerPlayerConnection> seenBy = Sets.newIdentityHashSet();
|
public final Set<ServerPlayerConnection> seenBy = Sets.newIdentityHashSet();
|
||||||
|
|
||||||
public TrackedEntity(final Entity entity, final int i, final int j, final boolean flag) {
|
public TrackedEntity(final Entity entity, final int i, final int j, final boolean flag) {
|
||||||
|
@ -190,7 +194,7 @@
|
||||||
this.entity = entity;
|
this.entity = entity;
|
||||||
this.range = i;
|
this.range = i;
|
||||||
this.lastSectionPos = SectionPos.of((EntityAccess) entity);
|
this.lastSectionPos = SectionPos.of((EntityAccess) entity);
|
||||||
@@ -1469,6 +1522,7 @@
|
@@ -1469,6 +1523,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removePlayer(ServerPlayer player) {
|
public void removePlayer(ServerPlayer player) {
|
||||||
|
@ -198,7 +202,7 @@
|
||||||
if (this.seenBy.remove(player.connection)) {
|
if (this.seenBy.remove(player.connection)) {
|
||||||
this.serverEntity.removePairing(player);
|
this.serverEntity.removePairing(player);
|
||||||
}
|
}
|
||||||
@@ -1476,6 +1530,7 @@
|
@@ -1476,6 +1531,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updatePlayer(ServerPlayer player) {
|
public void updatePlayer(ServerPlayer player) {
|
||||||
|
@ -206,7 +210,7 @@
|
||||||
if (player != this.entity) {
|
if (player != this.entity) {
|
||||||
Vec3 vec3d = player.position().subtract(this.entity.position());
|
Vec3 vec3d = player.position().subtract(this.entity.position());
|
||||||
int i = ChunkMap.this.getPlayerViewDistance(player);
|
int i = ChunkMap.this.getPlayerViewDistance(player);
|
||||||
@@ -1484,6 +1539,11 @@
|
@@ -1484,6 +1540,11 @@
|
||||||
double d2 = d0 * d0;
|
double d2 = d0 * d0;
|
||||||
boolean flag = d1 <= d2 && this.entity.broadcastToPlayer(player) && ChunkMap.this.isChunkTracked(player, this.entity.chunkPosition().x, this.entity.chunkPosition().z);
|
boolean flag = d1 <= d2 && this.entity.broadcastToPlayer(player) && ChunkMap.this.isChunkTracked(player, this.entity.chunkPosition().x, this.entity.chunkPosition().z);
|
||||||
|
|
||||||
|
|
|
@ -211,4 +211,21 @@ public class SpigotWorldConfig
|
||||||
this.ignoreSpectatorActivation = this.getBoolean( "entity-activation-range.ignore-spectators", this.ignoreSpectatorActivation );
|
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 );
|
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 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
59
paper-server/src/main/java/org/spigotmc/TrackingRange.java
Normal file
59
paper-server/src/main/java/org/spigotmc/TrackingRange.java
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue