Skip to content

Commit 0bec503

Browse files
committed
Retain future entries buffers in chunk queue
Probably fixes #5
1 parent 594264d commit 0bec503

File tree

2 files changed

+42
-8
lines changed

2 files changed

+42
-8
lines changed

common/src/main/java/dev/booky/betterview/common/BetterViewManager.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,8 @@ private void tickPlayer(PlayerHook player, LevelHook level, McChunkPos chunkPos,
147147

148148
// start building chunk queue and add to processing queue
149149
CompletableFuture<@Nullable ByteBuf> future = level.getChunkCache().get(nextChunk).get();
150-
bv.chunkQueue.add(new ChunkQueueEntry(nextChunk, future));
150+
ChunkQueueEntry queueEntry = new ChunkQueueEntry(nextChunk, future);
151+
bv.chunkQueue.add(queueEntry.retain());
151152

152153
// check if a limit has been reached
153154
if (chunksPerTick-- <= 0) {
@@ -181,7 +182,8 @@ public PlayerHook getPlayer(UUID playerId) {
181182
}
182183

183184
public void unregisterPlayer(UUID playerId) {
184-
this.players.remove(playerId);
185+
PlayerHook player = this.players.remove(playerId);
186+
player.getNettyChannel().eventLoop().execute(player.getBvPlayer()::release);
185187
}
186188

187189
public BvLevelConfig getConfig(Key worldName) {

common/src/main/java/dev/booky/betterview/common/BetterViewPlayer.java

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import dev.booky.betterview.common.util.ChunkIterationUtil;
88
import dev.booky.betterview.common.util.McChunkPos;
99
import io.netty.buffer.ByteBuf;
10+
import io.netty.util.ReferenceCountUtil;
1011
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
1112
import org.jspecify.annotations.NullMarked;
1213
import org.jspecify.annotations.Nullable;
@@ -276,8 +277,13 @@ public void move(LevelHook newLevel, McChunkPos newPos) {
276277
}
277278

278279
public void purgeQueue(int chunkX, int chunkZ) {
279-
this.chunkQueue.removeIf(entry ->
280-
entry.chunkPos.getX() == chunkX && entry.chunkPos.getZ() == chunkZ);
280+
this.chunkQueue.removeIf(entry -> {
281+
if (entry.chunkPos.getX() == chunkX && entry.chunkPos.getZ() == chunkZ) {
282+
entry.release();
283+
return true;
284+
}
285+
return false;
286+
});
281287
}
282288

283289
public boolean checkQueueEntry(ChunkQueueEntry entry) {
@@ -290,6 +296,7 @@ public boolean checkQueueEntry(ChunkQueueEntry entry) {
290296
int chunkIndex = calcIndex(chunkPos.getX(), chunkPos.getZ(), this.storageDiameter);
291297
ChunkState state = this.chunkStates[chunkIndex];
292298
if (state.lifecycle != BV_QUEUED) {
299+
entry.release();
293300
return true; // chunk no longer queued, remove entry
294301
}
295302

@@ -299,16 +306,18 @@ public boolean checkQueueEntry(ChunkQueueEntry entry) {
299306
LOGGER.error("Error while building chunk {} for {} in {}",
300307
chunkPos, this.player, this.level, exception);
301308
state.lifecycle = UNLOADED;
309+
entry.release();
302310
return true;
303311
}
304312

305313
ByteBuf chunkBuf = entry.future.getNow(null);
306314
if (chunkBuf == null) {
307-
// ran into generation limit, try again later
315+
// probably ran into generation limit, try again later
308316
state.lifecycle = UNLOADED;
309317
// reset iteration index to prevent this entry from getting skipped
310318
// until all other chunks have been loaded
311319
this.iterationIndex = 0;
320+
entry.release();
312321
return true;
313322
}
314323

@@ -319,6 +328,7 @@ public boolean checkQueueEntry(ChunkQueueEntry entry) {
319328
: this.level.getEmptyChunkBuf(chunkPos);
320329
this.player.getNettyChannel().write(new BypassedPacket(finalChunkBuf));
321330
state.lifecycle = BV_LOADED; // mark chunk as loaded by BV
331+
entry.release();
322332
return true;
323333
}
324334

@@ -342,7 +352,7 @@ public void unloadBvChunks() {
342352
}
343353
}
344354
// clear all chunks which are currently queued for sending
345-
this.chunkQueue.clear();
355+
this.clearChunkQueue();
346356
}
347357

348358
public void handleDimensionReset(@Nullable Object networkDimension) {
@@ -357,7 +367,7 @@ public void handleDimensionReset(@Nullable Object networkDimension) {
357367
for (int i = 0, len = this.chunkStates.length; i < len; i++) {
358368
this.chunkStates[i].set(0, 0, UNLOADED);
359369
}
360-
this.chunkQueue.clear();
370+
this.clearChunkQueue();
361371
// disable temporarily
362372
this.disable();
363373
}
@@ -410,6 +420,17 @@ public void disable() {
410420
this.player.sendViewDistancePacket(this.getServerViewDistance());
411421
}
412422

423+
public void release() {
424+
this.clearChunkQueue();
425+
}
426+
427+
public void clearChunkQueue() {
428+
for (ChunkQueueEntry entry : this.chunkQueue) {
429+
entry.release();
430+
}
431+
this.chunkQueue.clear();
432+
}
433+
413434
public enum ChunkLifecycle {
414435
UNLOADED,
415436
SERVER_LOADED,
@@ -437,5 +458,16 @@ public boolean hasCoords() {
437458
public record ChunkQueueEntry(
438459
McChunkPos chunkPos,
439460
CompletableFuture<@Nullable ByteBuf> future
440-
) {}
461+
) {
462+
463+
public ChunkQueueEntry retain() {
464+
this.future.thenApply(ReferenceCountUtil::retain);
465+
return this;
466+
}
467+
468+
public ChunkQueueEntry release() {
469+
this.future.thenApply(ReferenceCountUtil::release);
470+
return this;
471+
}
472+
}
441473
}

0 commit comments

Comments
 (0)