From 75a1c7c851d70b109be904394d0ca0301e76cf01 Mon Sep 17 00:00:00 2001 From: Kam Date: Mon, 28 Apr 2025 03:05:56 -0400 Subject: [PATCH] Parallel Action Chains --- build.gradle | 2 +- src/api | 2 +- .../npcs/scripted/ScriptedActionManager.java | 71 ++++++++++++++++--- 3 files changed, 63 insertions(+), 12 deletions(-) diff --git a/build.gradle b/build.gradle index cfb32693b..c844354bc 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ plugins { id 'idea' } -version = "1.10-testingbeta18.1" +version = "1.10-testingbeta18.2" group= "kamkeel.customnpc-plus" archivesBaseName = "CustomNPC-Plus" diff --git a/src/api b/src/api index 0bbb00f1e..656a7f756 160000 --- a/src/api +++ b/src/api @@ -1 +1 @@ -Subproject commit 0bbb00f1e1c61dc69e207c9aa22bf9b86a7d3f32 +Subproject commit 656a7f75636c367ea7a3eaeee36eb0f50524cbe4 diff --git a/src/main/java/noppes/npcs/scripted/ScriptedActionManager.java b/src/main/java/noppes/npcs/scripted/ScriptedActionManager.java index 60ed59925..c94ebef5a 100644 --- a/src/main/java/noppes/npcs/scripted/ScriptedActionManager.java +++ b/src/main/java/noppes/npcs/scripted/ScriptedActionManager.java @@ -19,7 +19,9 @@ import java.util.function.Supplier; */ public class ScriptedActionManager implements IActionManager { private boolean isWorking = false; + private final Deque actionQueue = new LinkedList<>(); + private final List parallelActions = new LinkedList<>(); private final List conditionalActions = new LinkedList<>(); @Override @@ -118,6 +120,7 @@ public class ScriptedActionManager implements IActionManager { @Override public void clear() { actionQueue.clear(); + parallelActions.clear(); conditionalActions.clear(); } @@ -132,6 +135,14 @@ public class ScriptedActionManager implements IActionManager { } } + Iterator pit = parallelActions.iterator(); + while (pit.hasNext()) { + if (pit.next().getName().equals(name)) { + pit.remove(); + return true; + } + } + Iterator cons = conditionalActions.iterator(); while (cons.hasNext()) { IConditionalAction con = cons.next(); @@ -167,6 +178,13 @@ public class ScriptedActionManager implements IActionManager { return conditionalActions; } + @Override + public IAction scheduleParallelAction(IAction action) { + parallelActions.add(action); + return action; + } + + /** * Call once per tick from your main loop. * @@ -174,22 +192,30 @@ public class ScriptedActionManager implements IActionManager { */ public void tick(int ticksExisted) { if (!isWorking) return; + + // ─── Sequential (head only) ───────────────────────────────── IAction current = getCurrentAction(); if (current instanceof ActionBase) { ActionBase cab = (ActionBase) current; cab.tick(ticksExisted); - if (cab.isDone()) - actionQueue.pollFirst(); + if (cab.isDone()) actionQueue.pollFirst(); } - Iterator it = conditionalActions.iterator(); - while (it.hasNext()) { - ConditionalAction con = (ConditionalAction) it.next(); + // ─── Parallel (all) ─────────────────────────────────────── + Iterator pit = parallelActions.iterator(); + while (pit.hasNext()) { + ActionBase a = (ActionBase) pit.next(); + a.tick(ticksExisted); + if (a.isDone()) pit.remove(); + } + + // ─── Conditionals ───────────────────────────────────────── + Iterator cit = conditionalActions.iterator(); + while (cit.hasNext()) { + ConditionalAction con = (ConditionalAction) cit.next(); con.tick(ticksExisted); - if (con.isDone()) - it.remove(); + if (con.isDone()) cit.remove(); } - } @Override @@ -197,6 +223,12 @@ public class ScriptedActionManager implements IActionManager { return new ActionChain(); } + @Override + public IActionChain parallelChain() { + return new ParallelActionChain(); + } + + /** helper to build a back‐to‐back chain of one‐shot actions */ public class ActionChain implements IActionChain { private int offset = 0, index = 0; @@ -216,6 +248,27 @@ public class ScriptedActionManager implements IActionManager { } } + private class ParallelActionChain implements IActionChain { + private int offset = 0, idx = 0; + + /** schedule the next task ‘delay’ ticks after the previous one, fully in parallel */ + @Override + public IActionChain after(int delay, Consumer task) { + offset += delay; + Consumer wrapper = act -> { + task.accept(act); + act.markDone(); + }; + IAction a = create("parallel#" + (idx++), + Integer.MAX_VALUE, // no max-duration + offset, + wrapper); + a.setUpdateEveryXTick(1); + scheduleParallelAction(a); + return this; + } + } + // ──── base class for all custom actions ────────────────────────────────── private abstract class ActionBase implements IAction { @@ -527,7 +580,5 @@ public class ScriptedActionManager implements IActionManager { public IConditionalAction after(String name, Supplier predicate, Supplier terminate, Consumer task) { return after(create(name, predicate, terminate, task)); } - - } }