From 7c24caf004b9276ee6d64c610d1760da99aab76f Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Tue, 8 Jul 2025 11:34:32 +0300 Subject: [PATCH 1/5] More ActionLogger and ActionThread optimisations --- .../npcs/controllers/data/action/Action.java | 5 ++-- .../controllers/data/action/ActionLogger.java | 18 +++++++---- .../data/action/ActionManager.java | 3 ++ .../controllers/data/action/ActionQueue.java | 28 +++++++++-------- .../controllers/data/action/ActionThread.java | 30 +++++++++++++++---- 5 files changed, 59 insertions(+), 25 deletions(-) diff --git a/src/main/java/noppes/npcs/controllers/data/action/Action.java b/src/main/java/noppes/npcs/controllers/data/action/Action.java index b6d7dad2b..3951b09b2 100644 --- a/src/main/java/noppes/npcs/controllers/data/action/Action.java +++ b/src/main/java/noppes/npcs/controllers/data/action/Action.java @@ -368,6 +368,9 @@ public class Action implements IAction { @Override public void kill() { + if (manager.debug) + manager.LOGGER.log(String.format("Killing Action '%s'...", name), queue); + if (actionThread != null) actionThread.stop(); @@ -375,8 +378,6 @@ public class Action implements IAction { isScheduled = false; done = true; - if (manager.debug) - manager.LOGGER.log(String.format("Killed Action '%s'", name), queue); } public String toString() { diff --git a/src/main/java/noppes/npcs/controllers/data/action/ActionLogger.java b/src/main/java/noppes/npcs/controllers/data/action/ActionLogger.java index 34eacb9a5..f4b6cbc2b 100644 --- a/src/main/java/noppes/npcs/controllers/data/action/ActionLogger.java +++ b/src/main/java/noppes/npcs/controllers/data/action/ActionLogger.java @@ -93,17 +93,14 @@ public class ActionLogger { ListIterator it = new ArrayList<>(stack).listIterator(stack.size()); while (it.hasPrevious()) { - TreeNode node = it.previous(); - if (it.hasPrevious()) { + if (it.hasPrevious()) prefix.append("│ "); - } else { + else prefix.append(isLast ? "└──── " : "├──── "); - } } String header = getLogHeader(source); - LogWriter.info(prefix + header + message); - + println(prefix + header + message); return this; } @@ -126,11 +123,20 @@ public class ActionLogger { name = ((IActionQueue) obj).getName(); } else if (obj instanceof IAction) { name = ((IAction) obj).getName(); + } else if (obj instanceof ActionThread) { + name = ((ActionThread) obj).getAction().getName(); } return String.format("[%s/'%s'] ", type, name); } + private static final String ANSI_CYAN = "\u001B[96m"; + private static final String ANSI_GOLD = "\u001B[93m"; + private static final String ANSI_RESET = "\u001B[0m"; + + public void println(String str) { + System.out.printf("[%tT] %s[%s]:%s %s%s%n", new Date(), ANSI_CYAN, Thread.currentThread().getName(), ANSI_GOLD, str, ANSI_RESET); + } // public ActionLogger beginTick1(ActionManager manager) { // snapshot.clear(); diff --git a/src/main/java/noppes/npcs/controllers/data/action/ActionManager.java b/src/main/java/noppes/npcs/controllers/data/action/ActionManager.java index f379d5dd5..167ee729e 100644 --- a/src/main/java/noppes/npcs/controllers/data/action/ActionManager.java +++ b/src/main/java/noppes/npcs/controllers/data/action/ActionManager.java @@ -66,6 +66,9 @@ public class ActionManager implements IActionManager { @Override public IActionManager setDebugMode(boolean debug) { this.debug = debug; + + if (debug) + LOGGER.log("Enabled debug mode", this); return this; } diff --git a/src/main/java/noppes/npcs/controllers/data/action/ActionQueue.java b/src/main/java/noppes/npcs/controllers/data/action/ActionQueue.java index d55b44101..1a07eee03 100644 --- a/src/main/java/noppes/npcs/controllers/data/action/ActionQueue.java +++ b/src/main/java/noppes/npcs/controllers/data/action/ActionQueue.java @@ -261,18 +261,7 @@ public class ActionQueue implements IActionQueue { /////////////////////////////////////////////////// // Handling - protected boolean tick(Action a) { - if (a == null) - return false; - - if (manager.debug) - manager.LOGGER.push(this).log(String.format("Started ticking Action '%s' ", a.name), this).push(a); - - a.tick(); - - if (manager.debug) - manager.LOGGER.pop().finish(String.format("Finished ticking Action '%s' ", a.name), this).pop(); - + public boolean finish(Action a) { if (a.isDone()) { if (a.onDone != null) a.execute("done", a::executeOnDone); @@ -286,6 +275,21 @@ public class ActionQueue implements IActionQueue { return false; } + protected boolean tick(Action a) { + if (a == null) + return false; + + boolean wasDone = a.isDone(); + if (manager.debug && !wasDone) + manager.LOGGER.push(this).log(String.format("Started ticking Action '%s' ", a.name), this).push(a); + + a.tick(); + + if (manager.debug && !wasDone) + manager.LOGGER.pop().finish(String.format("Finished ticking Action '%s' ", a.name), this).pop(); + + return finish(a); + } protected void tick() { if (!isWorking || isDead) diff --git a/src/main/java/noppes/npcs/controllers/data/action/ActionThread.java b/src/main/java/noppes/npcs/controllers/data/action/ActionThread.java index c4df4858c..813efd476 100644 --- a/src/main/java/noppes/npcs/controllers/data/action/ActionThread.java +++ b/src/main/java/noppes/npcs/controllers/data/action/ActionThread.java @@ -29,6 +29,9 @@ public class ActionThread { thread.setName(String.format("ActionThread (%s)", action.getName())); return thread; }); + + if (action.manager.debug) + action.manager.LOGGER.log("Created Action thread!", this); } public void stop() { @@ -41,7 +44,11 @@ public class ActionThread { if (action.manager.debug) - action.manager.LOGGER.log("Stopping thread", action); + action.manager.LOGGER.log("Stopping thread", this); + } + + public Action getAction() { + return action; } public void pauseFor(long millis) { @@ -51,7 +58,7 @@ public class ActionThread { try { threadSleeping = true; if (action.manager.debug) - action.manager.LOGGER.log(String.format("Sleeping thread for %s ticks", millis / 50), action); + action.manager.LOGGER.log(String.format("Sleeping thread for %s ticks", millis / 50), this); Thread.sleep(millis); } catch (InterruptedException e) { @@ -60,7 +67,7 @@ public class ActionThread { threadSleeping = false; if (action.manager.debug) - action.manager.LOGGER.log(String.format("Woken up thread after sleeping for %s ticks", millis / 50), action); + action.manager.LOGGER.log(String.format("Woken up thread after sleeping for %s ticks", millis / 50), this); } } @@ -77,7 +84,7 @@ public class ActionThread { while (threadPaused) { try { if (action.manager.debug) - action.manager.LOGGER.log(String.format("Pausing thread"), action); + action.manager.LOGGER.log(String.format("Pausing thread"), this); lock.wait(); // Wait until notified } catch (InterruptedException e) { @@ -99,7 +106,7 @@ public class ActionThread { lock.notify(); if (action.manager.debug) - action.manager.LOGGER.log(String.format("Resumed thread"), action); + action.manager.LOGGER.log(String.format("Resumed thread"), this); } if (threadSleeping) @@ -130,14 +137,27 @@ public class ActionThread { if (!runningKeys.add(taskKey)) return; + if (action.manager.debug) + action.manager.LOGGER.log(String.format("Delegating task '%s' to Action thread...", taskKey), action); + final AtomicReference> taskRef = new AtomicReference<>(); taskRef.set(executor.submit(() -> { + if (action.manager.debug) + action.manager.LOGGER.log(String.format("Started executing task '%s' on Action thread...", taskKey), this); + runningTasks.add(taskRef.get()); try { task.run(); } finally { runningTasks.remove(taskRef.get()); runningKeys.remove(taskKey); + + if (action.manager.debug) + action.manager.LOGGER.log(String.format("Finished executing task '%s' on Action thread", taskKey), this); + + if (((ActionQueue) action.queue).finish(action)) + action.queue.getQueue().remove(action); + } })); } From b6ac84d4c4d10c2006c60dc68896b3541a5c98cf Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Tue, 8 Jul 2025 11:59:22 +0300 Subject: [PATCH 2/5] oops --- .../java/noppes/npcs/controllers/data/action/ActionLogger.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/noppes/npcs/controllers/data/action/ActionLogger.java b/src/main/java/noppes/npcs/controllers/data/action/ActionLogger.java index f4b6cbc2b..fc24c79e8 100644 --- a/src/main/java/noppes/npcs/controllers/data/action/ActionLogger.java +++ b/src/main/java/noppes/npcs/controllers/data/action/ActionLogger.java @@ -93,6 +93,7 @@ public class ActionLogger { ListIterator it = new ArrayList<>(stack).listIterator(stack.size()); while (it.hasPrevious()) { + TreeNode node = it.previous(); if (it.hasPrevious()) prefix.append("│ "); else From b37f9a7ea4ea686029ac6c631c5e490e75cd300c Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Tue, 8 Jul 2025 12:00:37 +0300 Subject: [PATCH 3/5] Added Action.getIdentifier --- .../noppes/npcs/controllers/data/action/Action.java | 13 +++++++++---- .../npcs/controllers/data/action/ActionQueue.java | 8 ++++---- .../data/action/action/ConditionalAction.java | 3 +-- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/main/java/noppes/npcs/controllers/data/action/Action.java b/src/main/java/noppes/npcs/controllers/data/action/Action.java index 3951b09b2..76df3d8e6 100644 --- a/src/main/java/noppes/npcs/controllers/data/action/Action.java +++ b/src/main/java/noppes/npcs/controllers/data/action/Action.java @@ -107,7 +107,7 @@ public class Action implements IAction { this.isScheduled = true; if (manager.debug) - manager.LOGGER.log(String.format("Scheduled Action '%s'", name), queue); + manager.LOGGER.log(String.format("Scheduled %s", getIdentifier()), queue); } @Override @@ -278,7 +278,7 @@ public class Action implements IAction { } if (duration == 0 && onStart != null) - execute("start", this::executeOnStart); + execute("onStart", this::executeOnStart); if (done) return; @@ -369,7 +369,7 @@ public class Action implements IAction { @Override public void kill() { if (manager.debug) - manager.LOGGER.log(String.format("Killing Action '%s'...", name), queue); + manager.LOGGER.log(String.format("Killing %s...", getIdentifier()), queue); if (actionThread != null) actionThread.stop(); @@ -380,8 +380,13 @@ public class Action implements IAction { } + @Override + public String getIdentifier() { + return String.format("%s '%s'", getClass().getSimpleName(), name); + } + public String toString() { - return String.format("%s '%s' [queue='%s', scheduled=%s, done=%s, paused=%s, updateEvery=%s, duration=%d/%d, count=%d/%d, threaded=%s]", getClass().getSimpleName(), name != null ? name : "unnamed", getQueueName(), isScheduled, done, isPaused(), updateEveryXTick, duration, maxDuration, count, maxCount, isThreaded); + return String.format("%s [queue='%s', scheduled=%s, done=%s, paused=%s, updateEvery=%s, duration=%d/%d, count=%d/%d, threaded=%s]", getIdentifier(), getQueueName(), isScheduled, done, isPaused(), updateEveryXTick, duration, maxDuration, count, maxCount, isThreaded); } /////////////////////////////////////////////////// ////////////////////////////////////////////////// diff --git a/src/main/java/noppes/npcs/controllers/data/action/ActionQueue.java b/src/main/java/noppes/npcs/controllers/data/action/ActionQueue.java index 1a07eee03..cd06bacf2 100644 --- a/src/main/java/noppes/npcs/controllers/data/action/ActionQueue.java +++ b/src/main/java/noppes/npcs/controllers/data/action/ActionQueue.java @@ -264,12 +264,12 @@ public class ActionQueue implements IActionQueue { public boolean finish(Action a) { if (a.isDone()) { if (a.onDone != null) - a.execute("done", a::executeOnDone); + a.execute("onDone", a::executeOnDone); a.kill(); if (manager.debug) - manager.LOGGER.finish(String.format("Removing Action '%s' from queue", a.name), this); + manager.LOGGER.finish(String.format("Removing %s from queue", a.getIdentifier()), this); return true; } @@ -281,12 +281,12 @@ public class ActionQueue implements IActionQueue { boolean wasDone = a.isDone(); if (manager.debug && !wasDone) - manager.LOGGER.push(this).log(String.format("Started ticking Action '%s' ", a.name), this).push(a); + manager.LOGGER.push(this).log(String.format("Started ticking %s", a.getIdentifier(), a.name), this).push(a); a.tick(); if (manager.debug && !wasDone) - manager.LOGGER.pop().finish(String.format("Finished ticking Action '%s' ", a.name), this).pop(); + manager.LOGGER.pop().finish(String.format("Finished ticking %s", a.getIdentifier(), a.name), this).pop(); return finish(a); } diff --git a/src/main/java/noppes/npcs/controllers/data/action/action/ConditionalAction.java b/src/main/java/noppes/npcs/controllers/data/action/action/ConditionalAction.java index 04eddd3b3..7bcd0ef97 100644 --- a/src/main/java/noppes/npcs/controllers/data/action/action/ConditionalAction.java +++ b/src/main/java/noppes/npcs/controllers/data/action/action/ConditionalAction.java @@ -155,8 +155,7 @@ public class ConditionalAction extends Action implements IConditionalAction { public String toString() { - return String.format("%s '%s' [queue='%s', scheduled=%s, done=%s, paused=%s, updateEvery=%s, duration=%d/%d, count=%d/%d, checks=%d/%d, taskExecuted=%s, threaded=%s]", getClass().getSimpleName(), - name != null ? name : "unnamed", getQueueName(), + return String.format("%s [queue='%s', scheduled=%s, done=%s, paused=%s, updateEvery=%s, duration=%d/%d, count=%d/%d, checks=%d/%d, taskExecuted=%s, threaded=%s]", getIdentifier(), getQueueName(), isScheduled, done, isPaused(), From 70f0ab1e6f6dc7bb09a8d136479f33de31641542 Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Tue, 8 Jul 2025 14:22:49 +0300 Subject: [PATCH 4/5] ActionQueue.stopWhenEmpty --- .../controllers/data/action/ActionQueue.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/main/java/noppes/npcs/controllers/data/action/ActionQueue.java b/src/main/java/noppes/npcs/controllers/data/action/ActionQueue.java index cd06bacf2..0a20f4a5a 100644 --- a/src/main/java/noppes/npcs/controllers/data/action/ActionQueue.java +++ b/src/main/java/noppes/npcs/controllers/data/action/ActionQueue.java @@ -19,6 +19,8 @@ public class ActionQueue implements IActionQueue { protected boolean isParallel; protected boolean isDead; + protected boolean stopWhenEmpty; + protected boolean killWhenEmpty; protected int killWhenEmptyAfter = 100; @@ -70,6 +72,18 @@ public class ActionQueue implements IActionQueue { isParallel = parallel; return this; } + + @Override + public boolean isStoppedWhenEmpty() { + return stopWhenEmpty; + } + + @Override + public IActionQueue stopWhenEmpty(boolean stopWhenEmpty) { + this.stopWhenEmpty = stopWhenEmpty; + return this; + } + @Override public boolean isKilledWhenEmpty() { return killWhenEmpty; @@ -309,6 +323,9 @@ public class ActionQueue implements IActionQueue { pit.remove(); } + if (stopWhenEmpty && !hasActiveTasks()) + stop(); + killWhenEmpty(); if (manager.debug && active) From 91dc56bf87ff624ed7ea5da0dbc7a470f0e1d4ff Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Tue, 8 Jul 2025 14:34:39 +0300 Subject: [PATCH 5/5] Moved NpcAPI.actionManager to ActionManager.GLOBAL --- src/main/java/noppes/npcs/ServerTickHandler.java | 4 ++-- .../controllers/data/action/ActionManager.java | 16 ++++++++++++++++ src/main/java/noppes/npcs/scripted/NpcAPI.java | 6 +----- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/main/java/noppes/npcs/ServerTickHandler.java b/src/main/java/noppes/npcs/ServerTickHandler.java index 6b5706b15..2cb6d4e6d 100644 --- a/src/main/java/noppes/npcs/ServerTickHandler.java +++ b/src/main/java/noppes/npcs/ServerTickHandler.java @@ -11,7 +11,7 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.world.WorldServer; import noppes.npcs.client.AnalyticsTracking; import noppes.npcs.controllers.data.PlayerData; -import noppes.npcs.scripted.NpcAPI; +import noppes.npcs.controllers.data.action.ActionManager; import java.net.InetAddress; import java.net.UnknownHostException; @@ -21,7 +21,7 @@ public class ServerTickHandler { @SubscribeEvent public void onServerTick(TickEvent.ServerTickEvent event) { if (event.phase == Phase.END) { - NpcAPI.actionManager.tick(); + ActionManager.GLOBAL.tick(); } } diff --git a/src/main/java/noppes/npcs/controllers/data/action/ActionManager.java b/src/main/java/noppes/npcs/controllers/data/action/ActionManager.java index 167ee729e..01173b4ce 100644 --- a/src/main/java/noppes/npcs/controllers/data/action/ActionManager.java +++ b/src/main/java/noppes/npcs/controllers/data/action/ActionManager.java @@ -7,6 +7,7 @@ import noppes.npcs.api.handler.data.IActionQueue; import noppes.npcs.api.handler.data.actions.IConditionalAction; import noppes.npcs.controllers.ScriptContainer; import noppes.npcs.controllers.data.action.action.ConditionalAction; +import noppes.npcs.scripted.NpcAPI; import java.util.*; import java.util.function.Consumer; @@ -21,6 +22,8 @@ import java.util.function.Function; * - cancellation & clearing */ public class ActionManager implements IActionManager { + public static final ActionManager GLOBAL = new ActionManager("GLOBAL"); + protected boolean isWorking = false; public ActionLogger LOGGER = new ActionLogger(this); protected String name = ""; @@ -33,6 +36,19 @@ public class ActionManager implements IActionManager { protected boolean debug; protected ScriptContainer reportTo; + private static final Map listeners = new WeakHashMap<>(); + + public IActionListener getOrCreateListener(Object obj) { + return listeners.computeIfAbsent(obj, o -> new ActionListener(o)); + } + + public ActionManager() { + } + + public ActionManager(String name) { + this.name = name; + } + @Override public IActionManager start() { diff --git a/src/main/java/noppes/npcs/scripted/NpcAPI.java b/src/main/java/noppes/npcs/scripted/NpcAPI.java index 34dc85b54..984c929b9 100644 --- a/src/main/java/noppes/npcs/scripted/NpcAPI.java +++ b/src/main/java/noppes/npcs/scripted/NpcAPI.java @@ -79,7 +79,6 @@ public class NpcAPI extends AbstractNpcAPI { private static final CacheHashMap> scriptItemCache = new CacheHashMap<>(60 * 1000); public static final HashMap engineObjects = new HashMap<>(); public static final EventBus EVENT_BUS = new EventBus(); - public static final ActionManager actionManager = new ActionManager(); private static AbstractNpcAPI instance = null; private final static String API_USER_AGENT = "CNPC+API"; @@ -569,10 +568,7 @@ public class NpcAPI extends AbstractNpcAPI { } public IActionManager getActionManager() { - if (actionManager.getName().isEmpty()) - actionManager.setName("Global"); - - return actionManager; + return ActionManager.GLOBAL; } private void checkWorld() {