Skip to content

Commit de903bc

Browse files
committed
fix: redundant logic & potential memory leaks
1 parent 9500c92 commit de903bc

File tree

5 files changed

+55
-27
lines changed

5 files changed

+55
-27
lines changed

src/main/java/me/mapacheee/extendedhorizons/fakechunks/dispatch/ChunkSendQueueEntry.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@
88
public record ChunkSendQueueEntry(long chunkKey, CompletableFuture<ByteBuf> buildFuture) {
99

1010
public void releaseFuture() {
11-
this.buildFuture.thenAccept(ReferenceCountUtil::release);
11+
this.buildFuture.thenAccept(buf -> {
12+
if (buf != null && buf.refCnt() > 0) {
13+
ReferenceCountUtil.release(buf);
14+
}
15+
});
1216
}
1317
}
1418

src/main/java/me/mapacheee/extendedhorizons/fakechunks/listener/ChunkInvalidationListener.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,17 @@
33
import com.google.inject.Inject;
44
import com.thewinterframework.paper.listener.ListenerComponent;
55
import me.mapacheee.extendedhorizons.fakechunks.cache.ChunkBuildCacheService;
6-
import me.mapacheee.extendedhorizons.fakechunks.session.PlayerSession;
76
import me.mapacheee.extendedhorizons.fakechunks.session.SessionRegistry;
87
import org.bukkit.block.Block;
9-
import org.bukkit.entity.Player;
8+
import net.minecraft.world.level.ChunkPos;
109
import org.bukkit.event.EventHandler;
1110
import org.bukkit.event.EventPriority;
1211
import org.bukkit.event.Listener;
1312
import org.bukkit.event.block.BlockBreakEvent;
1413
import org.bukkit.event.block.BlockPlaceEvent;
1514

15+
import java.util.UUID;
16+
1617
@ListenerComponent
1718
public final class ChunkInvalidationListener implements Listener {
1819

@@ -38,15 +39,14 @@ public void onPlace(BlockPlaceEvent event) {
3839
private void invalidate(Block block) {
3940
int chunkX = block.getX() >> 4;
4041
int chunkZ = block.getZ() >> 4;
41-
long chunkKey = net.minecraft.world.level.ChunkPos.asLong(chunkX, chunkZ);
42-
this.cacheService.invalidate(block.getWorld().getUID(), chunkKey);
42+
long chunkKey = ChunkPos.asLong(chunkX, chunkZ);
43+
UUID worldId = block.getWorld().getUID();
44+
this.cacheService.invalidate(worldId, chunkKey);
4345

44-
for (Player player : block.getWorld().getPlayers()) {
45-
PlayerSession session = this.sessionRegistry.get(player.getUniqueId());
46-
if (session == null) {
47-
continue;
46+
this.sessionRegistry.forEachSession(session -> {
47+
if (worldId.equals(session.worldId())) {
48+
session.invalidateChunk(chunkKey);
4849
}
49-
session.invalidateChunk(chunkKey);
50-
}
50+
});
5151
}
5252
}

src/main/java/me/mapacheee/extendedhorizons/fakechunks/listener/PlayerLifecycleListener.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.google.inject.Inject;
44
import com.thewinterframework.paper.listener.ListenerComponent;
5+
import me.mapacheee.extendedhorizons.fakechunks.farplayers.cache.FarPlayerCacheService;
56
import me.mapacheee.extendedhorizons.fakechunks.netty.ChannelInjectionService;
67
import me.mapacheee.extendedhorizons.fakechunks.session.PlayerSession;
78
import me.mapacheee.extendedhorizons.fakechunks.session.SessionRegistry;
@@ -18,11 +19,17 @@ public final class PlayerLifecycleListener implements Listener {
1819

1920
private final SessionRegistry sessionRegistry;
2021
private final ChannelInjectionService channelInjectionService;
22+
private final FarPlayerCacheService farPlayerCacheService;
2123

2224
@Inject
23-
public PlayerLifecycleListener(SessionRegistry sessionRegistry, ChannelInjectionService channelInjectionService) {
25+
public PlayerLifecycleListener(
26+
SessionRegistry sessionRegistry,
27+
ChannelInjectionService channelInjectionService,
28+
FarPlayerCacheService farPlayerCacheService
29+
) {
2430
this.sessionRegistry = sessionRegistry;
2531
this.channelInjectionService = channelInjectionService;
32+
this.farPlayerCacheService = farPlayerCacheService;
2633
}
2734

2835
@EventHandler(priority = EventPriority.MONITOR)
@@ -44,6 +51,7 @@ public void onQuit(PlayerQuitEvent event) {
4451
Player player = event.getPlayer();
4552
this.channelInjectionService.uninject(player);
4653
this.sessionRegistry.remove(player.getUniqueId());
54+
this.farPlayerCacheService.removePlayer(player.getUniqueId());
4755
}
4856
}
4957

src/main/java/me/mapacheee/extendedhorizons/fakechunks/session/PlayerSession.java

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,36 +5,37 @@
55
import net.minecraft.world.level.ChunkPos;
66

77
import java.util.Deque;
8+
import java.util.HashSet;
9+
import java.util.Map;
10+
import java.util.Set;
811
import java.util.UUID;
9-
import java.util.stream.LongStream;
12+
import java.util.concurrent.ConcurrentHashMap;
1013
import java.util.concurrent.ConcurrentLinkedDeque;
1114
import java.util.concurrent.atomic.AtomicLong;
15+
import java.util.stream.LongStream;
1216

1317
public 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
}

src/main/java/me/mapacheee/extendedhorizons/fakechunks/session/SessionRegistry.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import java.util.Map;
77
import java.util.UUID;
88
import java.util.concurrent.ConcurrentHashMap;
9+
import java.util.function.Consumer;
910

1011
@Service
1112
public final class SessionRegistry {
@@ -32,6 +33,9 @@ public PlayerSession ensureFor(Player player, boolean bumpEpoch) {
3233
});
3334
}
3435

36+
public void forEachSession(Consumer<PlayerSession> action) {
37+
this.sessions.values().forEach(action);
38+
}
3539

3640
public PlayerSession get(UUID playerId) {
3741
return this.sessions.get(playerId);

0 commit comments

Comments
 (0)