mirror of
https://github.com/BX-Team/DivineMC.git
synced 2026-01-04 15:31:43 +00:00
115 lines
6.2 KiB
Diff
115 lines
6.2 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
|
Date: Mon, 24 Feb 2025 19:58:39 +0300
|
|
Subject: [PATCH] Regionized Chunk Ticking
|
|
|
|
|
|
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
|
|
index ae0e36d198ad8243920c8e8a55c0be4945542763..7f982949304535376dabf42aab1848cabc8987cf 100644
|
|
--- a/net/minecraft/server/level/ServerChunkCache.java
|
|
+++ b/net/minecraft/server/level/ServerChunkCache.java
|
|
@@ -54,6 +54,10 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
|
private static final Logger LOGGER = LogUtils.getLogger();
|
|
private final DistanceManager distanceManager;
|
|
private final ServerLevel level;
|
|
+ // DivineMC - Regionized Chunk Ticking
|
|
+ public static final Executor REGION_EXECUTOR = java.util.concurrent.Executors.newFixedThreadPool(org.bxteam.divinemc.DivineConfig.regionizedChunkTickingExecutorThreadCount, new org.bxteam.divinemc.util.NamedAgnosticThreadFactory<>("region_ticking", ca.spottedleaf.moonrise.common.util.TickThread::new, org.bxteam.divinemc.DivineConfig.regionizedChunkTickingExecutorThreadPriority));
|
|
+ public volatile int tickingRegionsCount = 0;
|
|
+ // DivineMC end - Regionized Chunk Ticking
|
|
public final Thread mainThread;
|
|
final ThreadedLevelLightEngine lightEngine;
|
|
public final ServerChunkCache.MainThreadExecutor mainThreadProcessor;
|
|
@@ -461,6 +465,46 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
|
((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getChunkTaskScheduler().chunkHolderManager.close(save, true); // Paper - rewrite chunk system
|
|
}
|
|
|
|
+ // DivineMC start - Regionized Chunk Ticking
|
|
+ private static final int[] DX = {1, -1, 0, 0, 1, -1, -1, 1};
|
|
+ private static final int[] DZ = {0, 0, 1, -1, 1, 1, -1, -1};
|
|
+
|
|
+ private List<LevelChunk>[] splitChunksIntoRegions(List<LevelChunk> chunks) {
|
|
+ int size = chunks.size();
|
|
+ java.util.IdentityHashMap<LevelChunk, Boolean> chunkSet = new java.util.IdentityHashMap<>(size);
|
|
+
|
|
+ for (LevelChunk chunk : chunks) {
|
|
+ chunkSet.put(chunk, Boolean.TRUE);
|
|
+ }
|
|
+
|
|
+ List<List<LevelChunk>> groups = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>(size >> 3);
|
|
+ LevelChunk[] stack = new LevelChunk[size];
|
|
+ int stackPointer = 0;
|
|
+
|
|
+ for (LevelChunk chunk : chunks) {
|
|
+ if (chunkSet.remove(chunk) == null) continue;
|
|
+
|
|
+ List<LevelChunk> group = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>(64);
|
|
+ stack[stackPointer++] = chunk;
|
|
+
|
|
+ while (stackPointer > 0) {
|
|
+ LevelChunk current = stack[--stackPointer];
|
|
+ group.add(current);
|
|
+
|
|
+ for (int i = 0; i < 8; i++) {
|
|
+ LevelChunk neighbor = getChunk(current.locX + DX[i], current.locZ + DZ[i], false);
|
|
+ if (neighbor == null || chunkSet.remove(neighbor) == null) continue;
|
|
+ stack[stackPointer++] = neighbor;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ groups.add(group);
|
|
+ }
|
|
+
|
|
+ return groups.toArray(new List[0]);
|
|
+ }
|
|
+ // DivineMC end - Regionized Chunk Ticking
|
|
+
|
|
@Override
|
|
public void tick(BooleanSupplier hasTimeLeft, boolean tickChunks) {
|
|
if (this.level.tickRateManager().runsNormally() || !tickChunks || this.level.spigotConfig.unloadFrozenChunks) { // Spigot
|
|
@@ -492,7 +536,44 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
|
this.shuffleRandom.setSeed(this.level.random.nextLong());
|
|
if (!this.level.paperConfig().entities.spawning.perPlayerMobSpawns) Util.shuffle(list, this.shuffleRandom); // Paper - Optional per player mob spawns; do not need this when per-player is enabled
|
|
// Paper end - chunk tick iteration optimisation
|
|
- this.tickChunks(l, list);
|
|
+ // DivineMC start - Regionized Chunk Ticking
|
|
+ if (org.bxteam.divinemc.DivineConfig.enableRegionizedChunkTicking) {
|
|
+ List<LevelChunk>[] regions = splitChunksIntoRegions(list);
|
|
+ int regionCount = regions.length;
|
|
+ this.tickingRegionsCount = regionCount;
|
|
+ java.util.concurrent.CountDownLatch latch = new java.util.concurrent.CountDownLatch(regionCount);
|
|
+
|
|
+ try {
|
|
+ java.util.concurrent.ForkJoinPool.managedBlock(new java.util.concurrent.ForkJoinPool.ManagedBlocker() {
|
|
+ @Override
|
|
+ public boolean block() throws InterruptedException {
|
|
+ for (List<LevelChunk> region : regions) {
|
|
+ if (region == null) continue;
|
|
+ REGION_EXECUTOR.execute(() -> {
|
|
+ try {
|
|
+ tickChunks(l, region);
|
|
+ } finally {
|
|
+ latch.countDown();
|
|
+ }
|
|
+ });
|
|
+ }
|
|
+
|
|
+ latch.await();
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean isReleasable() {
|
|
+ return latch.getCount() == 0;
|
|
+ }
|
|
+ });
|
|
+ } catch (InterruptedException ex) {
|
|
+ throw new RuntimeException("Interrupted managed block during region ticking", ex);
|
|
+ }
|
|
+ } else {
|
|
+ this.tickChunks(l, list);
|
|
+ }
|
|
+ // DivineMC end - Regionized Chunk Ticking
|
|
} finally {
|
|
list.clear();
|
|
}
|