This commit is contained in:
@@ -33,6 +33,17 @@ public class DirtyUpdateService {
|
||||
section.acquire();
|
||||
this.dirtyQueue.add(new DirtySection(world, section, updateFlags, neighborMsk));
|
||||
// Logger.info("Section dirty: " + section.lvl + " " + section.x + " " + section.y + " " + section.z);
|
||||
int lvl = section.lvl;
|
||||
int sx = section.x;
|
||||
int sz = section.z;
|
||||
int m = (1 << (lvl + 1)) - 1;
|
||||
for (int dx = 0; dx <= m; dx++) {
|
||||
for (int dz = 0; dz <= m; dz++) {
|
||||
int absX = (sx << (lvl + 1)) | dx;
|
||||
int absZ = (sz << (lvl + 1)) | dz;
|
||||
this.instance.getVisibleBandCache().invalidate(absX, absZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,7 +132,8 @@ public class DirtyUpdateService {
|
||||
int absZ = (int) it[1];
|
||||
int minAbsY = (sy << (lvl + 1));
|
||||
int maxAbsY = minAbsY + m;
|
||||
int[] yList = VisibleBandUtil.computeVisibleBands(matchLevel, dirty.world, absX, absZ);
|
||||
int[] yList = this.instance.getVisibleBandCache().getOrSchedule(matchLevel, dirty.world, absX, absZ);
|
||||
if (yList == null) continue;
|
||||
for (int i = 0; i < yList.length && perPlayerBudget > 0; i++) {
|
||||
int absY = yList[i];
|
||||
if (absY < minAbsY || absY > maxAbsY) continue;
|
||||
|
||||
@@ -109,8 +109,11 @@ public class PlayerLodTracker {
|
||||
long key = (((long)x) << 32) ^ (z & 0xffffffffL);
|
||||
var prog = state.sentColumns.computeIfAbsent(key, k -> new ColumnProgress());
|
||||
if (prog.yList == null) {
|
||||
prog.yList = VisibleBandUtil.computeVisibleBands(level, engine, x, z);
|
||||
prog.nextIdx = 0;
|
||||
int[] ys = this.instance.getVisibleBandCache().getOrSchedule(level, engine, x, z);
|
||||
if (ys != null) {
|
||||
prog.yList = ys;
|
||||
prog.nextIdx = 0;
|
||||
}
|
||||
}
|
||||
// defer processing to global prioritized loop
|
||||
}
|
||||
@@ -139,8 +142,13 @@ public class PlayerLodTracker {
|
||||
var prog = state.sentColumns.get(key);
|
||||
if (prog == null) continue;
|
||||
if (prog.yList == null) {
|
||||
prog.yList = VisibleBandUtil.computeVisibleBands(level, engine, cx, cz);
|
||||
prog.nextIdx = 0;
|
||||
int[] ys = this.instance.getVisibleBandCache().getOrSchedule(level, engine, cx, cz);
|
||||
if (ys != null) {
|
||||
prog.yList = ys;
|
||||
prog.nextIdx = 0;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
budget.addAndGet(-processVerticalList(player, engine, cx, cz, prog, budget.get()));
|
||||
}
|
||||
|
||||
39
src/main/java/me/cortex/voxy/server/VisibleBandCache.java
Normal file
39
src/main/java/me/cortex/voxy/server/VisibleBandCache.java
Normal file
@@ -0,0 +1,39 @@
|
||||
package me.cortex.voxy.server;
|
||||
|
||||
import me.cortex.voxy.common.world.WorldEngine;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
final class VisibleBandCache {
|
||||
private final VoxyServerInstance instance;
|
||||
private final ConcurrentHashMap<Long, int[]> cache = new ConcurrentHashMap<>();
|
||||
private final ConcurrentHashMap<Long, Boolean> pending = new ConcurrentHashMap<>();
|
||||
|
||||
VisibleBandCache(VoxyServerInstance instance) {
|
||||
this.instance = instance;
|
||||
}
|
||||
|
||||
int[] getOrSchedule(ServerLevel level, WorldEngine engine, int chunkX, int chunkZ) {
|
||||
long key = (((long) chunkX) << 32) ^ (chunkZ & 0xffffffffL);
|
||||
int[] ys = cache.get(key);
|
||||
if (ys != null) return ys;
|
||||
if (pending.putIfAbsent(key, Boolean.TRUE) == null) {
|
||||
this.instance.getThreadPool().execute(() -> {
|
||||
try {
|
||||
int[] result = VisibleBandUtil.computeVisibleBands(level, engine, chunkX, chunkZ);
|
||||
cache.put(key, result);
|
||||
} finally {
|
||||
pending.remove(key);
|
||||
}
|
||||
});
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void invalidate(int chunkX, int chunkZ) {
|
||||
long key = (((long) chunkX) << 32) ^ (chunkZ & 0xffffffffL);
|
||||
cache.remove(key);
|
||||
pending.remove(key);
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ public class VoxyServerInstance extends VoxyInstance {
|
||||
|
||||
private final DirtyUpdateService dirtyUpdateService;
|
||||
private final PlayerLodTracker playerLodTracker;
|
||||
private final VisibleBandCache visibleBandCache;
|
||||
|
||||
public VoxyServerInstance(MinecraftServer server) {
|
||||
super();
|
||||
@@ -35,6 +36,7 @@ public class VoxyServerInstance extends VoxyInstance {
|
||||
|
||||
this.dirtyUpdateService = new DirtyUpdateService(this);
|
||||
this.playerLodTracker = new PlayerLodTracker(this);
|
||||
this.visibleBandCache = new VisibleBandCache(this);
|
||||
|
||||
// Start a service to tick the dirty service
|
||||
this.threadPool.serviceManager.createServiceNoCleanup(() -> this.dirtyUpdateService::tick, VoxyServerConfig.CONFIG.dirtyUpdateDelay * 50, "DirtyUpdateService");
|
||||
@@ -110,4 +112,8 @@ public class VoxyServerInstance extends VoxyInstance {
|
||||
public UnifiedServiceThreadPool getThreadPool() {
|
||||
return this.threadPool;
|
||||
}
|
||||
|
||||
VisibleBandCache getVisibleBandCache() {
|
||||
return this.visibleBandCache;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user