@@ -69,6 +69,8 @@ public class FakeChunkService {
6969 private final Map <UUID , Integer > lastSentRadius = new ConcurrentHashMap <>();
7070 private final Map <UUID , Integer > lastSentSimulationDistance = new ConcurrentHashMap <>();
7171 private final Map <UUID , Long > lastForcedPlanMs = new ConcurrentHashMap <>();
72+ private final Map <UUID , Long > lastAutoRefreshMs = new ConcurrentHashMap <>();
73+ private final Map <UUID , AtomicInteger > autoRefreshCursor = new ConcurrentHashMap <>();
7274 private final Map <UUID , UUID > lastKnownWorldId = new ConcurrentHashMap <>();
7375 private final Map <UUID , Long > sessionEpoch = new ConcurrentHashMap <>();
7476 private final AtomicLong chunkLoadSamples = new AtomicLong ();
@@ -141,6 +143,9 @@ public void onEnable() {
141143 }
142144 }
143145 }
146+ if (tracker != null ) {
147+ maybeAutoRefreshSentChunks (world , playerId , tracker );
148+ }
144149 });
145150 }
146151 },
@@ -168,6 +173,8 @@ public void onDisable() {
168173 lastSentRadius .clear ();
169174 lastSentSimulationDistance .clear ();
170175 lastForcedPlanMs .clear ();
176+ lastAutoRefreshMs .clear ();
177+ autoRefreshCursor .clear ();
171178 lastKnownWorldId .clear ();
172179 sessionEpoch .clear ();
173180 }
@@ -431,6 +438,34 @@ private void resetPlayerState(UUID playerId, boolean resetTracker) {
431438 lastSentRadius .remove (playerId );
432439 lastSentSimulationDistance .remove (playerId );
433440 lastForcedPlanMs .remove (playerId );
441+ lastAutoRefreshMs .remove (playerId );
442+ autoRefreshCursor .remove (playerId );
443+ }
444+
445+ private void maybeAutoRefreshSentChunks (World world , UUID playerId , PlayerChunkTracker tracker ) {
446+ if (!config ().autoRefreshEnabled ()) return ;
447+ if (world == null || playerId == null || tracker == null ) return ;
448+ Set <Long > sent = tracker .getSentChunks ();
449+ if (sent .isEmpty ()) return ;
450+ long now = System .currentTimeMillis ();
451+ long periodMs = config ().autoRefreshPeriodMs ();
452+ Long last = lastAutoRefreshMs .get (playerId );
453+ if (last != null && now - last < periodMs ) return ;
454+
455+ List <Long > sentList = new ArrayList <>(sent );
456+ int size = sentList .size ();
457+ if (size == 0 ) return ;
458+
459+ int perCycle = Math .min (config ().autoRefreshChunksPerCycle (), size );
460+ AtomicInteger cursor = autoRefreshCursor .computeIfAbsent (playerId , k -> new AtomicInteger (0 ));
461+ for (int i = 0 ; i < perCycle ; i ++) {
462+ int idx = Math .floorMod (cursor .getAndIncrement (), size );
463+ long chunkKey = sentList .get (idx );
464+ int cx = ChunkPos .getX (chunkKey );
465+ int cz = ChunkPos .getZ (chunkKey );
466+ handleRealChunkInteraction (world , cx , cz );
467+ }
468+ lastAutoRefreshMs .put (playerId , now );
434469 }
435470
436471 private void refreshChunkForPlayer (Player player , World world , PlayerChunkTracker tracker , int chunkX , int chunkZ , long chunkKey ) {
0 commit comments