mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2025-12-25 18:09:17 +00:00
Revert AI goal selector to vanilla behavior (#458)
* Revert AI goal selector to vanilla behavior * remove config * Remove config & Update patch comments * rename * re apply
This commit is contained in:
@@ -3,7 +3,6 @@ package org.dreeam.leaf.async;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dreeam.leaf.async.ai.AsyncGoalThread;
|
||||
import org.dreeam.leaf.async.locate.AsyncLocator;
|
||||
import org.dreeam.leaf.async.path.AsyncPathProcessor;
|
||||
import org.dreeam.leaf.async.tracker.AsyncTracker;
|
||||
@@ -32,15 +31,6 @@ public class ShutdownExecutors {
|
||||
}
|
||||
}
|
||||
|
||||
if (server.asyncGoalThread != null) {
|
||||
LOGGER.info("Waiting for mob target finding thread to shutdown...");
|
||||
AsyncGoalThread.RUNNING = false;
|
||||
try {
|
||||
server.asyncGoalThread.join(3000L);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
if (AsyncTracker.TRACKER_EXECUTOR != null) {
|
||||
LOGGER.info("Waiting for entity tracker executor to shutdown...");
|
||||
AsyncTracker.TRACKER_EXECUTOR.shutdown();
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
package org.dreeam.leaf.async.ai;
|
||||
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dreeam.leaf.config.modules.async.AsyncTargetFinding;
|
||||
import org.dreeam.leaf.util.queue.SpscIntQueue;
|
||||
|
||||
import java.util.OptionalInt;
|
||||
|
||||
public class AsyncGoalExecutor {
|
||||
|
||||
protected static final Logger LOGGER = LogManager.getLogger("Leaf Async Goal");
|
||||
protected final SpscIntQueue queue;
|
||||
private final ServerLevel world;
|
||||
|
||||
public AsyncGoalExecutor(ServerLevel world) {
|
||||
this.world = world;
|
||||
this.queue = new SpscIntQueue(AsyncTargetFinding.queueSize);
|
||||
}
|
||||
|
||||
boolean wakeAll() {
|
||||
boolean success = false;
|
||||
while (true) {
|
||||
OptionalInt result = queue.recv();
|
||||
if (result.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
int id = result.getAsInt();
|
||||
success = true;
|
||||
wake(id);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
public void tickMob(Mob mob) {
|
||||
if (!poll(mob)) {
|
||||
return;
|
||||
}
|
||||
int entityId = mob.getId();
|
||||
if (!this.queue.send(entityId)) {
|
||||
do {
|
||||
wake(entityId);
|
||||
} while (poll(mob));
|
||||
}
|
||||
}
|
||||
|
||||
private void wake(int id) {
|
||||
Entity entity = this.world.getEntities().get(id);
|
||||
if (entity == null || entity.isRemoved() || !(entity instanceof Mob mob)) {
|
||||
return;
|
||||
}
|
||||
mob.goalSelector.ctx.wake(this.world);
|
||||
mob.targetSelector.ctx.wake(this.world);
|
||||
}
|
||||
|
||||
private boolean poll(Mob mob) {
|
||||
try {
|
||||
mob.tickingTarget = true;
|
||||
boolean a = mob.targetSelector.poll();
|
||||
mob.tickingTarget = false;
|
||||
boolean b = mob.goalSelector.poll();
|
||||
return a || b;
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Exception while polling", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package org.dreeam.leaf.async.ai;
|
||||
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
|
||||
import java.util.OptionalInt;
|
||||
import java.util.concurrent.locks.LockSupport;
|
||||
|
||||
public class AsyncGoalThread extends Thread {
|
||||
|
||||
public static volatile boolean RUNNING = true;
|
||||
public AsyncGoalThread(final MinecraftServer server) {
|
||||
super(() -> run(server), "Leaf Async Goal Thread");
|
||||
this.setDaemon(false);
|
||||
this.setUncaughtExceptionHandler(Util::onThreadException);
|
||||
this.setPriority(Thread.NORM_PRIORITY - 1);
|
||||
this.start();
|
||||
}
|
||||
|
||||
private static void run(MinecraftServer server) {
|
||||
while (RUNNING) {
|
||||
boolean retry = false;
|
||||
for (ServerLevel level : server.getAllLevels()) {
|
||||
retry |= level.asyncGoalExecutor.wakeAll();
|
||||
}
|
||||
|
||||
if (!retry) {
|
||||
LockSupport.parkNanos(1_000_000L);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package org.dreeam.leaf.async.ai;
|
||||
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface VWaker {
|
||||
@Nullable Object wake(ServerLevel world);
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package org.dreeam.leaf.async.ai;
|
||||
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class Waker {
|
||||
|
||||
@Nullable
|
||||
public volatile VWaker wake = null;
|
||||
@Nullable
|
||||
public volatile Object result = null;
|
||||
private volatile boolean cancel = false;
|
||||
public boolean state = true;
|
||||
|
||||
public final @Nullable Object result() {
|
||||
Object result = this.result;
|
||||
this.result = null;
|
||||
return result;
|
||||
}
|
||||
|
||||
public final void cancel() {
|
||||
this.cancel = true;
|
||||
this.wake = null;
|
||||
this.result = null;
|
||||
}
|
||||
|
||||
final void wake(ServerLevel world) {
|
||||
final VWaker wake = this.wake;
|
||||
if (wake != null) {
|
||||
try {
|
||||
this.result = wake.wake(world);
|
||||
} catch (Exception e) {
|
||||
AsyncGoalExecutor.LOGGER.error("Exception while wake", e);
|
||||
}
|
||||
this.wake = null;
|
||||
if (this.cancel) {
|
||||
this.result = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
|
||||
package org.dreeam.leaf.config.modules.async;
|
||||
|
||||
import org.dreeam.leaf.config.ConfigModules;
|
||||
import org.dreeam.leaf.config.EnumConfigCategory;
|
||||
import org.dreeam.leaf.config.LeafConfig;
|
||||
|
||||
public class AsyncTargetFinding extends ConfigModules {
|
||||
|
||||
public String getBasePath() {
|
||||
return EnumConfigCategory.ASYNC.getBaseKeyName() + ".async-target-finding";
|
||||
}
|
||||
|
||||
public static boolean enabled = false;
|
||||
public static boolean alertOther = true;
|
||||
public static boolean searchBlock = true;
|
||||
public static boolean searchEntity = true;
|
||||
public static int queueSize = 4096;
|
||||
private static boolean asyncTargetFindingInitialized;
|
||||
|
||||
@Override
|
||||
public void onLoaded() {
|
||||
config.addCommentRegionBased(getBasePath(), """
|
||||
This moves the expensive entity and block search calculations to background thread while
|
||||
keeping the actual validation on the main thread.""",
|
||||
"""
|
||||
这会将昂贵的实体目标搜索计算移至后台线程, 同时在主线程上保持实际的实体验证.""");
|
||||
|
||||
if (asyncTargetFindingInitialized) {
|
||||
config.getConfigSection(getBasePath());
|
||||
return;
|
||||
}
|
||||
asyncTargetFindingInitialized = true;
|
||||
|
||||
enabled = config.getBoolean(getBasePath() + ".enabled", enabled);
|
||||
// Disable if parallel world ticking is enabled, as they are incompatible.
|
||||
if (enabled && SparklyPaperParallelWorldTicking.enabled) {
|
||||
LeafConfig.LOGGER.warn("Async target finding is incompatible with Parallel World Ticking. Disabling Async target finding automatically.");
|
||||
enabled = false;
|
||||
}
|
||||
alertOther = config.getBoolean(getBasePath() + ".async-alert-other", true);
|
||||
searchBlock = config.getBoolean(getBasePath() + ".async-search-block", true);
|
||||
searchEntity = config.getBoolean(getBasePath() + ".async-search-entity", true);
|
||||
queueSize = config.getInt(getBasePath() + ".queue-size", 0);
|
||||
|
||||
if (queueSize <= 0) {
|
||||
queueSize = 4096;
|
||||
}
|
||||
if (!enabled) {
|
||||
alertOther = false;
|
||||
searchEntity = false;
|
||||
searchBlock = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package org.dreeam.leaf.config.modules.opt;
|
||||
|
||||
import org.dreeam.leaf.config.ConfigModules;
|
||||
import org.dreeam.leaf.config.EnumConfigCategory;
|
||||
|
||||
public class ThrottleInactiveGoalSelectorTick extends ConfigModules {
|
||||
|
||||
public String getBasePath() {
|
||||
return EnumConfigCategory.PERF.getBaseKeyName();
|
||||
}
|
||||
|
||||
public static boolean enabled = true;
|
||||
|
||||
@Override
|
||||
public void onLoaded() {
|
||||
enabled = config.getBoolean(getBasePath() + ".inactive-goal-selector-throttle", enabled, config.pickStringRegionBased("""
|
||||
Throttles the AI goal selector in entity inactive ticks.
|
||||
This can improve performance by a few percent, but has minor gameplay implications.""",
|
||||
"""
|
||||
是否在实体不活跃 tick 时阻塞 AI 目标选择器.
|
||||
有助于提升性能, 但对游戏有轻微影响."""));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user