2025-03-03 23:59:49 +02:00
|
|
|
package noppes.npcs.scripted;
|
|
|
|
|
|
2025-03-03 20:05:19 -05:00
|
|
|
import noppes.npcs.api.handler.IActionManager;
|
|
|
|
|
import noppes.npcs.api.handler.data.IAction;
|
2025-04-27 23:10:55 -04:00
|
|
|
import noppes.npcs.api.handler.data.IActionChain;
|
2025-04-28 07:41:29 +03:00
|
|
|
import noppes.npcs.api.handler.data.actions.IConditionalAction;
|
2025-04-28 03:25:01 -04:00
|
|
|
import noppes.npcs.controllers.data.action.Action;
|
|
|
|
|
import noppes.npcs.controllers.data.action.ActionChain;
|
|
|
|
|
import noppes.npcs.controllers.data.action.ConditionalAction;
|
|
|
|
|
import noppes.npcs.controllers.data.action.ParallelActionChain;
|
2025-03-03 23:59:49 +02:00
|
|
|
|
2025-04-28 07:41:29 +03:00
|
|
|
import java.util.*;
|
2025-05-19 22:07:57 -04:00
|
|
|
import java.util.concurrent.ConcurrentLinkedDeque;
|
2025-03-03 23:59:49 +02:00
|
|
|
import java.util.function.Consumer;
|
2025-04-26 20:52:08 -04:00
|
|
|
import java.util.function.Supplier;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Full-featured ActionManager:
|
|
|
|
|
* - delayed start, max-duration, tick-interval
|
|
|
|
|
* - chaining (getNext, getPrevious, scheduleAfter/Before)
|
|
|
|
|
* - per-action data
|
|
|
|
|
* - conditional actions
|
|
|
|
|
* - cancellation & clearing
|
|
|
|
|
*/
|
2025-03-03 23:59:49 +02:00
|
|
|
public class ScriptedActionManager implements IActionManager {
|
2025-04-26 20:52:08 -04:00
|
|
|
private boolean isWorking = false;
|
2025-04-28 03:05:56 -04:00
|
|
|
|
2025-05-19 22:07:57 -04:00
|
|
|
private final Deque<IAction> actionQueue = new ConcurrentLinkedDeque<>();
|
|
|
|
|
private final Deque<IAction> parallelActions = new ConcurrentLinkedDeque<>();
|
|
|
|
|
private final Deque<IConditionalAction> conditionalActions = new ConcurrentLinkedDeque<>();
|
2025-03-03 23:59:49 +02:00
|
|
|
|
2025-04-28 10:09:50 +03:00
|
|
|
@Override
|
|
|
|
|
public IAction create(String name) {
|
2025-04-28 03:25:01 -04:00
|
|
|
return new Action(this, name);
|
2025-04-28 10:09:50 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public IAction create(Consumer<IAction> t) {
|
2025-04-28 03:25:01 -04:00
|
|
|
return new Action(this, t);
|
2025-04-28 10:09:50 +03:00
|
|
|
}
|
|
|
|
|
|
2025-06-30 07:15:34 +03:00
|
|
|
@Override
|
|
|
|
|
public IAction create(int maxDuration, int delay, Consumer<IAction> task) {
|
|
|
|
|
return new Action(this, maxDuration, delay, task);
|
|
|
|
|
}
|
2025-03-03 23:59:49 +02:00
|
|
|
@Override
|
2025-06-29 11:22:43 +03:00
|
|
|
public IAction create(String name, int maxDuration, int delay, Consumer<IAction> task) {
|
|
|
|
|
return new Action(this, name, maxDuration, delay, task);
|
2025-03-03 23:59:49 +02:00
|
|
|
}
|
|
|
|
|
|
2025-04-28 07:26:39 +03:00
|
|
|
@Override
|
|
|
|
|
public IAction create(String name, int delay, Consumer<IAction> t) {
|
2025-04-28 03:25:01 -04:00
|
|
|
return new Action(this, name, delay, t);
|
2025-04-28 07:26:39 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public IAction create(int delay, Consumer<IAction> t) {
|
2025-04-28 03:25:01 -04:00
|
|
|
return new Action(this, delay, t);
|
2025-04-28 07:26:39 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public IAction create(String name, Consumer<IAction> t) {
|
2025-04-28 03:25:01 -04:00
|
|
|
return new Action(this, name, t);
|
2025-04-28 07:26:39 +03:00
|
|
|
}
|
|
|
|
|
|
2025-04-28 08:17:57 +03:00
|
|
|
@Override
|
2025-04-29 09:08:43 +03:00
|
|
|
public IConditionalAction create(Supplier<Boolean> condition, Consumer<IAction> task) {
|
|
|
|
|
return new ConditionalAction(this, condition, task);
|
2025-04-28 08:17:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
2025-04-29 09:08:43 +03:00
|
|
|
public IConditionalAction create(String name, Supplier<Boolean> condition, Consumer<IAction> task) {
|
|
|
|
|
return new ConditionalAction(this, name, condition, task);
|
2025-04-28 08:17:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
2025-04-29 09:08:43 +03:00
|
|
|
public IConditionalAction create(Supplier<Boolean> condition, Consumer<IAction> task, Supplier<Boolean> terminateWhen) {
|
|
|
|
|
return new ConditionalAction(this, condition, task, terminateWhen);
|
2025-04-28 08:17:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
2025-04-29 09:08:43 +03:00
|
|
|
public IConditionalAction create(String name, Supplier<Boolean> condition, Consumer<IAction> task, Supplier<Boolean> terminateWhen) {
|
|
|
|
|
return new ConditionalAction(this, name, condition, task, terminateWhen);
|
2025-04-28 09:57:25 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
2025-04-29 09:08:43 +03:00
|
|
|
public IConditionalAction create(Supplier<Boolean> condition, Consumer<IAction> task, Supplier<Boolean> terminateWhen, Consumer<IAction> onTermination) {
|
|
|
|
|
return new ConditionalAction(this, condition, task, terminateWhen, onTermination);
|
2025-04-28 09:57:25 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
2025-04-29 09:08:43 +03:00
|
|
|
public IConditionalAction create(String name, Supplier<Boolean> condition, Consumer<IAction> task, Supplier<Boolean> terminateWhen, Consumer<IAction> onTermination) {
|
|
|
|
|
return new ConditionalAction(this, name, condition, task, terminateWhen, onTermination);
|
2025-04-28 08:17:57 +03:00
|
|
|
}
|
|
|
|
|
|
2025-03-03 23:59:49 +02:00
|
|
|
@Override
|
|
|
|
|
public void start() {
|
|
|
|
|
isWorking = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void stop() {
|
|
|
|
|
isWorking = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
2025-04-28 06:47:34 +03:00
|
|
|
public IAction scheduleAction(IAction action) {
|
2025-04-26 20:52:08 -04:00
|
|
|
actionQueue.addLast(action);
|
2025-04-28 06:47:34 +03:00
|
|
|
return action;
|
2025-03-03 23:59:49 +02:00
|
|
|
}
|
|
|
|
|
|
2025-06-29 11:22:43 +03:00
|
|
|
@Override
|
|
|
|
|
public IAction scheduleAction(Consumer<IAction> task) {
|
|
|
|
|
return scheduleAction(create(task));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public IAction scheduleAction(int delay, Consumer<IAction> task) {
|
|
|
|
|
return scheduleAction(create(delay, task));
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-30 07:15:34 +03:00
|
|
|
@Override
|
|
|
|
|
public IAction scheduleAction(int maxDuration, int delay, Consumer<IAction> task) {
|
|
|
|
|
return scheduleAction(create(maxDuration, delay, task));
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-29 09:07:09 +03:00
|
|
|
@Override
|
2025-06-29 09:44:20 +03:00
|
|
|
public IAction scheduleAction(String name, Consumer<IAction> task) {
|
2025-06-29 09:07:09 +03:00
|
|
|
return scheduleAction(create(name, task));
|
|
|
|
|
}
|
|
|
|
|
@Override
|
2025-06-29 11:22:43 +03:00
|
|
|
public IAction scheduleAction(String name, int delay, Consumer<IAction> task) {
|
|
|
|
|
return scheduleAction(create(name, delay, task));
|
2025-06-29 09:07:09 +03:00
|
|
|
}
|
|
|
|
|
|
2025-03-03 23:59:49 +02:00
|
|
|
@Override
|
2025-06-29 11:22:43 +03:00
|
|
|
public IAction scheduleAction(String name, int maxDuration, int delay, Consumer<IAction> task) {
|
|
|
|
|
return scheduleAction(create(name, maxDuration, delay, task));
|
2025-03-03 23:59:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
2025-04-28 06:47:34 +03:00
|
|
|
public IAction scheduleActionAt(int index, IAction action) {
|
2025-05-19 22:07:57 -04:00
|
|
|
int size = actionQueue.size();
|
|
|
|
|
if (index <= 0) {
|
|
|
|
|
actionQueue.addFirst(action);
|
|
|
|
|
} else if (index >= size) {
|
2025-04-26 20:52:08 -04:00
|
|
|
actionQueue.addLast(action);
|
|
|
|
|
} else {
|
2025-05-19 22:07:57 -04:00
|
|
|
List<IAction> tmp = new ArrayList<>(actionQueue);
|
|
|
|
|
tmp.add(index, action);
|
|
|
|
|
actionQueue.clear();
|
|
|
|
|
actionQueue.addAll(tmp);
|
2025-04-26 20:52:08 -04:00
|
|
|
}
|
2025-04-28 06:47:34 +03:00
|
|
|
return action;
|
2025-03-03 23:59:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
2025-03-13 16:52:08 -04:00
|
|
|
public int getIndex(IAction action) {
|
2025-05-19 22:07:57 -04:00
|
|
|
int i = 0;
|
|
|
|
|
for (IAction a : actionQueue) {
|
|
|
|
|
if (a.equals(action)) return i;
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
2025-03-03 23:59:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public IAction getCurrentAction() {
|
2025-04-26 20:52:08 -04:00
|
|
|
return actionQueue.peekFirst();
|
2025-03-03 23:59:49 +02:00
|
|
|
}
|
|
|
|
|
|
2025-06-28 19:07:37 +03:00
|
|
|
@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;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-03 23:59:49 +02:00
|
|
|
@Override
|
|
|
|
|
public Queue<IAction> getActionQueue() {
|
|
|
|
|
return actionQueue;
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-29 09:44:20 +03:00
|
|
|
@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;
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-28 08:33:06 +03:00
|
|
|
///////////////////////////////////////////////////
|
|
|
|
|
///////////////////////////////////////////////////
|
|
|
|
|
// Conditionals
|
2025-06-30 07:15:34 +03:00
|
|
|
@Override
|
|
|
|
|
public IConditionalAction scheduleAction(Supplier<Boolean> condition, Consumer<IAction> task) {
|
|
|
|
|
return scheduleAction(new ConditionalAction(this, condition, task));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public IConditionalAction scheduleAction(Supplier<Boolean> condition, Consumer<IAction> task, Supplier<Boolean> terminateWhen) {
|
|
|
|
|
return scheduleAction(new ConditionalAction(this, condition, task, terminateWhen));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public IConditionalAction scheduleAction(Supplier<Boolean> condition, Consumer<IAction> task, Supplier<Boolean> terminateWhen, Consumer<IAction> onTermination) {
|
|
|
|
|
return scheduleAction(new ConditionalAction(this, condition, task, terminateWhen, onTermination));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2025-04-26 20:52:08 -04:00
|
|
|
@Override
|
2025-04-29 09:08:43 +03:00
|
|
|
public IConditionalAction scheduleAction(String name, Supplier<Boolean> condition, Consumer<IAction> task) {
|
|
|
|
|
return scheduleAction(new ConditionalAction(this, name, condition, task));
|
2025-04-26 20:52:08 -04:00
|
|
|
}
|
2025-03-03 23:59:49 +02:00
|
|
|
|
2025-04-27 07:33:50 +03:00
|
|
|
@Override
|
2025-04-29 09:08:43 +03:00
|
|
|
public IConditionalAction scheduleAction(String name, Supplier<Boolean> condition, Consumer<IAction> task, Supplier<Boolean> terminateWhen) {
|
|
|
|
|
return scheduleAction(new ConditionalAction(this, name, condition, task, terminateWhen));
|
2025-04-28 07:41:29 +03:00
|
|
|
}
|
|
|
|
|
|
2025-04-29 09:01:37 +03:00
|
|
|
@Override
|
2025-04-29 09:08:43 +03:00
|
|
|
public IConditionalAction scheduleAction(String name, Supplier<Boolean> condition, Consumer<IAction> task, Supplier<Boolean> terminateWhen, Consumer<IAction> onTermination) {
|
|
|
|
|
return scheduleAction(new ConditionalAction(this, name, condition, task, terminateWhen, onTermination));
|
2025-04-29 09:01:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2025-04-28 07:41:29 +03:00
|
|
|
@Override
|
2025-04-28 08:33:06 +03:00
|
|
|
public IConditionalAction scheduleAction(IConditionalAction action) {
|
2025-04-28 07:41:29 +03:00
|
|
|
conditionalActions.add(action);
|
|
|
|
|
return action;
|
2025-04-27 07:33:50 +03:00
|
|
|
}
|
|
|
|
|
|
2025-04-28 08:33:06 +03:00
|
|
|
@Override
|
|
|
|
|
public List<IConditionalAction> getConditionalActions() {
|
2025-05-19 22:07:57 -04:00
|
|
|
return new ArrayList<>(conditionalActions);
|
2025-04-28 08:33:06 +03:00
|
|
|
}
|
|
|
|
|
|
2025-06-29 09:44:20 +03:00
|
|
|
@Override
|
|
|
|
|
public boolean hasConditional(String name) {
|
|
|
|
|
for (IAction act : conditionalActions)
|
|
|
|
|
if (act.getName().equals(name))
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-28 03:05:56 -04:00
|
|
|
@Override
|
|
|
|
|
public IAction scheduleParallelAction(IAction action) {
|
|
|
|
|
parallelActions.add(action);
|
|
|
|
|
return action;
|
|
|
|
|
}
|
2025-06-29 09:55:14 +03:00
|
|
|
@Override
|
|
|
|
|
public IAction scheduleParallelAction(String name, Consumer<IAction> task) {
|
|
|
|
|
return scheduleParallelAction(create(name, task));
|
|
|
|
|
}
|
|
|
|
|
@Override
|
2025-06-29 11:22:43 +03:00
|
|
|
public IAction scheduleParallelAction(String name, int delay, Consumer<IAction> task) {
|
|
|
|
|
return scheduleParallelAction(create(name, delay, task));
|
2025-06-29 09:55:14 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
2025-06-29 11:22:43 +03:00
|
|
|
public IAction scheduleParallelAction(String name, int maxDuration, int delay, Consumer<IAction> task) {
|
|
|
|
|
return scheduleParallelAction(create(name, maxDuration, delay, task));
|
2025-06-29 09:55:14 +03:00
|
|
|
}
|
2025-04-28 03:05:56 -04:00
|
|
|
|
|
|
|
|
|
2025-04-26 20:52:08 -04:00
|
|
|
/**
|
|
|
|
|
* Call once per tick from your main loop.
|
|
|
|
|
*
|
|
|
|
|
* @param ticksExisted the global tick count, used for modulo checks.
|
|
|
|
|
*/
|
|
|
|
|
public void tick(int ticksExisted) {
|
|
|
|
|
if (!isWorking) return;
|
2025-04-28 03:05:56 -04:00
|
|
|
|
|
|
|
|
// ─── Sequential (head only) ─────────────────────────────────
|
2025-04-26 20:52:08 -04:00
|
|
|
IAction current = getCurrentAction();
|
2025-04-28 03:25:01 -04:00
|
|
|
if (current instanceof Action) {
|
|
|
|
|
Action cab = (Action) current;
|
2025-04-26 20:52:08 -04:00
|
|
|
cab.tick(ticksExisted);
|
2025-06-29 09:44:20 +03:00
|
|
|
if (cab.isDone()) {
|
|
|
|
|
cab.kill();
|
|
|
|
|
actionQueue.pollFirst();
|
|
|
|
|
}
|
2025-04-26 20:52:08 -04:00
|
|
|
}
|
2025-04-28 07:41:29 +03:00
|
|
|
|
2025-04-28 03:05:56 -04:00
|
|
|
// ─── Parallel (all) ───────────────────────────────────────
|
|
|
|
|
Iterator<IAction> pit = parallelActions.iterator();
|
|
|
|
|
while (pit.hasNext()) {
|
2025-04-28 03:25:01 -04:00
|
|
|
Action a = (Action) pit.next();
|
2025-04-28 03:05:56 -04:00
|
|
|
a.tick(ticksExisted);
|
2025-06-29 09:44:20 +03:00
|
|
|
if (a.isDone()) {
|
|
|
|
|
a.kill();
|
|
|
|
|
pit.remove();
|
|
|
|
|
}
|
2025-04-28 07:41:29 +03:00
|
|
|
}
|
|
|
|
|
|
2025-04-28 03:05:56 -04:00
|
|
|
// ─── Conditionals ─────────────────────────────────────────
|
|
|
|
|
Iterator<IConditionalAction> cit = conditionalActions.iterator();
|
|
|
|
|
while (cit.hasNext()) {
|
|
|
|
|
ConditionalAction con = (ConditionalAction) cit.next();
|
|
|
|
|
con.tick(ticksExisted);
|
2025-06-29 09:44:20 +03:00
|
|
|
if (con.isDone()) {
|
|
|
|
|
con.kill();
|
|
|
|
|
cit.remove();
|
|
|
|
|
}
|
2025-04-28 03:05:56 -04:00
|
|
|
}
|
2025-04-26 20:52:08 -04:00
|
|
|
}
|
|
|
|
|
|
2025-06-30 08:59:51 +03:00
|
|
|
@Override
|
|
|
|
|
public void clear() {
|
|
|
|
|
actionQueue.forEach((act) -> act.kill());
|
|
|
|
|
actionQueue.clear();
|
|
|
|
|
|
|
|
|
|
parallelActions.forEach((act) -> act.kill());
|
|
|
|
|
parallelActions.clear();
|
|
|
|
|
|
|
|
|
|
conditionalActions.forEach((act) -> act.kill());
|
|
|
|
|
conditionalActions.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public boolean cancelAction(String name) {
|
|
|
|
|
Iterator<IAction> acts = actionQueue.iterator();
|
|
|
|
|
while (acts.hasNext()) {
|
|
|
|
|
IAction act = acts.next();
|
|
|
|
|
if (act.getName().equals(name)) {
|
|
|
|
|
acts.remove();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Iterator<IAction> pit = parallelActions.iterator();
|
|
|
|
|
while (pit.hasNext()) {
|
|
|
|
|
if (pit.next().getName().equals(name)) {
|
|
|
|
|
pit.remove();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Iterator<IConditionalAction> cons = conditionalActions.iterator();
|
|
|
|
|
while (cons.hasNext()) {
|
|
|
|
|
IConditionalAction con = cons.next();
|
|
|
|
|
if (con.getName().equals(name)) {
|
|
|
|
|
cons.remove();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-27 23:10:55 -04:00
|
|
|
@Override
|
|
|
|
|
public IActionChain chain() {
|
2025-04-28 03:25:01 -04:00
|
|
|
return new ActionChain(this);
|
2025-04-27 23:10:55 -04:00
|
|
|
}
|
|
|
|
|
|
2025-04-28 03:05:56 -04:00
|
|
|
@Override
|
|
|
|
|
public IActionChain parallelChain() {
|
2025-04-28 03:25:01 -04:00
|
|
|
return new ParallelActionChain(this);
|
2025-04-26 20:52:08 -04:00
|
|
|
}
|
2025-06-29 09:44:20 +03:00
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Queue<IAction> getParallelActions() {
|
|
|
|
|
return parallelActions;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public boolean hasParallel(String name) {
|
|
|
|
|
for (IAction act : parallelActions)
|
|
|
|
|
if (act.getName().equals(name))
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2025-04-26 20:52:08 -04:00
|
|
|
}
|