This commit is contained in:
Kam committed 2025-06-29 14:32:26 -04:00
commit 8296a008d4
9 files changed
+365 -23

No files matched your search

@@ -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) {
@@ -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);
}
@@ -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;
@@ -16,8 +18,10 @@ public class Action implements IAction {
protected int maxDuration = -1;
protected int updateEveryXTick = 5;
protected Consumer<IAction> task;
private boolean done;
private final Map<String, Object> dataStore = new HashMap<>();
protected boolean done;
protected final Map<String, Object> dataStore = new HashMap<>();
protected boolean isThreaded;
protected ActionThread threaded;
public Action(ScriptedActionManager manager, String name) {
this.manager = manager;
@@ -68,13 +72,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++;
@@ -107,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;
}
@@ -121,6 +129,11 @@ public class Action implements IAction {
return done;
}
public void kill() {
if (threaded != null)
threaded.stop();
}
@Override
public Object getData(String key) {
return dataStore.get(key);
@@ -150,7 +163,7 @@ public class Action implements IAction {
@Override
public IAction setUpdateEveryXTick(int x) {
this.updateEveryXTick = x;
this.updateEveryXTick = Math.max(1, x);
return this;
}
@@ -161,7 +174,67 @@ public class Action implements IAction {
@Override
public IAction pauseFor(int ticks) {
this.startAfterTicks = ticks;
if (isThreaded)
threaded.pauseFor(ticks);
else
this.startAfterTicks = ticks;
return this;
}
@Override
public IAction pauseFor(long 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<Boolean> 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)
return threaded.isPaused();
return startAfterTicks > 0;
}
@Override
public IAction threadify() {
if (!isThreaded) {
isThreaded = true;
threaded = new ActionThread(this);
}
return this;
}
@Override
public IAction start() {
manager.start();
return this;
}
@@ -191,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<IAction> task) {
return manager.scheduleParallelAction(manager.create(task));
}
@Override
public IAction parallel(int delay, Consumer<IAction> task) {
return manager.scheduleParallelAction(manager.create(delay, task));
}
@Override
public IAction parallel(String name, Consumer<IAction> task) {
return manager.scheduleParallelAction(manager.create(name, task));
}
@Override
public IAction parallel(String name, int startAfterTicks, Consumer<IAction> task) {
return manager.scheduleParallelAction(manager.create(name, startAfterTicks, task));
}
@Override
public IAction after(IAction after) {
int idx = manager.getIndex(this);
@@ -0,0 +1,119 @@
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 {
private final Action action;
private final Object lock = new Object();
private Thread thread;
ExecutorService executor;
private Future<?> currentExecution;
private volatile boolean threadPaused, threadSleeping;
private Supplier<Boolean> pauseUntil;
public ActionThread(Action action) {
this.action = action;
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() || !inActionThread())
return;
try {
threadSleeping = true;
Thread.sleep(millis);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
threadSleeping = false;
}
}
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();
}
}
}
}
public void pauseUntil(Supplier<Boolean> until) {
this.pauseUntil = until;
pause();
}
public void resume() {
synchronized (lock) {
if (threadPaused) {
threadPaused = false;
lock.notify();
}
if (threadSleeping && currentExecution != null)
currentExecution.cancel(true);
}
}
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 (isThreadRunning())
return;
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();
}
});
}
}
@@ -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);
@@ -79,6 +79,7 @@ public class NpcAPI extends AbstractNpcAPI {
private static final CacheHashMap<ItemStack, CacheHashMap.CachedObject<ScriptItemStack>> scriptItemCache = new CacheHashMap<>(60 * 1000);
public static final HashMap<String, Object> 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");
@@ -40,8 +40,8 @@ public class ScriptedActionManager implements IActionManager {
}
@Override
public IAction create(String name, int maxDuration, int startAfterTicks, Consumer<IAction> task) {
return new Action(this, name, maxDuration, startAfterTicks, task);
public IAction create(String name, int maxDuration, int delay, Consumer<IAction> task) {
return new Action(this, name, maxDuration, delay, task);
}
@Override
@@ -106,8 +106,27 @@ public class ScriptedActionManager implements IActionManager {
}
@Override
public IAction scheduleAction(String name, int maxDuration, int startAfterTicks, Consumer<IAction> task) {
return scheduleAction(create(name, maxDuration, startAfterTicks, task));
public IAction scheduleAction(Consumer<IAction> task) {
return scheduleAction(create(task));
}
@Override
public IAction scheduleAction(int delay, Consumer<IAction> task) {
return scheduleAction(create(delay, task));
}
@Override
public IAction scheduleAction(String name, Consumer<IAction> task) {
return scheduleAction(create(name, task));
}
@Override
public IAction scheduleAction(String name, int delay, Consumer<IAction> task) {
return scheduleAction(create(name, delay, task));
}
@Override
public IAction scheduleAction(String name, int maxDuration, int delay, Consumer<IAction> task) {
return scheduleAction(create(name, maxDuration, delay, task));
}
@Override
@@ -141,11 +160,51 @@ 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<IAction> getActionQueue() {
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();
@@ -213,11 +272,33 @@ 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);
return action;
}
@Override
public IAction scheduleParallelAction(String name, Consumer<IAction> task) {
return scheduleParallelAction(create(name, task));
}
@Override
public IAction scheduleParallelAction(String name, int delay, Consumer<IAction> task) {
return scheduleParallelAction(create(name, delay, task));
}
@Override
public IAction scheduleParallelAction(String name, int maxDuration, int delay, Consumer<IAction> task) {
return scheduleParallelAction(create(name, maxDuration, delay, task));
}
/**
@@ -233,7 +314,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) ───────────────────────────────────────
@@ -241,7 +325,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 ─────────────────────────────────────────
@@ -249,7 +336,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();
}
}
}
@@ -262,4 +352,18 @@ public class ScriptedActionManager implements IActionManager {
public IActionChain parallelChain() {
return new ParallelActionChain(this);
}
@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;
}
}
@@ -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<T extends EntityPlayerMP> extends ScriptLivingBase<T>
public IPlayerAttributes getAttributes() {
return AttributeController.getTracker(this.player);
}
@Override
public IActionManager getActionManager() {
return data.actionManager;
}
}