From 994cadfc3bc0aeb4e700f0ab234a9a3c6a736661 Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Tue, 8 Jul 2025 21:31:55 +0300 Subject: [PATCH] IActionListener W.I.P --- .../npcs/controllers/data/action/Action.java | 18 ++++ .../data/action/ActionListener.java | 90 +++++++++++++++++++ .../data/action/ActionManager.java | 43 +++++++-- 3 files changed, 143 insertions(+), 8 deletions(-) create mode 100644 src/main/java/noppes/npcs/controllers/data/action/ActionListener.java 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 76df3d8e6..852e43ee4 100644 --- a/src/main/java/noppes/npcs/controllers/data/action/Action.java +++ b/src/main/java/noppes/npcs/controllers/data/action/Action.java @@ -2,6 +2,7 @@ package noppes.npcs.controllers.data.action; import noppes.npcs.api.handler.IActionManager; import noppes.npcs.api.handler.data.IAction; +import noppes.npcs.api.handler.data.IActionListener; import noppes.npcs.api.handler.data.IActionQueue; import noppes.npcs.api.handler.data.actions.IConditionalAction; import noppes.npcs.controllers.ScriptContainer; @@ -257,6 +258,23 @@ public class Action implements IAction { return done; } + /////////////////////////////////////////////////// + ////////////////////////////////////////////////// + // Listener + + public IAction listenTo(String hook, Object object) { + return listenTo(hook, manager.getOrCreateListener(object)); + } + + public IAction listenTo(String hook, IActionListener listener) { + return listenTo(listener.getOrCreateHook(hook)); + } + + public IAction listenTo(ActionListener.Hook hook) { + hook.schedule(this); + return this; + } + /////////////////////////////////////////////////// ////////////////////////////////////////////////// // Handling diff --git a/src/main/java/noppes/npcs/controllers/data/action/ActionListener.java b/src/main/java/noppes/npcs/controllers/data/action/ActionListener.java new file mode 100644 index 000000000..5ff0d72db --- /dev/null +++ b/src/main/java/noppes/npcs/controllers/data/action/ActionListener.java @@ -0,0 +1,90 @@ +package noppes.npcs.controllers.data.action; + +import noppes.npcs.api.handler.data.IAction; +import noppes.npcs.api.handler.data.IActionListener; +import noppes.npcs.api.handler.data.IActionQueue; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +public class ActionListener implements IActionListener { + private static final ActionManager manager = ActionManager.GLOBAL; + + private final Object object; //object listener is attached to + private final Map hooks = new ConcurrentHashMap<>(); + + public ActionListener(Object target) { + this.object = target; + } + + public void tick() { + Iterator> it = hooks.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry entry = it.next(); + Hook hook = entry.getValue(); + ActionQueue hookQueue = (ActionQueue) hook.queue; + hookQueue.tick(); + + if (hookQueue.isDead()) { + hookQueue.clear(); + if (manager.debug) + manager.LOGGER.log(String.format("Removing queue '%s'", hookQueue.getName()), manager); + it.remove(); + } + } + } + + public Object getObject() { + return object; + } + + @Override + public Hook getOrCreateHook(String hookName) { + return hooks.computeIfAbsent(hookName, Hook::new); + } + + @Override + public Hook getHook(String hookName) { + return hooks.get(hookName); + } + + @Override + public boolean fire(String hookName) { + Hook hook = hooks.get(hookName); + if (hook != null) { + hook.fire(); + return true; + } + + return false; + } + + public IAction schedule(String hookName, IAction action) { + return getOrCreateHook(hookName).schedule(action); + } + + public class Hook { + public final String name; + public final IActionQueue queue; + + public Hook(String hookName) { + this.name = hookName; + + String queueName = String.format("ActionListener#%s:%s", object, hookName); + this.queue = manager.createQueue(queueName).stopWhenEmpty(true).killWhenEmpty(false); + } + + public String getName() { + return name; + } + + public void fire() { + queue.getManager().start(); // just in case, ensures the manager is ticking + queue.start(); + } + + public IAction schedule(IAction action) { + return queue.schedule(action); + } + } +} 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 01173b4ce..e8405c033 100644 --- a/src/main/java/noppes/npcs/controllers/data/action/ActionManager.java +++ b/src/main/java/noppes/npcs/controllers/data/action/ActionManager.java @@ -3,13 +3,14 @@ package noppes.npcs.controllers.data.action; import noppes.npcs.api.handler.IActionManager; import noppes.npcs.api.handler.data.IAction; import noppes.npcs.api.handler.data.IActionChain; +import noppes.npcs.api.handler.data.IActionListener; 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.concurrent.ConcurrentHashMap; import java.util.function.Consumer; import java.util.function.Function; @@ -23,6 +24,7 @@ import java.util.function.Function; */ public class ActionManager implements IActionManager { public static final ActionManager GLOBAL = new ActionManager("GLOBAL"); + private static final Map listeners = new ConcurrentHashMap<>(); protected boolean isWorking = false; public ActionLogger LOGGER = new ActionLogger(this); @@ -36,12 +38,6 @@ 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() { } @@ -73,7 +69,6 @@ public class ActionManager implements IActionManager { return this; } - @Override public boolean inDebugMode() { return debug; @@ -88,6 +83,34 @@ public class ActionManager implements IActionManager { return this; } + /////////////////////////////////////////////////// + /////////////////////////////////////////////////// + // Listeners + + public IActionListener getOrCreateListener(Object obj) { + return listeners.computeIfAbsent(obj, o -> new ActionListener(o)); + } + + public IActionListener getListener(Object obj) { + return listeners.get(obj); + } + + public boolean removeListener(Object obj) { + if (listeners.containsKey(obj)) { + listeners.remove(obj); + return true; + } + + return false; + } + + public boolean fireListener(String hookName, Object obj) { + IActionListener listener = getListener(obj); + if (listener != null) + return listener.fire(hookName); + + return false; + } /////////////////////////////////////////////////// /////////////////////////////////////////////////// // Creators @@ -472,6 +495,10 @@ public class ActionManager implements IActionManager { it.remove(); } } + // ─── All Listeners ───────────────────────────────────────── + if (this == GLOBAL) { + listeners.forEach((obj, listener) -> ((ActionListener) listener).tick()); + } if (debug && active) LOGGER.finish("Finished Tick Cycle",this);