mirror of
https://github.com/BX-Team/DivineMC.git
synced 2025-12-22 16:29:23 +00:00
regionized chunk ticking
This commit is contained in:
@@ -0,0 +1,89 @@
|
|||||||
|
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 2678bf59d557f085c7265e2f3eb038647723d35e..ee4e5462c784ea8588c12eb2b248c708c4d84bee 100644
|
||||||
|
--- a/net/minecraft/server/level/ServerChunkCache.java
|
||||||
|
+++ b/net/minecraft/server/level/ServerChunkCache.java
|
||||||
|
@@ -56,6 +56,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||||
|
private static final Logger LOGGER = LogUtils.getLogger();
|
||||||
|
private final DistanceManager distanceManager;
|
||||||
|
private final ServerLevel level;
|
||||||
|
+ 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)); // DivineMC - Regionized Chunk Ticking
|
||||||
|
public final Thread mainThread;
|
||||||
|
final ThreadedLevelLightEngine lightEngine;
|
||||||
|
public final ServerChunkCache.MainThreadExecutor mainThreadProcessor;
|
||||||
|
@@ -479,6 +480,41 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||||
|
}
|
||||||
|
// CraftBukkit end
|
||||||
|
|
||||||
|
+ // 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<List<LevelChunk>> splitChunksIntoRegions(List<LevelChunk> chunks) {
|
||||||
|
+ Set<LevelChunk> chunkSet = new java.util.HashSet<>(chunks);
|
||||||
|
+ Set<LevelChunk> visited = new java.util.HashSet<>(chunks.size());
|
||||||
|
+ List<List<LevelChunk>> groups = new ArrayList<>();
|
||||||
|
+
|
||||||
|
+ for (LevelChunk chunk : chunks) {
|
||||||
|
+ if (visited.contains(chunk)) continue;
|
||||||
|
+
|
||||||
|
+ List<LevelChunk> group = new ArrayList<>(64);
|
||||||
|
+ java.util.ArrayDeque<net.minecraft.world.level.chunk.LevelChunk> stack = new java.util.ArrayDeque<>();
|
||||||
|
+ stack.push(chunk);
|
||||||
|
+ visited.add(chunk);
|
||||||
|
+
|
||||||
|
+ while (!stack.isEmpty()) {
|
||||||
|
+ LevelChunk current = stack.pop();
|
||||||
|
+ 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.contains(neighbor) || !visited.add(neighbor)) continue;
|
||||||
|
+ stack.push(neighbor);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ groups.add(group);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return groups;
|
||||||
|
+ }
|
||||||
|
+ // DivineMC end - Regionized Chunk Ticking
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
public void tick(BooleanSupplier hasTimeLeft, boolean tickChunks) {
|
||||||
|
ProfilerFiller profilerFiller = Profiler.get();
|
||||||
|
@@ -519,7 +555,27 @@ 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(profilerFiller, l, list);
|
||||||
|
+ // DivineMC start - Regionized Chunk Ticking
|
||||||
|
+ if (org.bxteam.divinemc.DivineConfig.enableRegionizedChunkTicking) {
|
||||||
|
+ List<List<LevelChunk>> regions = splitChunksIntoRegions(list);
|
||||||
|
+ List<CompletableFuture<Void>> futures = new ArrayList<>();
|
||||||
|
+ for (List<LevelChunk> region : regions) {
|
||||||
|
+ CompletableFuture<Void> future = new CompletableFuture<>();
|
||||||
|
+ futures.add(future);
|
||||||
|
+ REGION_EXECUTOR.execute(() -> {
|
||||||
|
+ try {
|
||||||
|
+ tickChunks(profilerFiller, l, region);
|
||||||
|
+ } finally {
|
||||||
|
+ future.complete(null);
|
||||||
|
+ }
|
||||||
|
+ });
|
||||||
|
+ }
|
||||||
|
+ CompletableFuture<Void> finalFuture = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
|
||||||
|
+ finalFuture.join();
|
||||||
|
+ } else {
|
||||||
|
+ this.tickChunks(profilerFiller, l, list);
|
||||||
|
+ }
|
||||||
|
+ // DivineMC end - Regionized Chunk Ticking
|
||||||
|
profilerFiller.pop();
|
||||||
|
} finally {
|
||||||
|
list.clear();
|
||||||
@@ -246,6 +246,24 @@ public class DivineConfig {
|
|||||||
"modpacks where many structure mods are using very high weight values in their template pools.");
|
"modpacks where many structure mods are using very high weight values in their template pools.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean enableRegionizedChunkTicking = false;
|
||||||
|
public static int regionizedChunkTickingExecutorThreadCount = 4;
|
||||||
|
public static int regionizedChunkTickingExecutorThreadPriority = Thread.NORM_PRIORITY;
|
||||||
|
private static void regionizedChunkTicking() {
|
||||||
|
enableRegionizedChunkTicking = getBoolean("settings.regionized-chunk-ticking.enable", enableRegionizedChunkTicking,
|
||||||
|
"Enables regionized chunk ticking. This feature is similar to Folia");
|
||||||
|
|
||||||
|
regionizedChunkTickingExecutorThreadCount = getInt("settings.regionized-chunk-ticking.executor-thread-count", regionizedChunkTickingExecutorThreadCount,
|
||||||
|
"The amount of threads to allocate to regionized chunk ticking.");
|
||||||
|
regionizedChunkTickingExecutorThreadPriority = getInt("settings.regionized-chunk-ticking.executor-thread-priority", regionizedChunkTickingExecutorThreadPriority,
|
||||||
|
"Configures the thread priority of the executor");
|
||||||
|
|
||||||
|
if (regionizedChunkTickingExecutorThreadCount < 1 || regionizedChunkTickingExecutorThreadCount > 10) {
|
||||||
|
LOGGER.warn("Invalid regionized chunk ticking thread count: " + regionizedChunkTickingExecutorThreadCount + ", resetting to default (5)");
|
||||||
|
regionizedChunkTickingExecutorThreadCount = 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean skipUselessSecondaryPoiSensor = true;
|
public static boolean skipUselessSecondaryPoiSensor = true;
|
||||||
public static boolean clumpOrbs = true;
|
public static boolean clumpOrbs = true;
|
||||||
public static boolean ignoreMovedTooQuicklyWhenLagging = true;
|
public static boolean ignoreMovedTooQuicklyWhenLagging = true;
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package org.bxteam.divinemc.util;
|
||||||
|
|
||||||
|
import com.mojang.logging.LogUtils;
|
||||||
|
import java.util.concurrent.ThreadFactory;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
public class NamedAgnosticThreadFactory<T extends Thread> implements ThreadFactory {
|
||||||
|
private static final Logger LOGGER = LogUtils.getLogger();
|
||||||
|
private final ThreadGroup group;
|
||||||
|
private final AtomicInteger threadNumber = new AtomicInteger(1);
|
||||||
|
private final String namePrefix;
|
||||||
|
private final ThreadBuilderFunction<T> typeOfThread;
|
||||||
|
private final int priority;
|
||||||
|
|
||||||
|
public NamedAgnosticThreadFactory(String name, ThreadBuilderFunction<T> typeOfThread, int priority) {
|
||||||
|
this.typeOfThread = typeOfThread;
|
||||||
|
this.priority = priority;
|
||||||
|
this.group = Thread.currentThread().getThreadGroup();
|
||||||
|
this.namePrefix = name + "-";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Thread newThread(@NotNull Runnable runnable) {
|
||||||
|
T thread = typeOfThread.apply(this.group, runnable, this.namePrefix + this.threadNumber.getAndIncrement());
|
||||||
|
thread.setUncaughtExceptionHandler((threadx, throwable) -> {
|
||||||
|
LOGGER.error("Caught exception in thread {} from {}", threadx, runnable);
|
||||||
|
LOGGER.error("", throwable);
|
||||||
|
});
|
||||||
|
if (thread.getPriority() != priority) {
|
||||||
|
thread.setPriority(priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
return thread;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ThreadBuilderFunction<T extends Thread> {
|
||||||
|
T apply(ThreadGroup threadGroup, Runnable runnable, String name);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user