From 9322cd7429b87a4ac339f4546db69db6f7ebc976 Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Sat, 28 Jun 2025 09:30:21 +0300 Subject: [PATCH 01/12] Added ActionThread IActions can now be threaded using action.threadify() --- src/api | 2 +- .../npcs/controllers/data/action/Action.java | 48 ++++++++++--- .../controllers/data/action/ActionThread.java | 71 +++++++++++++++++++ 3 files changed, 111 insertions(+), 10 deletions(-) create mode 100644 src/main/java/noppes/npcs/controllers/data/action/ActionThread.java diff --git a/src/api b/src/api index bbbea878f..3efd012ae 160000 --- a/src/api +++ b/src/api @@ -1 +1 @@ -Subproject commit bbbea878fe30ea033112b0c5f1604417d4197447 +Subproject commit 3efd012ae0c465ff39ccfa85986ea966cc1bfa26 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 9bf4e745e..6b2eb6336 100644 --- a/src/main/java/noppes/npcs/controllers/data/action/Action.java +++ b/src/main/java/noppes/npcs/controllers/data/action/Action.java @@ -16,8 +16,10 @@ public class Action implements IAction { protected int maxDuration = -1; protected int updateEveryXTick = 5; protected Consumer task; - private boolean done; - private final Map dataStore = new HashMap<>(); + protected boolean done; + protected final Map dataStore = new HashMap<>(); + protected boolean isThreaded; + protected ActionThread threaded; public Action(ScriptedActionManager manager, String name) { this.manager = manager; @@ -68,13 +70,17 @@ public class Action implements IAction { return; } if (ticksExisted % updateEveryXTick == 0 && task != null) { - try { - task.accept(this); - count++; - } catch (Throwable t) { - System.err.println("Scripted action '" + name + "' threw an exception:"); - t.printStackTrace(); - markDone(); + if (isThreaded) + threaded.run(); + else { + try { + task.accept(this); + count++; + } catch (Throwable t) { + System.err.println("Scripted action '" + name + "' threw an exception:"); + t.printStackTrace(); + markDone(); + } } } duration++; @@ -161,10 +167,34 @@ public class Action implements IAction { @Override public IAction pauseFor(int ticks) { + if (isThreaded) + return threaded.pauseFor(ticks); + this.startAfterTicks = ticks; return this; } + @Override + public IAction pauseFor(long millis) { + if (isThreaded) + return threaded.pauseFor(millis); + + return pauseFor((int) (millis / 50)); + } + + @Override + public boolean isPaused() { + if (isThreaded) + return threaded.isPaused(); + + return startAfterTicks > 0; + } + + @Override + public void threadify() { + isThreaded = true; + threaded = new ActionThread(this); + } @Override public IAction getNext() { boolean seenMe = false; diff --git a/src/main/java/noppes/npcs/controllers/data/action/ActionThread.java b/src/main/java/noppes/npcs/controllers/data/action/ActionThread.java new file mode 100644 index 000000000..c0009d940 --- /dev/null +++ b/src/main/java/noppes/npcs/controllers/data/action/ActionThread.java @@ -0,0 +1,71 @@ +package noppes.npcs.controllers.data.action; + +import noppes.npcs.api.handler.data.IAction; + +public class ActionThread { + private Action action; + private Thread thread; + private volatile boolean threadPaused; + private boolean threadRunning; + + public ActionThread(Action action) { + this.action = action; + createThread(); + } + + private void createThread() { + thread = new Thread(() -> { + threadRunning = true; + action.task.accept(action); + threadRunning = false; + action.count++; + }); + } + + public IAction pauseFor(long millis) { + if (Thread.currentThread() == thread) { + try { + threadPaused = true; + Thread.sleep(millis); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } finally { + threadPaused = false; + return action; + } + } else + return action.pauseFor((int) (millis / 50)); + } + + public IAction pauseFor(int ticks) { + if (Thread.currentThread() == thread) { + try { + threadPaused = true; + Thread.sleep(ticks * 50); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } finally { + threadPaused = false; + return action; + } + } else + return action.pauseFor(ticks); + } + + public boolean isPaused() { + return threadPaused; + } + + public void run() { + if (threadRunning) + return; + + try { + thread.start(); + } catch (Throwable t) { + System.err.println("Scripted threaded action '" + action.name + "' threw an exception:"); + t.printStackTrace(); + action.markDone(); + } + } +} From 6de09c1ee430435efe9d372e05f20a5e10a32c44 Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Sat, 28 Jun 2025 09:38:38 +0300 Subject: [PATCH 02/12] Added player's ActionManager getter to API --- src/main/java/noppes/npcs/scripted/entity/ScriptPlayer.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/noppes/npcs/scripted/entity/ScriptPlayer.java b/src/main/java/noppes/npcs/scripted/entity/ScriptPlayer.java index fb3d3d9ab..93b7aa6e7 100644 --- a/src/main/java/noppes/npcs/scripted/entity/ScriptPlayer.java +++ b/src/main/java/noppes/npcs/scripted/entity/ScriptPlayer.java @@ -27,6 +27,7 @@ import noppes.npcs.api.*; import noppes.npcs.api.entity.IEntity; import noppes.npcs.api.entity.IPlayer; import noppes.npcs.api.gui.ICustomGui; +import noppes.npcs.api.handler.IActionManager; import noppes.npcs.api.handler.IOverlayHandler; import noppes.npcs.api.handler.data.*; import noppes.npcs.api.item.IItemStack; @@ -846,4 +847,9 @@ public class ScriptPlayer extends ScriptLivingBase public IPlayerAttributes getAttributes() { return AttributeController.getTracker(this.player); } + + @Override + public IActionManager getActionManager() { + return data.actionManager; + } } From e001beb6bae2f4a7371e42d0958d9c9e0f77a16a Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Sat, 28 Jun 2025 10:06:14 +0300 Subject: [PATCH 03/12] Added global API.getActionManager() --- src/api | 2 +- src/main/java/noppes/npcs/ServerTickHandler.java | 11 ++++++++++- src/main/java/noppes/npcs/scripted/NpcAPI.java | 5 +++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/api b/src/api index 3efd012ae..f074267f7 160000 --- a/src/api +++ b/src/api @@ -1 +1 @@ -Subproject commit 3efd012ae0c465ff39ccfa85986ea966cc1bfa26 +Subproject commit f074267f73cd3c8480efe354af7b3d8c63480d90 diff --git a/src/main/java/noppes/npcs/ServerTickHandler.java b/src/main/java/noppes/npcs/ServerTickHandler.java index c73874df5..ecfdce50a 100644 --- a/src/main/java/noppes/npcs/ServerTickHandler.java +++ b/src/main/java/noppes/npcs/ServerTickHandler.java @@ -11,13 +11,22 @@ 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 java.net.InetAddress; import java.net.UnknownHostException; public class ServerTickHandler { + @SubscribeEvent - public void onServerTick(TickEvent.WorldTickEvent event) { + public void onServerTick(TickEvent.ServerTickEvent event) { + if (event.phase == Phase.END) { + NpcAPI.actionManager.tick(MinecraftServer.getServer().getTickCounter()); + } + } + + @SubscribeEvent + public void onWorldTick(TickEvent.WorldTickEvent event) { if (event.phase == Phase.START) { NPCSpawning.findChunksForSpawning((WorldServer) event.world); } diff --git a/src/main/java/noppes/npcs/scripted/NpcAPI.java b/src/main/java/noppes/npcs/scripted/NpcAPI.java index 54d86963d..a514f8508 100644 --- a/src/main/java/noppes/npcs/scripted/NpcAPI.java +++ b/src/main/java/noppes/npcs/scripted/NpcAPI.java @@ -79,6 +79,7 @@ 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 ScriptedActionManager actionManager = new ScriptedActionManager(); private static AbstractNpcAPI instance = null; private final static String API_USER_AGENT = "CNPC+API"; @@ -559,6 +560,10 @@ public class NpcAPI extends AbstractNpcAPI { return container instanceof ContainerNpcInterface ? ContainerNpcInterface.getOrCreateIContainer((ContainerNpcInterface) container) : new ScriptContainer(container); } + public IActionManager getActionManager() { + return actionManager; + } + private void checkWorld() { if (CustomNpcs.getServer() == null || CustomNpcs.getServer().isServerStopped()) { throw new CustomNPCsException("No world is loaded right now"); From 70cc7b75e48a1931d8f4d6bbfe847707ac530d3e Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Sat, 28 Jun 2025 19:07:19 +0300 Subject: [PATCH 04/12] More important ActionThread pausing frameworks and documentation --- .../npcs/controllers/data/action/Action.java | 45 ++++++++-- .../controllers/data/action/ActionThread.java | 82 +++++++++++++------ 2 files changed, 97 insertions(+), 30 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 6b2eb6336..f61ddb6cd 100644 --- a/src/main/java/noppes/npcs/controllers/data/action/Action.java +++ b/src/main/java/noppes/npcs/controllers/data/action/Action.java @@ -1,11 +1,13 @@ package noppes.npcs.controllers.data.action; import noppes.npcs.api.handler.data.IAction; +import noppes.npcs.scripted.CustomNPCsException; import noppes.npcs.scripted.ScriptedActionManager; import java.util.HashMap; import java.util.Map; import java.util.function.Consumer; +import java.util.function.Supplier; public class Action implements IAction { protected final ScriptedActionManager manager; @@ -168,20 +170,45 @@ public class Action implements IAction { @Override public IAction pauseFor(int ticks) { if (isThreaded) - return threaded.pauseFor(ticks); + threaded.pauseFor(ticks); + else + this.startAfterTicks = ticks; - this.startAfterTicks = ticks; return this; } @Override public IAction pauseFor(long millis) { - if (isThreaded) - return threaded.pauseFor(millis); + if (isThreaded) { + threaded.pauseFor(millis); + return this; + } return pauseFor((int) (millis / 50)); } + @Override + public void pause() { + if (isThreaded) + threaded.pause(); + else + throw new CustomNPCsException("Must threadify() IAction before pausing!"); + } + + @Override + public void pauseUntil(Supplier until) { + if (isThreaded) + threaded.pauseUntil(until); + else + throw new CustomNPCsException("Must threadify() IAction before pausing!"); + } + + @Override + public void resume() { + if (isThreaded) + threaded.resume(); + } + @Override public boolean isPaused() { if (isThreaded) @@ -191,9 +218,13 @@ public class Action implements IAction { } @Override - public void threadify() { - isThreaded = true; - threaded = new ActionThread(this); + public IAction threadify() { + if (!isThreaded) { + isThreaded = true; + threaded = new ActionThread(this); + } + + return this; } @Override public IAction getNext() { 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 c0009d940..6effa1310 100644 --- a/src/main/java/noppes/npcs/controllers/data/action/ActionThread.java +++ b/src/main/java/noppes/npcs/controllers/data/action/ActionThread.java @@ -1,13 +1,17 @@ package noppes.npcs.controllers.data.action; -import noppes.npcs.api.handler.data.IAction; +import java.util.function.Supplier; public class ActionThread { - private Action action; + private final Action action; + + private final Object lock = new Object(); private Thread thread; - private volatile boolean threadPaused; + private volatile boolean threadPaused, threadSleeping; private boolean threadRunning; + private Supplier pauseUntil; + public ActionThread(Action action) { this.action = action; createThread(); @@ -22,41 +26,73 @@ public class ActionThread { }); } - public IAction pauseFor(long millis) { - if (Thread.currentThread() == thread) { + + public void pauseFor(long millis) { + if (isPaused()) + return; + + if (inActionThread()) { try { - threadPaused = true; + threadSleeping = true; Thread.sleep(millis); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { - threadPaused = false; - return action; + threadSleeping = false; } } else - return action.pauseFor((int) (millis / 50)); + action.pauseFor((int) (millis / 50)); } - public IAction pauseFor(int ticks) { - if (Thread.currentThread() == thread) { - try { - threadPaused = true; - Thread.sleep(ticks * 50); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } finally { - threadPaused = false; - return action; + public void pauseFor(int ticks) { + pauseFor(ticks * 50L); + } + + public void pause() { + if (!inActionThread() || isPaused()) + return; + + threadPaused = true; + synchronized (lock) { + while (threadPaused) { + try { + lock.wait(); // Wait until notified + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } } - } else - return action.pauseFor(ticks); + } + } + + public void pauseUntil(Supplier until) { + this.pauseUntil = until; + pause(); + } + + public void resume() { + synchronized (lock) { + if (threadPaused) { + threadPaused = false; + lock.notify(); + } + + if (threadSleeping) + thread.interrupt(); + } } public boolean isPaused() { - return threadPaused; + return threadPaused || threadSleeping; } - public void run() { + public boolean inActionThread() { + return Thread.currentThread() == thread; + } + + protected void run() { + if (threadPaused && pauseUntil != null && pauseUntil.get()) + resume(); + if (threadRunning) return; From 203a7949505623c332e0bd426427b9987244bd0f Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Sat, 28 Jun 2025 19:07:37 +0300 Subject: [PATCH 05/12] ActionManager.getAction(name) --- src/api | 2 +- .../npcs/scripted/ScriptedActionManager.java | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/api b/src/api index f074267f7..8ad0c21ef 160000 --- a/src/api +++ b/src/api @@ -1 +1 @@ -Subproject commit f074267f73cd3c8480efe354af7b3d8c63480d90 +Subproject commit 8ad0c21ef4a368755208f7341ce130ace9586877 diff --git a/src/main/java/noppes/npcs/scripted/ScriptedActionManager.java b/src/main/java/noppes/npcs/scripted/ScriptedActionManager.java index 9d62fffac..f76fcbc0d 100644 --- a/src/main/java/noppes/npcs/scripted/ScriptedActionManager.java +++ b/src/main/java/noppes/npcs/scripted/ScriptedActionManager.java @@ -141,6 +141,26 @@ public class ScriptedActionManager implements IActionManager { return actionQueue.peekFirst(); } + @Override + public IAction getAction(String name) { + for (IAction action : actionQueue) { + if (action.getName().equals(name)) + return action; + } + + for (IAction action : parallelActions) { + if (action.getName().equals(name)) + return action; + } + + for (IAction action : conditionalActions) { + if (action.getName().equals(name)) + return action; + } + + return null; + } + @Override public Queue getActionQueue() { return actionQueue; From dd4b0c8b4b739f8c368da73736438bc7b2d9457a Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Sat, 28 Jun 2025 19:10:15 +0300 Subject: [PATCH 06/12] ActionManager no longer cleared on entity's death/reset --- src/main/java/noppes/npcs/ScriptPlayerEventHandler.java | 2 +- src/main/java/noppes/npcs/entity/EntityNPCInterface.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/noppes/npcs/ScriptPlayerEventHandler.java b/src/main/java/noppes/npcs/ScriptPlayerEventHandler.java index 8f8ffbb2f..26b638ac6 100644 --- a/src/main/java/noppes/npcs/ScriptPlayerEventHandler.java +++ b/src/main/java/noppes/npcs/ScriptPlayerEventHandler.java @@ -496,7 +496,7 @@ public class ScriptPlayerEventHandler { EntityPlayer player = (EntityPlayer) event.entityLiving; PlayerData playerData = PlayerData.get(player); - playerData.actionManager.clear(); + // playerData.actionManager.clear(); } if (event.source.getEntity() instanceof EntityPlayerMP) { diff --git a/src/main/java/noppes/npcs/entity/EntityNPCInterface.java b/src/main/java/noppes/npcs/entity/EntityNPCInterface.java index c79354347..6ff6961f0 100644 --- a/src/main/java/noppes/npcs/entity/EntityNPCInterface.java +++ b/src/main/java/noppes/npcs/entity/EntityNPCInterface.java @@ -1168,7 +1168,7 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti setHealth(getMaxHealth()); dataWatcher.updateObject(14, 0); // animation Normal dataWatcher.updateObject(15, 0); - actionManager.clear(); + // actionManager.clear(); combatHandler.reset(); this.setAttackTarget(null); this.setRevengeTarget(null); From 8ee35e8088a8bdeb79609200747010839e61b1a7 Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Sun, 29 Jun 2025 09:07:09 +0300 Subject: [PATCH 07/12] IActionManager and IAction QoL --- .../noppes/npcs/controllers/data/action/Action.java | 11 +++++++++-- .../noppes/npcs/scripted/ScriptedActionManager.java | 9 +++++++++ 2 files changed, 18 insertions(+), 2 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 f61ddb6cd..20244d56a 100644 --- a/src/main/java/noppes/npcs/controllers/data/action/Action.java +++ b/src/main/java/noppes/npcs/controllers/data/action/Action.java @@ -115,7 +115,7 @@ public class Action implements IAction { @Override public IAction setMaxDuration(int x) { - this.maxDuration = x; + this.maxDuration = Math.max(-1, x); return this; } @@ -158,7 +158,7 @@ public class Action implements IAction { @Override public IAction setUpdateEveryXTick(int x) { - this.updateEveryXTick = x; + this.updateEveryXTick = Math.max(1, x); return this; } @@ -226,6 +226,13 @@ public class Action implements IAction { return this; } + + @Override + public IAction start() { + manager.start(); + return this; + } + @Override public IAction getNext() { boolean seenMe = false; diff --git a/src/main/java/noppes/npcs/scripted/ScriptedActionManager.java b/src/main/java/noppes/npcs/scripted/ScriptedActionManager.java index f76fcbc0d..9d17e3b30 100644 --- a/src/main/java/noppes/npcs/scripted/ScriptedActionManager.java +++ b/src/main/java/noppes/npcs/scripted/ScriptedActionManager.java @@ -105,6 +105,15 @@ public class ScriptedActionManager implements IActionManager { return action; } + @Override + public IAction scheduleAction(String name, Consumer task) { + return scheduleAction(create(name, task)); + } + @Override + public IAction scheduleAction(String name, int startAfterTicks, Consumer task) { + return scheduleAction(create(name, startAfterTicks, task)); + } + @Override public IAction scheduleAction(String name, int maxDuration, int startAfterTicks, Consumer task) { return scheduleAction(create(name, maxDuration, startAfterTicks, task)); From fa9e5cdfe55c50db4d9ac2bc92ac1e528da160f5 Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Sun, 29 Jun 2025 09:44:20 +0300 Subject: [PATCH 08/12] More IActionManager and IAction QoL !!! --- src/api | 2 +- .../npcs/controllers/data/action/Action.java | 4 ++ .../npcs/scripted/ScriptedActionManager.java | 60 +++++++++++++++++-- 3 files changed, 61 insertions(+), 5 deletions(-) diff --git a/src/api b/src/api index 8ad0c21ef..50f30f367 160000 --- a/src/api +++ b/src/api @@ -1 +1 @@ -Subproject commit 8ad0c21ef4a368755208f7341ce130ace9586877 +Subproject commit 50f30f3678970011fcc7d4bdd8928fabc2f84ea0 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 20244d56a..9a28ed23e 100644 --- a/src/main/java/noppes/npcs/controllers/data/action/Action.java +++ b/src/main/java/noppes/npcs/controllers/data/action/Action.java @@ -129,6 +129,10 @@ public class Action implements IAction { return done; } + public void kill() { + + } + @Override public Object getData(String key) { return dataStore.get(key); diff --git a/src/main/java/noppes/npcs/scripted/ScriptedActionManager.java b/src/main/java/noppes/npcs/scripted/ScriptedActionManager.java index 9d17e3b30..dea0797b4 100644 --- a/src/main/java/noppes/npcs/scripted/ScriptedActionManager.java +++ b/src/main/java/noppes/npcs/scripted/ScriptedActionManager.java @@ -106,7 +106,7 @@ public class ScriptedActionManager implements IActionManager { } @Override - public IAction scheduleAction(String name, Consumer task) { + public IAction scheduleAction(String name, Consumer task) { return scheduleAction(create(name, task)); } @Override @@ -175,6 +175,26 @@ public class ScriptedActionManager implements IActionManager { return actionQueue; } + @Override + public boolean hasAction(String name) { + for (IAction act : actionQueue) + if (act.getName().equals(name)) + return true; + + return false; + } + @Override + public boolean hasAny(String name) { + if (hasAction(name)) + return true; + else if (hasParallel(name)) + return true; + else if (hasConditional(name)) + return true; + + return false; + } + @Override public void clear() { actionQueue.clear(); @@ -242,6 +262,15 @@ public class ScriptedActionManager implements IActionManager { return new ArrayList<>(conditionalActions); } + @Override + public boolean hasConditional(String name) { + for (IAction act : conditionalActions) + if (act.getName().equals(name)) + return true; + + return false; + } + @Override public IAction scheduleParallelAction(IAction action) { parallelActions.add(action); @@ -262,7 +291,10 @@ public class ScriptedActionManager implements IActionManager { if (current instanceof Action) { Action cab = (Action) current; cab.tick(ticksExisted); - if (cab.isDone()) actionQueue.pollFirst(); + if (cab.isDone()) { + cab.kill(); + actionQueue.pollFirst(); + } } // ─── Parallel (all) ─────────────────────────────────────── @@ -270,7 +302,10 @@ public class ScriptedActionManager implements IActionManager { while (pit.hasNext()) { Action a = (Action) pit.next(); a.tick(ticksExisted); - if (a.isDone()) pit.remove(); + if (a.isDone()) { + a.kill(); + pit.remove(); + } } // ─── Conditionals ───────────────────────────────────────── @@ -278,7 +313,10 @@ public class ScriptedActionManager implements IActionManager { while (cit.hasNext()) { ConditionalAction con = (ConditionalAction) cit.next(); con.tick(ticksExisted); - if (con.isDone()) cit.remove(); + if (con.isDone()) { + con.kill(); + cit.remove(); + } } } @@ -291,4 +329,18 @@ public class ScriptedActionManager implements IActionManager { public IActionChain parallelChain() { return new ParallelActionChain(this); } + + @Override + public Queue getParallelActions() { + return parallelActions; + } + + @Override + public boolean hasParallel(String name) { + for (IAction act : parallelActions) + if (act.getName().equals(name)) + return true; + + return false; + } } From e03af5e76f2d73db0c9238af86d114c1bca26209 Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Sun, 29 Jun 2025 09:47:07 +0300 Subject: [PATCH 09/12] Vastly improved ActionThread --- .../npcs/controllers/data/action/Action.java | 3 +- .../controllers/data/action/ActionThread.java | 82 +++++++++++-------- 2 files changed, 49 insertions(+), 36 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 9a28ed23e..121f6484c 100644 --- a/src/main/java/noppes/npcs/controllers/data/action/Action.java +++ b/src/main/java/noppes/npcs/controllers/data/action/Action.java @@ -130,7 +130,8 @@ public class Action implements IAction { } public void kill() { - + if (threaded != null) + threaded.stop(); } @Override 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 6effa1310..e00607e76 100644 --- a/src/main/java/noppes/npcs/controllers/data/action/ActionThread.java +++ b/src/main/java/noppes/npcs/controllers/data/action/ActionThread.java @@ -1,5 +1,8 @@ package noppes.npcs.controllers.data.action; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; import java.util.function.Supplier; public class ActionThread { @@ -7,41 +10,41 @@ public class ActionThread { private final Object lock = new Object(); private Thread thread; + ExecutorService executor; + private Future currentExecution; private volatile boolean threadPaused, threadSleeping; - private boolean threadRunning; private Supplier pauseUntil; public ActionThread(Action action) { this.action = action; - createThread(); - } - private void createThread() { - thread = new Thread(() -> { - threadRunning = true; - action.task.accept(action); - threadRunning = false; - action.count++; + executor = Executors.newSingleThreadExecutor(r -> { + thread = new Thread(r); + thread.setName(String.format("ActionThread (%s)", action.getName())); + return thread; }); } + public void stop() { + if (isThreadRunning()) + currentExecution.cancel(true); + + executor.shutdown(); + } public void pauseFor(long millis) { - if (isPaused()) + if (isPaused() || !inActionThread()) return; - if (inActionThread()) { - try { - threadSleeping = true; - Thread.sleep(millis); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } finally { - threadSleeping = false; - } - } else - action.pauseFor((int) (millis / 50)); + try { + threadSleeping = true; + Thread.sleep(millis); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } finally { + threadSleeping = false; + } } public void pauseFor(int ticks) { @@ -76,32 +79,41 @@ public class ActionThread { lock.notify(); } - if (threadSleeping) - thread.interrupt(); + if (threadSleeping && currentExecution != null) + currentExecution.cancel(true); } } - public boolean isPaused() { - return threadPaused || threadSleeping; - } - public boolean inActionThread() { return Thread.currentThread() == thread; } + public boolean isPaused() { + return threadPaused || threadSleeping; + } + + public boolean isThreadRunning() { + return currentExecution != null && !currentExecution.isDone(); + } + + protected void run() { if (threadPaused && pauseUntil != null && pauseUntil.get()) resume(); - if (threadRunning) + if (isThreadRunning()) return; - try { - thread.start(); - } catch (Throwable t) { - System.err.println("Scripted threaded action '" + action.name + "' threw an exception:"); - t.printStackTrace(); - action.markDone(); - } + currentExecution = executor.submit(() -> { + try { + action.task.accept(action); + action.count++; + } catch (Throwable t) { + System.err.println("Scripted threaded action '" + action.name + "' threw an exception:"); + t.printStackTrace(); + action.markDone(); + } + }); + } } From 213c9069de083c9d36b35f09fdf4089f91918eaf Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Sun, 29 Jun 2025 09:55:14 +0300 Subject: [PATCH 10/12] Parallel IAction schedulers --- .../noppes/npcs/scripted/ScriptedActionManager.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/java/noppes/npcs/scripted/ScriptedActionManager.java b/src/main/java/noppes/npcs/scripted/ScriptedActionManager.java index dea0797b4..1b6fd82eb 100644 --- a/src/main/java/noppes/npcs/scripted/ScriptedActionManager.java +++ b/src/main/java/noppes/npcs/scripted/ScriptedActionManager.java @@ -276,6 +276,19 @@ public class ScriptedActionManager implements IActionManager { parallelActions.add(action); return action; } + @Override + public IAction scheduleParallelAction(String name, Consumer task) { + return scheduleParallelAction(create(name, task)); + } + @Override + public IAction scheduleParallelAction(String name, int startAfterTicks, Consumer task) { + return scheduleParallelAction(create(name, startAfterTicks, task)); + } + + @Override + public IAction scheduleParallelAction(String name, int maxDuration, int startAfterTicks, Consumer task) { + return scheduleParallelAction(create(name, maxDuration, startAfterTicks, task)); + } /** From 6bb174102571449ea854b9445c4478f59b7b96bb Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Sun, 29 Jun 2025 11:04:14 +0300 Subject: [PATCH 11/12] Parallel IAction chain methods --- src/api | 2 +- .../npcs/controllers/data/action/Action.java | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/api b/src/api index 50f30f367..65c81997b 160000 --- a/src/api +++ b/src/api @@ -1 +1 @@ -Subproject commit 50f30f3678970011fcc7d4bdd8928fabc2f84ea0 +Subproject commit 65c81997b9d552d39ed1005975f9e9824eebccf6 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 121f6484c..39affcd26 100644 --- a/src/main/java/noppes/npcs/controllers/data/action/Action.java +++ b/src/main/java/noppes/npcs/controllers/data/action/Action.java @@ -264,6 +264,32 @@ public class Action implements IAction { return null; } + @Override + public IAction parallel(IAction after) { + return manager.scheduleParallelAction(after); + } + + @Override + public IAction parallel(Consumer task) { + return manager.scheduleParallelAction(manager.create(task)); + } + + @Override + public IAction parallel(int delay, Consumer task) { + return manager.scheduleParallelAction(manager.create(delay, task)); + } + + @Override + public IAction parallel(String name, Consumer task) { + return manager.scheduleParallelAction(manager.create(name, task)); + } + + @Override + public IAction parallel(String name, int startAfterTicks, Consumer task) { + return manager.scheduleParallelAction(manager.create(name, startAfterTicks, task)); + } + + @Override public IAction after(IAction after) { int idx = manager.getIndex(this); From 5994206abd41204e79581a2a56e3db97de0ca34b Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Sun, 29 Jun 2025 11:22:43 +0300 Subject: [PATCH 12/12] More schedulers and overloading methods !!!! --- .../npcs/scripted/ScriptedActionManager.java | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/main/java/noppes/npcs/scripted/ScriptedActionManager.java b/src/main/java/noppes/npcs/scripted/ScriptedActionManager.java index 1b6fd82eb..cf9f95bc0 100644 --- a/src/main/java/noppes/npcs/scripted/ScriptedActionManager.java +++ b/src/main/java/noppes/npcs/scripted/ScriptedActionManager.java @@ -40,8 +40,8 @@ public class ScriptedActionManager implements IActionManager { } @Override - public IAction create(String name, int maxDuration, int startAfterTicks, Consumer task) { - return new Action(this, name, maxDuration, startAfterTicks, task); + public IAction create(String name, int maxDuration, int delay, Consumer task) { + return new Action(this, name, maxDuration, delay, task); } @Override @@ -105,18 +105,28 @@ public class ScriptedActionManager implements IActionManager { return action; } + @Override + public IAction scheduleAction(Consumer task) { + return scheduleAction(create(task)); + } + + @Override + public IAction scheduleAction(int delay, Consumer task) { + return scheduleAction(create(delay, task)); + } + @Override public IAction scheduleAction(String name, Consumer task) { return scheduleAction(create(name, task)); } @Override - public IAction scheduleAction(String name, int startAfterTicks, Consumer task) { - return scheduleAction(create(name, startAfterTicks, task)); + public IAction scheduleAction(String name, int delay, Consumer task) { + return scheduleAction(create(name, delay, task)); } @Override - public IAction scheduleAction(String name, int maxDuration, int startAfterTicks, Consumer task) { - return scheduleAction(create(name, maxDuration, startAfterTicks, task)); + public IAction scheduleAction(String name, int maxDuration, int delay, Consumer task) { + return scheduleAction(create(name, maxDuration, delay, task)); } @Override @@ -281,13 +291,13 @@ public class ScriptedActionManager implements IActionManager { return scheduleParallelAction(create(name, task)); } @Override - public IAction scheduleParallelAction(String name, int startAfterTicks, Consumer task) { - return scheduleParallelAction(create(name, startAfterTicks, task)); + public IAction scheduleParallelAction(String name, int delay, Consumer task) { + return scheduleParallelAction(create(name, delay, task)); } @Override - public IAction scheduleParallelAction(String name, int maxDuration, int startAfterTicks, Consumer task) { - return scheduleParallelAction(create(name, maxDuration, startAfterTicks, task)); + public IAction scheduleParallelAction(String name, int maxDuration, int delay, Consumer task) { + return scheduleParallelAction(create(name, maxDuration, delay, task)); }