9
0
mirror of https://github.com/Winds-Studio/Leaf.git synced 2025-12-25 09:59:15 +00:00
This commit is contained in:
Dreeam
2025-05-02 22:22:53 -04:00
parent f1df5351ca
commit 3f20ea5c71
27 changed files with 730 additions and 634 deletions

View File

@@ -11,9 +11,11 @@ import org.dreeam.leaf.util.queue.SpscIntQueue;
import java.util.concurrent.locks.LockSupport;
public class AsyncGoalExecutor {
public static final Logger LOGGER = LogManager.getLogger("Leaf Async Goal");
final SpscIntQueue queue;
final SpscIntQueue wake;
protected final SpscIntQueue queue;
protected final SpscIntQueue wake;
private final AsyncGoalThread thread;
private final ServerLevel serverLevel;
private boolean dirty = false;
@@ -22,18 +24,18 @@ public class AsyncGoalExecutor {
public AsyncGoalExecutor(AsyncGoalThread thread, ServerLevel serverLevel) {
this.serverLevel = serverLevel;
queue = new SpscIntQueue(AsyncTargetFinding.queueSize);
wake = new SpscIntQueue(AsyncTargetFinding.queueSize);
this.queue = new SpscIntQueue(AsyncTargetFinding.queueSize);
this.wake = new SpscIntQueue(AsyncTargetFinding.queueSize);
this.thread = thread;
}
boolean wake(int id) {
Entity entity = this.serverLevel.getEntities().get(id);
if (entity == null || entity.isRemoved() || !(entity instanceof Mob m)) {
if (entity == null || entity.isRemoved() || !(entity instanceof Mob mob)) {
return false;
}
m.goalSelector.wake();
m.targetSelector.wake();
mob.goalSelector.wake();
mob.targetSelector.wake();
return true;
}
@@ -42,7 +44,7 @@ public class AsyncGoalExecutor {
int spinCount = 0;
while (!this.queue.send(entityId)) {
spinCount++;
// Unpark thread after some spinning to help clear the queue
// Unpark the thread after some spinning to help clear the queue
if (spinCount > SPIN_LIMIT) {
unpark();
spinCount = 0;

View File

@@ -7,6 +7,7 @@ import net.minecraft.server.level.ServerLevel;
import java.util.concurrent.locks.LockSupport;
public class AsyncGoalThread extends Thread {
private static final int SPIN_TRIES = 1000;
public AsyncGoalThread(final MinecraftServer server) {

View File

@@ -3,6 +3,7 @@ package org.dreeam.leaf.async.ai;
import org.jetbrains.annotations.Nullable;
public class Waker {
@Nullable
public volatile Runnable wake = null;
@Nullable

View File

@@ -6,8 +6,10 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class PWTEventScheduler {
private static volatile PWTEventScheduler instance;
private final ExecutorService executor;
private PWTEventScheduler() {
this.executor = Executors.newCachedThreadPool(
new ThreadFactoryBuilder()

View File

@@ -13,8 +13,7 @@ public class AsyncChunkSend extends ConfigModules {
@Override
public void onLoaded() {
config.addCommentRegionBased(getBasePath(),
"""
config.addCommentRegionBased(getBasePath(), """
Makes chunk packet preparation and sending asynchronous to improve server performance.
This can significantly reduce main thread load when many players are loading chunks.""",
"""

View File

@@ -20,8 +20,7 @@ public class AsyncPathfinding extends ConfigModules {
@Override
public void onLoaded() {
config.addCommentRegionBased(getBasePath() + ".reject-policy",
"""
config.addCommentRegionBased(getBasePath() + ".reject-policy", """
The policy to use when the queue is full and a new task is submitted.
FLUSH_ALL: All pending tasks will be run on server thread.
CALLER_RUNS: Newly submitted task will be run on server thread.
@@ -56,6 +55,10 @@ public class AsyncPathfinding extends ConfigModules {
if (asyncPathfindingQueueSize <= 0)
asyncPathfindingQueueSize = asyncPathfindingMaxThreads * 256;
asyncPathfindingRejectPolicy = PathfindTaskRejectPolicy.fromString(config.getString(getBasePath() + ".reject-policy", availableProcessors >= 12 && asyncPathfindingQueueSize < 512 ? PathfindTaskRejectPolicy.FLUSH_ALL.toString() : PathfindTaskRejectPolicy.CALLER_RUNS.toString()));
asyncPathfindingRejectPolicy = PathfindTaskRejectPolicy.fromString(config.getString(getBasePath() + ".reject-policy",
availableProcessors >= 12 && asyncPathfindingQueueSize < 512
? PathfindTaskRejectPolicy.FLUSH_ALL.toString()
: PathfindTaskRejectPolicy.CALLER_RUNS.toString())
);
}
}

View File

@@ -14,8 +14,7 @@ public class AsyncPlayerDataSave extends ConfigModules {
@Override
public void onLoaded() {
config.addCommentRegionBased(getBasePath(),
"""
config.addCommentRegionBased(getBasePath(), """
Make PlayerData saving asynchronously.""",
"""
异步保存玩家数据.""");

View File

@@ -37,6 +37,7 @@ public class AsyncTargetFinding extends ConfigModules {
searchBlock = config.getBoolean(getBasePath() + ".async-search-block", true);
searchEntity = config.getBoolean(getBasePath() + ".async-search-entity", true);
queueSize = config.getInt(getBasePath() + ".queue-size", 4096);
if (queueSize <= 0) {
queueSize = 4096;
}

View File

@@ -19,15 +19,13 @@ public class MultithreadedTracker extends ConfigModules {
@Override
public void onLoaded() {
config.addCommentRegionBased(getBasePath(),
"""
config.addCommentRegionBased(getBasePath(), """
Make entity tracking saving asynchronously, can improve performance significantly,
especially in some massive entities in small area situations.""",
"""
异步实体跟踪,
在实体数量多且密集的情况下效果明显.""");
config.addCommentRegionBased(getBasePath() + ".compat-mode",
"""
config.addCommentRegionBased(getBasePath() + ".compat-mode", """
Enable compat mode ONLY if Citizens or NPC plugins using real entity has installed,
Compat mode fixed visible issue with player type NPCs of Citizens,
But still recommend to use packet based / virtual entity NPC plugin, e.g. ZNPC Plus, Adyeshach, Fancy NPC or else.""",

View File

@@ -20,8 +20,7 @@ public class SparklyPaperParallelWorldTicking extends ConfigModules {
@Override
public void onLoaded() {
config.addCommentRegionBased(getBasePath(),
"""
config.addCommentRegionBased(getBasePath(), """
**Experimental feature**
Enables parallel world ticking to improve performance on multi-core systems.""",
"""

View File

@@ -15,8 +15,7 @@ public class SmoothTeleport extends ConfigModules {
@Override
public void onLoaded() {
enabled = config.getBoolean(getBasePath(), enabled, config.pickStringRegionBased(
"""
enabled = config.getBoolean(getBasePath(), enabled, config.pickStringRegionBased("""
**Experimental feature**
Whether to make a "smooth teleport" when players changing dimension.
This requires original world and target world have same logical height to work.""",

View File

@@ -17,8 +17,7 @@ public class ChatMessageSignature extends ConfigModules {
Whether or not enable chat message signature,
disable will prevent players to report chat messages.
And also disables the popup when joining a server without
'secure chat', such as offline-mode servers.
""",
'secure chat', such as offline-mode servers.""",
"""
是否启用聊天签名, 禁用后玩家无法进行聊天举报."""));
}

View File

@@ -20,8 +20,7 @@ public class OptimizeNonFlushPacketSending extends ConfigModules {
Optimizes non-flush packet sending by using Netty's lazyExecute method to avoid
expensive thread wakeup calls when scheduling packet operations.
Requires server restart to take effect.
""",
Requires server restart to take effect.""",
"""
警告: 此选项与 ProtocolLib 不兼容, 并可能导致与其他修改数据包
处理的插件出现问题.
@@ -29,7 +28,6 @@ public class OptimizeNonFlushPacketSending extends ConfigModules {
通过使用 Netty 的 lazyExecute 方法来优化非刷新数据包的发送,
避免在调度数据包操作时进行昂贵的线程唤醒调用.
需要重启服务器才能生效.
"""));
需要重启服务器才能生效."""));
}
}

View File

@@ -15,8 +15,7 @@ public class DontSaveEntity extends ConfigModules {
@Override
public void onLoaded() {
dontSavePrimedTNT = config.getBoolean(getBasePath() + ".dont-save-primed-tnt", dontSavePrimedTNT,
config.pickStringRegionBased(
"""
config.pickStringRegionBased("""
Disable save primed tnt on chunk unloads.
Useful for redstone/technical servers, can prevent machines from being exploded by TNT,
when player disconnected caused by Internet issue.""",

View File

@@ -11,6 +11,7 @@ import org.jspecify.annotations.Nullable;
@NullMarked
public final class BlockPosIterator extends AbstractIterator<BlockPos> {
private final int startX;
private final int startY;
private final int startZ;

View File

@@ -2,6 +2,7 @@ package org.dreeam.leaf.util.queue;
/// Lock-free Single Producer Single Consumer Queue
public class SpscIntQueue {
private final int[] data;
private final PaddedAtomicInteger producerIdx = new PaddedAtomicInteger();
private final PaddedAtomicInteger producerCachedIdx = new PaddedAtomicInteger();