55import net .minecraft .world .level .ChunkPos ;
66
77import java .util .Deque ;
8+ import java .util .HashSet ;
9+ import java .util .Map ;
10+ import java .util .Set ;
811import java .util .UUID ;
9- import java .util .stream . LongStream ;
12+ import java .util .concurrent . ConcurrentHashMap ;
1013import java .util .concurrent .ConcurrentLinkedDeque ;
1114import java .util .concurrent .atomic .AtomicLong ;
15+ import java .util .stream .LongStream ;
1216
1317public final class PlayerSession {
1418
1519 private static final long [] EMPTY_LONG_ARRAY = new long [0 ];
16- private static final ChunkState [] EMPTY_STATE_ARRAY = new ChunkState [0 ];
17-
20+ private static final ChunkState DUMMY_STATE = new ChunkState ();
1821 private final UUID playerId ;
1922 private volatile UUID worldId ;
2023 private final AtomicLong epoch = new AtomicLong (0L );
21-
2224 private volatile long chunkKey = ChunkPos .asLong (Integer .MIN_VALUE , Integer .MIN_VALUE );
2325 private volatile int distance ;
2426 private volatile int storageRadius ;
2527 private volatile int storageDiameter ;
2628 private volatile int iterationIndex ;
27-
29+ private volatile int trackingTicker = 0 ;
2830 private volatile boolean enabled ;
2931 private volatile boolean initiated ;
30-
3132 private volatile long [] chunksInDistance = EMPTY_LONG_ARRAY ;
32- private volatile ChunkState [] chunkStates = EMPTY_STATE_ARRAY ;
33-
33+ private volatile ChunkState [] chunkStates = new ChunkState [0 ];
3434 private volatile int lastAdvertisedDistance = -1 ;
3535 private volatile int serverViewDistance = 2 ;
36-
3736 private final Deque <ChunkSendQueueEntry > chunkQueue = new ConcurrentLinkedDeque <>();
37+ private final Map <UUID , Integer > trackedFarPlayers = new ConcurrentHashMap <>();
38+ private final Set <UUID > trackingBuffer = new HashSet <>();
3839
3940 public PlayerSession (UUID playerId , UUID worldId ) {
4041 this .playerId = playerId ;
@@ -57,6 +58,14 @@ public void bumpEpoch() {
5758 this .epoch .incrementAndGet ();
5859 }
5960
61+ public int incrementTrackingTicker () {
62+ return this .trackingTicker = (this .trackingTicker + 1 ) & Integer .MAX_VALUE ;
63+ }
64+
65+ public Set <UUID > trackingBuffer () {
66+ return this .trackingBuffer ;
67+ }
68+
6069 public boolean enabled () {
6170 return this .enabled ;
6271 }
@@ -113,6 +122,10 @@ public Deque<ChunkSendQueueEntry> chunkQueue() {
113122 return this .chunkQueue ;
114123 }
115124
125+ public Map <UUID , Integer > trackedFarPlayers () {
126+ return this .trackedFarPlayers ;
127+ }
128+
116129 public void updateDistance (int newDistance ) {
117130 this .distance = Math .max (2 , newDistance );
118131 this .storageRadius = Math .max (2 , this .distance ) + 3 ;
@@ -189,7 +202,7 @@ public void moveTo(int chunkX, int chunkZ) {
189202 }
190203
191204 public void serverChunkAdd (int chunkX , int chunkZ ) {
192- if (!this .canStore (chunkX , chunkZ )) {
205+ if (this . chunkStates . length == 0 || !this .canStore (chunkX , chunkZ )) {
193206 return ;
194207 }
195208 ChunkState state = this .getState (chunkX , chunkZ );
@@ -200,6 +213,9 @@ public void serverChunkAdd(int chunkX, int chunkZ) {
200213 }
201214
202215 public boolean serverChunkRemove (int chunkX , int chunkZ ) {
216+ if (this .chunkStates .length == 0 ) {
217+ return false ;
218+ }
203219 int centerX = ChunkPos .getX (this .chunkKey );
204220 int centerZ = ChunkPos .getZ (this .chunkKey );
205221 if (!ChunkPlannerService .isWithinRange (chunkX - centerX , chunkZ - centerZ , this .distance )) {
@@ -240,10 +256,6 @@ public Long pollNextChunkKey() {
240256 return null ;
241257 }
242258
243- public void onChunkQueued (long chunkKey ) {
244- // state is already set to BV_QUEUED by pollNextChunkKey.
245- }
246-
247259 public void onChunkBuildFailed (long chunkKey ) {
248260 ChunkState state = this .getStateByKey (chunkKey );
249261 if (state .lifecycle () == ChunkLifecycle .BV_QUEUED ) {
@@ -336,7 +348,7 @@ private ChunkState getStateByKey(long chunkKey) {
336348
337349 private ChunkState getState (int chunkX , int chunkZ ) {
338350 if (this .chunkStates .length == 0 ) {
339- return new ChunkState () ;
351+ return DUMMY_STATE ;
340352 }
341353 return this .chunkStates [calcIndex (chunkX , chunkZ , this .storageDiameter )];
342354 }
0 commit comments