Refactor: extract MacroLifecycle from MacroExecutor (upstream #4)

Move 56 run-lifecycle methods (flow control, step overrides, client
resources, run-list management, execute/track/stop) verbatim into
MacroLifecycle. The public lifecycle API stays reachable via
MacroExecutor delegates; all 150+ cross-helper call sites re-pointed.
All bodies verified identical against HEAD modulo mechanical
MacroExecutor./MacroLifecycle. qualification.
This commit is contained in:
sectersion 2026-10-11 16:41:36 +01:00
parent ad5826df73
commit 0e6d34f816
18 changed files with 1025 additions and 957 deletions

View file

@ -75,8 +75,8 @@ final class MacroActionRunner {
return postGuiFuture; return postGuiFuture;
} }
MacroExecutor.setCurrentStatus("Waiting target: " + action.getDisplayName()); MacroLifecycle.setCurrentStatus("Waiting target: " + action.getDisplayName());
while (MacroExecutor.isCurrentRunActive()) { while (MacroLifecycle.isCurrentRunActive()) {
if (!canRunTargetInteractionNow(mc, action)) { if (!canRunTargetInteractionNow(mc, action)) {
java.util.concurrent.locks.LockSupport.parkNanos(MacroExecutor.MACRO_WAIT_POLL_NANOS); java.util.concurrent.locks.LockSupport.parkNanos(MacroExecutor.MACRO_WAIT_POLL_NANOS);
if (Thread.interrupted()) throw new InterruptedException(); if (Thread.interrupted()) throw new InterruptedException();
@ -172,7 +172,7 @@ final class MacroActionRunner {
private static void waitForCurrentGuiReady(Minecraft mc) throws InterruptedException { private static void waitForCurrentGuiReady(Minecraft mc) throws InterruptedException {
long deadline = System.nanoTime() + 500_000_000L; long deadline = System.nanoTime() + 500_000_000L;
while (MacroExecutor.isCurrentRunActive()) { while (MacroLifecycle.isCurrentRunActive()) {
Boolean ready = MacroClientThread.callOnClientThread(mc, () -> { Boolean ready = MacroClientThread.callOnClientThread(mc, () -> {
if (mc.player == null || mc.gui.screen() == null) return false; if (mc.player == null || mc.gui.screen() == null) return false;
if (mc.player.containerMenu != null && mc.player.containerMenu != mc.player.inventoryMenu) { if (mc.player.containerMenu != null && mc.player.containerMenu != mc.player.inventoryMenu) {
@ -206,17 +206,17 @@ final class MacroActionRunner {
} }
public static void runItemActionPaced(Minecraft mc, ItemAction ia) throws InterruptedException { public static void runItemActionPaced(Minecraft mc, ItemAction ia) throws InterruptedException {
MacroExecutor.setCurrentStatus(ia.getDisplayName()); MacroLifecycle.setCurrentStatus(ia.getDisplayName());
java.util.List<Runnable> plan = MacroClientThread.callOnClientThread(mc, () -> ia.buildClickPlan(mc), java.util.Collections.<Runnable>emptyList()); java.util.List<Runnable> plan = MacroClientThread.callOnClientThread(mc, () -> ia.buildClickPlan(mc), java.util.Collections.<Runnable>emptyList());
if (plan == null || plan.isEmpty()) return; if (plan == null || plan.isEmpty()) return;
long delayMs = Math.max(0, ia.clickDelayMs); long delayMs = Math.max(0, ia.clickDelayMs);
MacroExecutor.RunState scheduledRun = MacroExecutor.CURRENT_RUN.get(); MacroExecutor.RunState scheduledRun = MacroExecutor.CURRENT_RUN.get();
boolean first = true; boolean first = true;
for (Runnable op : plan) { for (Runnable op : plan) {
if (!MacroExecutor.isCurrentRunActive()) break; if (!MacroLifecycle.isCurrentRunActive()) break;
if (!first && delayMs > 0) Thread.sleep(delayMs); if (!first && delayMs > 0) Thread.sleep(delayMs);
first = false; first = false;
mc.execute(() -> MacroExecutor.withRunContext(scheduledRun, () -> { mc.execute(() -> MacroLifecycle.withRunContext(scheduledRun, () -> {
if (PackHideState.isHardLocked()) return; if (PackHideState.isHardLocked()) return;
try { try {
op.run(); op.run();
@ -260,7 +260,7 @@ final class MacroActionRunner {
@Override public void runOnClientThread(Runnable r) { @Override public void runOnClientThread(Runnable r) {
if (r == null) return; if (r == null) return;
Runnable safe = () -> MacroExecutor.withRunContext(run, () -> { Runnable safe = () -> MacroLifecycle.withRunContext(run, () -> {
try { r.run(); } try { r.run(); }
catch (Throwable t) { AutismClientMessaging.sendPrefixed("\u00a7cAddon action (client task) error: " + (t.getMessage() == null ? t.getClass().getSimpleName() : t.getMessage())); } catch (Throwable t) { AutismClientMessaging.sendPrefixed("\u00a7cAddon action (client task) error: " + (t.getMessage() == null ? t.getClass().getSimpleName() : t.getMessage())); }
}); });
@ -272,7 +272,7 @@ final class MacroActionRunner {
if (s == null) return null; if (s == null) return null;
java.util.function.Supplier<T> safe = () -> { java.util.function.Supplier<T> safe = () -> {
AtomicReference<T> value = new AtomicReference<>(); AtomicReference<T> value = new AtomicReference<>();
MacroExecutor.withRunContext(run, () -> { MacroLifecycle.withRunContext(run, () -> {
try { value.set(s.get()); } try { value.set(s.get()); }
catch (Throwable t) { AutismClientMessaging.sendPrefixed("\u00a7cAddon action (client task) error: " + (t.getMessage() == null ? t.getClass().getSimpleName() : t.getMessage())); } catch (Throwable t) { AutismClientMessaging.sendPrefixed("\u00a7cAddon action (client task) error: " + (t.getMessage() == null ? t.getClass().getSimpleName() : t.getMessage())); }
}); });
@ -283,24 +283,24 @@ final class MacroActionRunner {
} }
@Override public void waitTicks(int ticks) { @Override public void waitTicks(int ticks) {
MacroExecutor.withRunContext(run, () -> { MacroLifecycle.withRunContext(run, () -> {
for (int i = 0; i < ticks && MacroExecutor.isCurrentRunActive(); i++) { for (int i = 0; i < ticks && MacroLifecycle.isCurrentRunActive(); i++) {
MacroRunLoop.waitForCondition(MacroConditionRegistry.waitForNextTick()); MacroRunLoop.waitForCondition(MacroConditionRegistry.waitForNextTick());
} }
}); });
} }
@Override public void awaitCondition(CompletableFuture<Void> future) { @Override public void awaitCondition(CompletableFuture<Void> future) {
if (future != null) MacroExecutor.withRunContext(run, () -> MacroRunLoop.waitForCondition(future)); if (future != null) MacroLifecycle.withRunContext(run, () -> MacroRunLoop.waitForCondition(future));
} }
@Override public void awaitCondition(autismclient.api.macro.AddonCondition condition) { @Override public void awaitCondition(autismclient.api.macro.AddonCondition condition) {
if (condition != null) MacroExecutor.withRunContext(run, () -> MacroRunLoop.waitForCondition(MacroConditionRegistry.await(condition))); if (condition != null) MacroLifecycle.withRunContext(run, () -> MacroRunLoop.waitForCondition(MacroConditionRegistry.await(condition)));
} }
@Override public boolean isActive() { return run != null && run.running.get() && !PackHideState.isHardLocked(); } @Override public boolean isActive() { return run != null && run.running.get() && !PackHideState.isHardLocked(); }
@Override public void setStatus(String status) { MacroExecutor.withRunContext(run, () -> MacroExecutor.setCurrentStatus(status)); } @Override public void setStatus(String status) { MacroLifecycle.withRunContext(run, () -> MacroLifecycle.setCurrentStatus(status)); }
@Override public void sendPacket(net.minecraft.network.protocol.Packet<?> packet) { @Override public void sendPacket(net.minecraft.network.protocol.Packet<?> packet) {
if (packet == null) return; if (packet == null) return;
@ -333,7 +333,7 @@ final class MacroActionRunner {
public static void runUseItemPhaseAction(Minecraft mc, UseItemPhaseAction action) throws InterruptedException { public static void runUseItemPhaseAction(Minecraft mc, UseItemPhaseAction action) throws InterruptedException {
int times = action.repeatTimes(); int times = action.repeatTimes();
for (int i = 0; i < times && MacroExecutor.isCurrentRunActive(); i++) { for (int i = 0; i < times && MacroLifecycle.isCurrentRunActive(); i++) {
MacroClientThread.runOnClientThread(mc, () -> { MacroClientThread.runOnClientThread(mc, () -> {
try { action.sendUsePacket(mc); } try { action.sendUsePacket(mc); }
@ -349,7 +349,7 @@ final class MacroActionRunner {
} }
try { try {
for (int t = 0; t < action.holdTicks && MacroExecutor.isCurrentRunActive(); t++) { for (int t = 0; t < action.holdTicks && MacroLifecycle.isCurrentRunActive(); t++) {
CompletableFuture<Void> tf = MacroConditionRegistry.waitForNextTick(); CompletableFuture<Void> tf = MacroConditionRegistry.waitForNextTick();
MacroRunLoop.waitForCondition(tf); MacroRunLoop.waitForCondition(tf);
} }
@ -363,7 +363,7 @@ final class MacroActionRunner {
} }
} }
} }
if (!MacroExecutor.isCurrentRunActive()) break; if (!MacroLifecycle.isCurrentRunActive()) break;
MacroClientThread.runOnClientThread(mc, () -> { MacroClientThread.runOnClientThread(mc, () -> {
try { action.finishRelease(mc); } try { action.finishRelease(mc); }
@ -376,7 +376,7 @@ final class MacroActionRunner {
int times = Math.max(1, action.clickCount); int times = Math.max(1, action.clickCount);
MacroClientThread.runOnClientThread(mc, () -> { MacroClientThread.runOnClientThread(mc, () -> {
for (int c = 0; c < times && MacroExecutor.isCurrentRunActive(); c++) { for (int c = 0; c < times && MacroLifecycle.isCurrentRunActive(); c++) {
try { try {
action.execute(mc); action.execute(mc);
} catch (Exception e) { } catch (Exception e) {
@ -407,7 +407,7 @@ final class MacroActionRunner {
} }
List<Integer> slots = MacroClientThread.callOnClientThread(mc, () -> action.collectTransferSlots(mc), List.of()); List<Integer> slots = MacroClientThread.callOnClientThread(mc, () -> action.collectTransferSlots(mc), List.of());
for (int i = 0; i < slots.size() && MacroExecutor.isCurrentRunActive(); i++) { for (int i = 0; i < slots.size() && MacroLifecycle.isCurrentRunActive(); i++) {
AutismInventoryClickHelper.click(mc, slots.get(i), 0, net.minecraft.world.inventory.ContainerInput.QUICK_MOVE); AutismInventoryClickHelper.click(mc, slots.get(i), 0, net.minecraft.world.inventory.ContainerInput.QUICK_MOVE);
if (i + 1 < slots.size()) waitTicks(delayTicks); if (i + 1 < slots.size()) waitTicks(delayTicks);
} }
@ -418,7 +418,7 @@ final class MacroActionRunner {
} }
private static void waitTicks(int ticks) { private static void waitTicks(int ticks) {
for (int i = 0; i < ticks && MacroExecutor.isCurrentRunActive(); i++) { for (int i = 0; i < ticks && MacroLifecycle.isCurrentRunActive(); i++) {
CompletableFuture<Void> tickFuture = MacroConditionRegistry.waitForNextTick(); CompletableFuture<Void> tickFuture = MacroConditionRegistry.waitForNextTick();
MacroRunLoop.waitForCondition(tickFuture); MacroRunLoop.waitForCondition(tickFuture);
} }
@ -439,7 +439,7 @@ final class MacroActionRunner {
}, action.isTickAligned()); }, action.isTickAligned());
if (action.holdTicks > 0) { if (action.holdTicks > 0) {
waitTicks(action.holdTicks); waitTicks(action.holdTicks);
if (!MacroExecutor.isCurrentRunActive()) return; if (!MacroLifecycle.isCurrentRunActive()) return;
MacroClientThread.runOnClientThread(mc, () -> { MacroClientThread.runOnClientThread(mc, () -> {
try { action.sendRelease(mc); } try { action.sendRelease(mc); }
catch (Exception e) { AutismClientMessaging.sendPrefixed("\u00a7cError in UseItem release: " + e.getMessage()); } catch (Exception e) { AutismClientMessaging.sendPrefixed("\u00a7cError in UseItem release: " + e.getMessage()); }
@ -450,7 +450,7 @@ final class MacroActionRunner {
} }
int times = Math.max(1, action.useCount); int times = Math.max(1, action.useCount);
for (int i = 0; i < times && MacroExecutor.isCurrentRunActive(); i++) { for (int i = 0; i < times && MacroLifecycle.isCurrentRunActive(); i++) {
MacroClientThread.runOnClientThread(mc, () -> { MacroClientThread.runOnClientThread(mc, () -> {
try { try {
if (sneaking) autismclient.util.AutismMacroSneak.forceSneak(mc, true); if (sneaking) autismclient.util.AutismMacroSneak.forceSneak(mc, true);
@ -459,7 +459,7 @@ final class MacroActionRunner {
catch (Exception e) { AutismClientMessaging.sendPrefixed("\u00a7cError in UseItem: " + e.getMessage()); } catch (Exception e) { AutismClientMessaging.sendPrefixed("\u00a7cError in UseItem: " + e.getMessage()); }
}, action.isTickAligned()); }, action.isTickAligned());
if (action.waitForFinish) waitForUseItemFinish(mc, 0); if (action.waitForFinish) waitForUseItemFinish(mc, 0);
if (i + 1 < times && MacroExecutor.isCurrentRunActive()) MacroExecutor.waitOneTick(); if (i + 1 < times && MacroLifecycle.isCurrentRunActive()) MacroExecutor.waitOneTick();
} }
} finally { } finally {
if (sneaking) mc.execute(() -> autismclient.util.AutismMacroSneak.forceSneak(mc, false)); if (sneaking) mc.execute(() -> autismclient.util.AutismMacroSneak.forceSneak(mc, false));
@ -473,9 +473,9 @@ final class MacroActionRunner {
int delay = Math.max(0, action.delayTicks); int delay = Math.max(0, action.delayTicks);
int total = repeats * slots.size(); int total = repeats * slots.size();
int sent = 0; int sent = 0;
for (int repeat = 0; repeat < repeats && MacroExecutor.isCurrentRunActive(); repeat++) { for (int repeat = 0; repeat < repeats && MacroLifecycle.isCurrentRunActive(); repeat++) {
for (int slot : slots) { for (int slot : slots) {
if (!MacroExecutor.isCurrentRunActive()) return; if (!MacroLifecycle.isCurrentRunActive()) return;
MacroClientThread.runOnClientThread(mc, () -> action.executeClick(mc, slot)); MacroClientThread.runOnClientThread(mc, () -> action.executeClick(mc, slot));
sent++; sent++;
if (delay > 0 && sent < total) waitTicks(delay); if (delay > 0 && sent < total) waitTicks(delay);
@ -488,14 +488,14 @@ final class MacroActionRunner {
if (action.flushBefore) AutismSharedState.get().flushDelayedPackets(mc.getConnection()); if (action.flushBefore) AutismSharedState.get().flushDelayedPackets(mc.getConnection());
int total = action.effectiveCount(); int total = action.effectiveCount();
int delay = Math.max(0, action.delayTicks); int delay = Math.max(0, action.delayTicks);
for (int i = 0; i < total && MacroExecutor.isCurrentRunActive(); i++) { for (int i = 0; i < total && MacroLifecycle.isCurrentRunActive(); i++) {
action.sendOne(mc); action.sendOne(mc);
if (delay > 0 && i + 1 < total) waitTicks(delay); if (delay > 0 && i + 1 < total) waitTicks(delay);
} }
} }
private static void waitForUseItemFinish(Minecraft mc, int fallbackTicks) throws InterruptedException { private static void waitForUseItemFinish(Minecraft mc, int fallbackTicks) throws InterruptedException {
if (mc == null || !MacroExecutor.isCurrentRunActive()) return; if (mc == null || !MacroLifecycle.isCurrentRunActive()) return;
if (!Boolean.TRUE.equals(MacroClientThread.callOnClientThread(mc, if (!Boolean.TRUE.equals(MacroClientThread.callOnClientThread(mc,
() -> mc.player != null && mc.player.isUsingItem(), () -> mc.player != null && mc.player.isUsingItem(),
@ -508,7 +508,7 @@ final class MacroActionRunner {
0); 0);
int maxTicks = Math.max(8, remaining > 0 ? remaining + 8 : fallbackTicks + 8); int maxTicks = Math.max(8, remaining > 0 ? remaining + 8 : fallbackTicks + 8);
maxTicks = Math.min(maxTicks, 72000); maxTicks = Math.min(maxTicks, 72000);
for (int i = 0; i < maxTicks && MacroExecutor.isCurrentRunActive(); i++) { for (int i = 0; i < maxTicks && MacroLifecycle.isCurrentRunActive(); i++) {
if (!Boolean.TRUE.equals(MacroClientThread.callOnClientThread(mc, if (!Boolean.TRUE.equals(MacroClientThread.callOnClientThread(mc,
() -> mc.player != null && mc.player.isUsingItem(), () -> mc.player != null && mc.player.isUsingItem(),
Boolean.FALSE))) { Boolean.FALSE))) {

View file

@ -39,7 +39,7 @@ final class MacroBreak {
try { try {
long lastAttemptTick = AutismSharedState.get().getClientTickCounter() - (delayTicks + 1L); long lastAttemptTick = AutismSharedState.get().getClientTickCounter() - (delayTicks + 1L);
long lastSneakTick = Long.MIN_VALUE; long lastSneakTick = Long.MIN_VALUE;
while (MacroExecutor.isCurrentRunActive() && isActionStillInCurrentMacro(action)) { while (MacroLifecycle.isCurrentRunActive() && isActionStillInCurrentMacro(action)) {
if (action.sneak) { if (action.sneak) {
long sneakTick = AutismSharedState.get().getClientTickCounter(); long sneakTick = AutismSharedState.get().getClientTickCounter();
@ -53,7 +53,7 @@ final class MacroBreak {
boolean isAir = isInstaBreakAir(mc, target); boolean isAir = isInstaBreakAir(mc, target);
if (wasSolid && isAir) { if (wasSolid && isAir) {
completed++; completed++;
MacroExecutor.setCurrentStatus("InstaBreak " + completed + "/" + (targetTimes == 0 ? "\u221e" : targetTimes)); MacroLifecycle.setCurrentStatus("InstaBreak " + completed + "/" + (targetTimes == 0 ? "\u221e" : targetTimes));
if (targetTimes > 0 && completed >= targetTimes) return; if (targetTimes > 0 && completed >= targetTimes) return;
wasSolid = false; wasSolid = false;
} else if (!isAir) { } else if (!isAir) {
@ -91,7 +91,7 @@ final class MacroBreak {
} }
} }
MacroExecutor.setCurrentStatus("InstaBreak " + target.getX() + "," + target.getY() + "," + target.getZ() MacroLifecycle.setCurrentStatus("InstaBreak " + target.getX() + "," + target.getY() + "," + target.getZ()
+ " " + completed + "/" + (targetTimes == 0 ? "\u221e" : targetTimes)); + " " + completed + "/" + (targetTimes == 0 ? "\u221e" : targetTimes));
Thread.sleep(1); Thread.sleep(1);
@ -191,7 +191,7 @@ final class MacroBreak {
AutismInstaBreakRenderer.setTarget(target); AutismInstaBreakRenderer.setTarget(target);
long lastTick = -1L; long lastTick = -1L;
try { try {
while (MacroExecutor.isCurrentRunActive() && isActionStillInCurrentMacro(action)) { while (MacroLifecycle.isCurrentRunActive() && isActionStillInCurrentMacro(action)) {
long now = AutismSharedState.get().getClientTickCounter(); long now = AutismSharedState.get().getClientTickCounter();
if (now == lastTick) { if (now == lastTick) {
Thread.sleep(1); Thread.sleep(1);
@ -225,13 +225,13 @@ final class MacroBreak {
MacroClientThread.runOnClientThread(mc, () -> sendBlockInteract(mc, target, direction), action.isTickAligned()); MacroClientThread.runOnClientThread(mc, () -> sendBlockInteract(mc, target, direction), action.isTickAligned());
} }
completed++; completed++;
MacroExecutor.setCurrentStatus("Break " + completed + "/" + (targetTimes == 0 ? "\u221e" : targetTimes)); MacroLifecycle.setCurrentStatus("Break " + completed + "/" + (targetTimes == 0 ? "\u221e" : targetTimes));
if (targetTimes > 0 && completed >= targetTimes) return; if (targetTimes > 0 && completed >= targetTimes) return;
started[0] = false; started[0] = false;
nextStepsFired[0] = false; nextStepsFired[0] = false;
waitForBreakSolid(mc, target); waitForBreakSolid(mc, target);
} else { } else {
MacroExecutor.setCurrentStatus("Break " + target.getX() + "," + target.getY() + "," + target.getZ() MacroLifecycle.setCurrentStatus("Break " + target.getX() + "," + target.getY() + "," + target.getZ()
+ " " + completed + "/" + (targetTimes == 0 ? "\u221e" : targetTimes)); + " " + completed + "/" + (targetTimes == 0 ? "\u221e" : targetTimes));
} }
} }
@ -253,7 +253,7 @@ final class MacroBreak {
if (plan.instant() && plan.interactFirst()) { if (plan.instant() && plan.interactFirst()) {
runBreakNextStepsOnce(mc, action, nextStepsFired, missingNextStepsWarned); runBreakNextStepsOnce(mc, action, nextStepsFired, missingNextStepsWarned);
if (!MacroExecutor.isCurrentRunActive()) return -1; if (!MacroLifecycle.isCurrentRunActive()) return -1;
} }
int result = MacroClientThread.callOnClientThread(mc, () -> startPreparedBreakOnClient(mc, action, pos, dir, started), -1, action.isTickAligned()); int result = MacroClientThread.callOnClientThread(mc, () -> startPreparedBreakOnClient(mc, action, pos, dir, started), -1, action.isTickAligned());
@ -326,11 +326,11 @@ final class MacroBreak {
InteractTiming timing = action.interactTiming; InteractTiming timing = action.interactTiming;
if (timing == InteractTiming.BEFORE && plan.breaksNextTick()) { if (timing == InteractTiming.BEFORE && plan.breaksNextTick()) {
runBreakNextStepsOnce(mc, action, nextStepsFired, missingNextStepsWarned); runBreakNextStepsOnce(mc, action, nextStepsFired, missingNextStepsWarned);
if (!MacroExecutor.isCurrentRunActive()) return -1; if (!MacroLifecycle.isCurrentRunActive()) return -1;
} }
if (timing == InteractTiming.WITH && plan.breaksThisTick()) { if (timing == InteractTiming.WITH && plan.breaksThisTick()) {
runBreakNextStepsOnce(mc, action, nextStepsFired, missingNextStepsWarned); runBreakNextStepsOnce(mc, action, nextStepsFired, missingNextStepsWarned);
if (!MacroExecutor.isCurrentRunActive()) return -1; if (!MacroLifecycle.isCurrentRunActive()) return -1;
} }
int result = MacroClientThread.callOnClientThread(mc, () -> continueBreakOnClient(mc, action, pos, dir), -1, action.isTickAligned()); int result = MacroClientThread.callOnClientThread(mc, () -> continueBreakOnClient(mc, action, pos, dir), -1, action.isTickAligned());
@ -396,7 +396,7 @@ final class MacroBreak {
int broke; int broke;
if (action.interactCustomMs < 0) { if (action.interactCustomMs < 0) {
runBreakNextStepsOnce(mc, action, nextStepsFired, missingNextStepsWarned); runBreakNextStepsOnce(mc, action, nextStepsFired, missingNextStepsWarned);
if (!MacroExecutor.isCurrentRunActive()) return -1; if (!MacroLifecycle.isCurrentRunActive()) return -1;
if (ns > 0) java.util.concurrent.locks.LockSupport.parkNanos(ns); if (ns > 0) java.util.concurrent.locks.LockSupport.parkNanos(ns);
broke = MacroClientThread.callOnClientThread(mc, () -> breakAndDetectOnClient(mc, pos, dir), -1, action.isTickAligned()); broke = MacroClientThread.callOnClientThread(mc, () -> breakAndDetectOnClient(mc, pos, dir), -1, action.isTickAligned());
} else { } else {
@ -475,13 +475,13 @@ final class MacroBreak {
if (fired != null) fired[0] = true; if (fired != null) fired[0] = true;
action.markNextActionsRan(); action.markNextActionsRan();
String names = actions.size() == 1 ? actions.get(0).getDisplayName() : actions.size() + " steps"; String names = actions.size() == 1 ? actions.get(0).getDisplayName() : actions.size() + " steps";
MacroExecutor.setCurrentStatus("Break: next " + names); MacroLifecycle.setCurrentStatus("Break: next " + names);
AutismModule module = AutismModule.get(); AutismModule module = AutismModule.get();
boolean previousSuppressPostGui = Boolean.TRUE.equals(MacroExecutor.SUPPRESS_POST_GUI_AFTER.get()); boolean previousSuppressPostGui = Boolean.TRUE.equals(MacroExecutor.SUPPRESS_POST_GUI_AFTER.get());
try { try {
MacroExecutor.SUPPRESS_POST_GUI_AFTER.set(true); MacroExecutor.SUPPRESS_POST_GUI_AFTER.set(true);
for (MacroAction next : actions) { for (MacroAction next : actions) {
if (next == null || !next.isEnabled() || !MacroExecutor.isCurrentRunActive()) continue; if (next == null || !next.isEnabled() || !MacroLifecycle.isCurrentRunActive()) continue;
try { try {
MacroDispatcher.executeSingleActionWithWaits(mc, next, module); MacroDispatcher.executeSingleActionWithWaits(mc, next, module);
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -524,7 +524,7 @@ final class MacroBreak {
} }
private static void waitForBreakSolid(Minecraft mc, BlockPos pos) throws InterruptedException { private static void waitForBreakSolid(Minecraft mc, BlockPos pos) throws InterruptedException {
while (MacroExecutor.isCurrentRunActive()) { while (MacroLifecycle.isCurrentRunActive()) {
if (!isInstaBreakAir(mc, pos)) return; if (!isInstaBreakAir(mc, pos)) return;
Thread.sleep(1); Thread.sleep(1);
} }
@ -532,7 +532,7 @@ final class MacroBreak {
private static void waitBreakClientTicks(int ticks) throws InterruptedException { private static void waitBreakClientTicks(int ticks) throws InterruptedException {
long start = AutismSharedState.get().getClientTickCounter(); long start = AutismSharedState.get().getClientTickCounter();
while (MacroExecutor.isCurrentRunActive() && (AutismSharedState.get().getClientTickCounter() - start) < ticks) { while (MacroLifecycle.isCurrentRunActive() && (AutismSharedState.get().getClientTickCounter() - start) < ticks) {
Thread.sleep(1); Thread.sleep(1);
} }
} }
@ -543,6 +543,6 @@ final class MacroBreak {
private static void releaseMacroSneak(Minecraft mc, String mode) { private static void releaseMacroSneak(Minecraft mc, String mode) {
autismclient.util.AutismMacroSneak.release(mc, mode); autismclient.util.AutismMacroSneak.release(mc, mode);
if (!autismclient.util.AutismMacroSneak.isPacket(mode)) MacroExecutor.applyAggregateSneakState(mc); if (!autismclient.util.AutismMacroSneak.isPacket(mode)) MacroLifecycle.applyAggregateSneakState(mc);
} }
} }

View file

@ -172,11 +172,11 @@ final class MacroCaptureAutofill {
if (action.autofillCacheList) { if (action.autofillCacheList) {
CachedSuggestions listCache = SUGGESTION_CACHE.get(query); CachedSuggestions listCache = SUGGESTION_CACHE.get(query);
if (listCache != null && listCache.connection() == connection && !listCache.suggestions().isEmpty()) { if (listCache != null && listCache.connection() == connection && !listCache.suggestions().isEmpty()) {
MacroExecutor.setCurrentStatus("Using cached suggestions"); MacroLifecycle.setCurrentStatus("Using cached suggestions");
applyCaptureSuggestions(run, action, listCache.suggestions(), query); applyCaptureSuggestions(run, action, listCache.suggestions(), query);
return; return;
} }
MacroExecutor.setCurrentStatus("Sweeping command suggestions"); MacroLifecycle.setCurrentStatus("Sweeping command suggestions");
java.util.List<String> all = sweepAutofillCommand(connection, query); java.util.List<String> all = sweepAutofillCommand(connection, query);
if (all.isEmpty()) return; if (all.isEmpty()) return;
if (SUGGESTION_CACHE.size() >= SUGGESTION_CACHE_MAX) SUGGESTION_CACHE.clear(); if (SUGGESTION_CACHE.size() >= SUGGESTION_CACHE_MAX) SUGGESTION_CACHE.clear();
@ -191,13 +191,13 @@ final class MacroCaptureAutofill {
if (cached != null) { if (cached != null) {
MacroExecutor.setCurrentStatus("Using cached suggestions"); MacroLifecycle.setCurrentStatus("Using cached suggestions");
applyCaptureSuggestions(run, action, capturePool(connection, action, query, cached.suggestions()), query); applyCaptureSuggestions(run, action, capturePool(connection, action, query, cached.suggestions()), query);
fireSuggestionFetch(connection, query, action.autofillTimeoutMs); fireSuggestionFetch(connection, query, action.autofillTimeoutMs);
return; return;
} }
MacroExecutor.setCurrentStatus("Requesting command suggestions"); MacroLifecycle.setCurrentStatus("Requesting command suggestions");
PendingFetch pending = fireSuggestionFetch(connection, query, action.autofillTimeoutMs); PendingFetch pending = fireSuggestionFetch(connection, query, action.autofillTimeoutMs);
if (pending == null) return; if (pending == null) return;
if (!MacroRace.waitForFutureDone(pending.future(), 0)) return; if (!MacroRace.waitForFutureDone(pending.future(), 0)) return;
@ -210,7 +210,7 @@ final class MacroCaptureAutofill {
autismclient.util.AutismNameHarvest.Control control = new autismclient.util.AutismNameHarvest.Control() { autismclient.util.AutismNameHarvest.Control control = new autismclient.util.AutismNameHarvest.Control() {
@Override public boolean cancelled() { @Override public boolean cancelled() {
Minecraft mc = Minecraft.getInstance(); Minecraft mc = Minecraft.getInstance();
return !MacroExecutor.isCurrentRunActive() || mc == null || mc.getConnection() != connection; return !MacroLifecycle.isCurrentRunActive() || mc == null || mc.getConnection() != connection;
} }
@Override public boolean paused() { return false; } @Override public boolean paused() { return false; }
@Override public int limit() { return MAX_SWEEP_NAMES; } @Override public int limit() { return MAX_SWEEP_NAMES; }
@ -230,11 +230,11 @@ final class MacroCaptureAutofill {
String cacheKey = "namescrape"; String cacheKey = "namescrape";
CachedSuggestions cached = SUGGESTION_CACHE.get(cacheKey); CachedSuggestions cached = SUGGESTION_CACHE.get(cacheKey);
if (cached != null && cached.connection() == connection && !cached.suggestions().isEmpty()) { if (cached != null && cached.connection() == connection && !cached.suggestions().isEmpty()) {
MacroExecutor.setCurrentStatus("Using cached names"); MacroLifecycle.setCurrentStatus("Using cached names");
applyCaptureSuggestions(run, action, cached.suggestions(), ""); applyCaptureSuggestions(run, action, cached.suggestions(), "");
return; return;
} }
MacroExecutor.setCurrentStatus("Scraping player names"); MacroLifecycle.setCurrentStatus("Scraping player names");
java.util.List<String> names = scrapeAllNames(mc, connection); java.util.List<String> names = scrapeAllNames(mc, connection);
if (names.isEmpty()) return; if (names.isEmpty()) return;
if (SUGGESTION_CACHE.size() >= SUGGESTION_CACHE_MAX) SUGGESTION_CACHE.clear(); if (SUGGESTION_CACHE.size() >= SUGGESTION_CACHE_MAX) SUGGESTION_CACHE.clear();
@ -250,7 +250,7 @@ final class MacroCaptureAutofill {
autismclient.util.AutismNameHarvest.Control control = new autismclient.util.AutismNameHarvest.Control() { autismclient.util.AutismNameHarvest.Control control = new autismclient.util.AutismNameHarvest.Control() {
@Override public boolean cancelled() { @Override public boolean cancelled() {
Minecraft m = Minecraft.getInstance(); Minecraft m = Minecraft.getInstance();
return !MacroExecutor.isCurrentRunActive() || m == null || m.getConnection() != connection; return !MacroLifecycle.isCurrentRunActive() || m == null || m.getConnection() != connection;
} }
@Override public boolean paused() { return false; } @Override public boolean paused() { return false; }
@Override public int limit() { return MAX_SWEEP_NAMES; } @Override public int limit() { return MAX_SWEEP_NAMES; }
@ -267,25 +267,25 @@ final class MacroCaptureAutofill {
String modifierError = action.numberModifierError(); String modifierError = action.numberModifierError();
if (!modifierError.isBlank()) { if (!modifierError.isBlank()) {
MacroExecutor.setCurrentStatus("Capture failed: " + modifierError); MacroLifecycle.setCurrentStatus("Capture failed: " + modifierError);
autismclient.util.AutismNotifications.error("Capture Value: " + modifierError); autismclient.util.AutismNotifications.error("Capture Value: " + modifierError);
return; return;
} }
if (action.source == CaptureValueAction.Source.COMMAND_AUTOFILL) { if (action.source == CaptureValueAction.Source.COMMAND_AUTOFILL) {
MacroExecutor.setCurrentStatus("Requesting command suggestions"); MacroLifecycle.setCurrentStatus("Requesting command suggestions");
runCaptureCommandAutofill(mc, action); runCaptureCommandAutofill(mc, action);
reportMissingCapture(action); reportMissingCapture(action);
return; return;
} }
if (action.source == CaptureValueAction.Source.NAMESCRAPE) { if (action.source == CaptureValueAction.Source.NAMESCRAPE) {
MacroExecutor.setCurrentStatus("Scraping player names"); MacroLifecycle.setCurrentStatus("Scraping player names");
runCaptureNamescrape(mc, action); runCaptureNamescrape(mc, action);
reportMissingCapture(action); reportMissingCapture(action);
return; return;
} }
if (action.waitForTrigger) { if (action.waitForTrigger) {
CaptureValueAction.Source source = action.source == null ? CaptureValueAction.Source.GUI_TITLE : action.source; CaptureValueAction.Source source = action.source == null ? CaptureValueAction.Source.GUI_TITLE : action.source;
MacroExecutor.setCurrentStatus("Waiting for capture: " + source.name().toLowerCase(Locale.ROOT).replace('_', ' ')); MacroLifecycle.setCurrentStatus("Waiting for capture: " + source.name().toLowerCase(Locale.ROOT).replace('_', ' '));
if (source == CaptureValueAction.Source.RECENT_CHAT) MacroPacketWait.awaitCaptureValueChat(action); if (source == CaptureValueAction.Source.RECENT_CHAT) MacroPacketWait.awaitCaptureValueChat(action);
else if (source == CaptureValueAction.Source.SCOREBOARD) awaitCaptureValueScoreboard(mc, action); else if (source == CaptureValueAction.Source.SCOREBOARD) awaitCaptureValueScoreboard(mc, action);
else awaitCaptureValueState(mc, action); else awaitCaptureValueState(mc, action);
@ -296,9 +296,9 @@ final class MacroCaptureAutofill {
new java.util.concurrent.atomic.AtomicReference<>(CaptureValueAction.Preview.unavailable("Not available")); new java.util.concurrent.atomic.AtomicReference<>(CaptureValueAction.Preview.unavailable("Not available"));
long deadline = System.nanoTime() + MacroExecutor.CAPTURE_SETTLE_MS * 1_000_000L; long deadline = System.nanoTime() + MacroExecutor.CAPTURE_SETTLE_MS * 1_000_000L;
while (MacroExecutor.isCurrentRunActive()) { while (MacroLifecycle.isCurrentRunActive()) {
CompletableFuture<Void> done = new CompletableFuture<>(); CompletableFuture<Void> done = new CompletableFuture<>();
mc.execute(() -> MacroExecutor.withRunContext(run, () -> { mc.execute(() -> MacroLifecycle.withRunContext(run, () -> {
try { try {
result.set(action.run(mc)); result.set(action.run(mc));
done.complete(null); done.complete(null);
@ -314,7 +314,7 @@ final class MacroCaptureAutofill {
CaptureValueAction.Preview preview = result.get(); CaptureValueAction.Preview preview = result.get();
if (!preview.success()) { if (!preview.success()) {
MacroExecutor.setCurrentStatus("Capture failed: " + preview.message()); MacroLifecycle.setCurrentStatus("Capture failed: " + preview.message());
autismclient.util.AutismNotifications.error( autismclient.util.AutismNotifications.error(
"Capture " + captureOutputLabel(action) + ": " + preview.message()); "Capture " + captureOutputLabel(action) + ": " + preview.message());
} }
@ -323,7 +323,7 @@ final class MacroCaptureAutofill {
private static void reportMissingCapture(CaptureValueAction action) { private static void reportMissingCapture(CaptureValueAction action) {
String name = MacroVariableContext.cleanRootName(action.saveAs); String name = MacroVariableContext.cleanRootName(action.saveAs);
if (name.isBlank() || MacroVariables.value(name).isPresent()) return; if (name.isBlank() || MacroVariables.value(name).isPresent()) return;
MacroExecutor.setCurrentStatus("Capture failed: nothing captured"); MacroLifecycle.setCurrentStatus("Capture failed: nothing captured");
autismclient.util.AutismNotifications.error( autismclient.util.AutismNotifications.error(
"Capture " + captureOutputLabel(action) + ": nothing captured"); "Capture " + captureOutputLabel(action) + ": nothing captured");
} }
@ -337,7 +337,7 @@ final class MacroCaptureAutofill {
MacroExecutor.RunState run = MacroExecutor.CURRENT_RUN.get(); MacroExecutor.RunState run = MacroExecutor.CURRENT_RUN.get();
MacroPrearm.clearCaptureOutputs(action); MacroPrearm.clearCaptureOutputs(action);
String lastMessage = ""; String lastMessage = "";
while (MacroExecutor.isCurrentRunActive()) { while (MacroLifecycle.isCurrentRunActive()) {
CaptureValueAction.Preview preview; CaptureValueAction.Preview preview;
try { try {
preview = MacroClientThread.callOnClientThread(mc, () -> action.previewCurrent(mc), preview = MacroClientThread.callOnClientThread(mc, () -> action.previewCurrent(mc),
@ -353,7 +353,7 @@ final class MacroCaptureAutofill {
} }
if (!preview.message().isBlank() && !preview.message().equals(lastMessage)) { if (!preview.message().isBlank() && !preview.message().equals(lastMessage)) {
lastMessage = preview.message(); lastMessage = preview.message();
MacroExecutor.setCurrentStatus("Capture waiting: " + lastMessage); MacroLifecycle.setCurrentStatus("Capture waiting: " + lastMessage);
} }
MacroExecutor.waitOneTick(); MacroExecutor.waitOneTick();
} }
@ -368,7 +368,7 @@ final class MacroCaptureAutofill {
String previousText = null; String previousText = null;
String lastMessage = ""; String lastMessage = "";
boolean baselineReady = false; boolean baselineReady = false;
while (MacroExecutor.isCurrentRunActive()) { while (MacroLifecycle.isCurrentRunActive()) {
CaptureValueAction.ScoreboardLine line; CaptureValueAction.ScoreboardLine line;
try { try {
String keySnapshot = trackedKey; String keySnapshot = trackedKey;
@ -397,7 +397,7 @@ final class MacroCaptureAutofill {
} }
if (!preview.message().isBlank() && !preview.message().equals(lastMessage)) { if (!preview.message().isBlank() && !preview.message().equals(lastMessage)) {
lastMessage = preview.message(); lastMessage = preview.message();
MacroExecutor.setCurrentStatus("Capture waiting: " + lastMessage); MacroLifecycle.setCurrentStatus("Capture waiting: " + lastMessage);
} }
previousText = currentText; previousText = currentText;
} }

View file

@ -122,11 +122,11 @@ final class MacroChatObserve {
} }
private static boolean matchesChatAction(WaitForChatAction action, MacroExecutor.ChatCapture capture) { private static boolean matchesChatAction(WaitForChatAction action, MacroExecutor.ChatCapture capture) {
return captureChatAction(action, capture, MacroExecutor.currentVariableContext()).isPresent(); return captureChatAction(action, capture, MacroLifecycle.currentVariableContext()).isPresent();
} }
private static java.util.Optional<java.util.Map<String, MacroValue>> captureChatAction(WaitForChatAction action, MacroExecutor.ChatCapture capture) { private static java.util.Optional<java.util.Map<String, MacroValue>> captureChatAction(WaitForChatAction action, MacroExecutor.ChatCapture capture) {
return captureChatAction(action, capture, MacroExecutor.currentVariableContext()); return captureChatAction(action, capture, MacroLifecycle.currentVariableContext());
} }
public static java.util.Optional<java.util.Map<String, MacroValue>> captureChatAction(WaitForChatAction action, MacroExecutor.ChatCapture capture, public static java.util.Optional<java.util.Map<String, MacroValue>> captureChatAction(WaitForChatAction action, MacroExecutor.ChatCapture capture,

View file

@ -14,7 +14,7 @@ final class MacroClientThread {
static void runOnClientThread(Minecraft mc, Runnable runnable) throws InterruptedException { static void runOnClientThread(Minecraft mc, Runnable runnable) throws InterruptedException {
if (PackHideState.isHardLocked()) return; if (PackHideState.isHardLocked()) return;
MacroExecutor.RunState scheduledRun = MacroExecutor.CURRENT_RUN.get(); MacroExecutor.RunState scheduledRun = MacroExecutor.CURRENT_RUN.get();
Runnable contextual = () -> MacroExecutor.withRunContext(scheduledRun, runnable); Runnable contextual = () -> MacroLifecycle.withRunContext(scheduledRun, runnable);
if (mc.isSameThread()) { if (mc.isSameThread()) {
if (PackHideState.isHardLocked()) return; if (PackHideState.isHardLocked()) return;
contextual.run(); contextual.run();
@ -48,14 +48,14 @@ final class MacroClientThread {
MacroExecutor.RunState scheduledRun = MacroExecutor.CURRENT_RUN.get(); MacroExecutor.RunState scheduledRun = MacroExecutor.CURRENT_RUN.get();
mc.execute(() -> { mc.execute(() -> {
if (PackHideState.isHardLocked()) return; if (PackHideState.isHardLocked()) return;
MacroExecutor.withRunContext(scheduledRun, runnable); MacroLifecycle.withRunContext(scheduledRun, runnable);
}); });
} }
static void runOnClientTick(Minecraft mc, Runnable runnable) throws InterruptedException { static void runOnClientTick(Minecraft mc, Runnable runnable) throws InterruptedException {
if (PackHideState.isHardLocked()) return; if (PackHideState.isHardLocked()) return;
MacroExecutor.RunState scheduledRun = MacroExecutor.CURRENT_RUN.get(); MacroExecutor.RunState scheduledRun = MacroExecutor.CURRENT_RUN.get();
Runnable contextual = () -> MacroExecutor.withRunContext(scheduledRun, runnable); Runnable contextual = () -> MacroLifecycle.withRunContext(scheduledRun, runnable);
if (mc.isSameThread()) { if (mc.isSameThread()) {
if (PackHideState.isHardLocked()) return; if (PackHideState.isHardLocked()) return;
@ -97,7 +97,7 @@ final class MacroClientThread {
MacroExecutor.RunState scheduledRun = MacroExecutor.CURRENT_RUN.get(); MacroExecutor.RunState scheduledRun = MacroExecutor.CURRENT_RUN.get();
java.util.function.Supplier<T> contextual = () -> { java.util.function.Supplier<T> contextual = () -> {
AtomicReference<T> value = new AtomicReference<>(fallback); AtomicReference<T> value = new AtomicReference<>(fallback);
MacroExecutor.withRunContext(scheduledRun, () -> value.set(supplier.get())); MacroLifecycle.withRunContext(scheduledRun, () -> value.set(supplier.get()));
return value.get(); return value.get();
}; };
if (mc.isSameThread()) { if (mc.isSameThread()) {
@ -130,7 +130,7 @@ final class MacroClientThread {
MacroExecutor.RunState scheduledRun = MacroExecutor.CURRENT_RUN.get(); MacroExecutor.RunState scheduledRun = MacroExecutor.CURRENT_RUN.get();
java.util.function.Supplier<T> contextual = () -> { java.util.function.Supplier<T> contextual = () -> {
AtomicReference<T> value = new AtomicReference<>(fallback); AtomicReference<T> value = new AtomicReference<>(fallback);
MacroExecutor.withRunContext(scheduledRun, () -> value.set(supplier.get())); MacroLifecycle.withRunContext(scheduledRun, () -> value.set(supplier.get()));
return value.get(); return value.get();
}; };
if (mc.isSameThread()) { if (mc.isSameThread()) {

View file

@ -17,7 +17,7 @@ final class MacroDispatcher {
if (!MacroDynamicBindings.apply(action, mc)) return; if (!MacroDynamicBindings.apply(action, mc)) return;
if (!MacroActionRunner.dynamicTextInputsAvailable(action, mc)) return; if (!MacroActionRunner.dynamicTextInputsAvailable(action, mc)) return;
MacroPrearm.clearOwnCaptureOutput(action); MacroPrearm.clearOwnCaptureOutput(action);
EnumSet<SharedClientResource> heldResources = MacroExecutor.acquireClientResources(action); EnumSet<SharedClientResource> heldResources = MacroLifecycle.acquireClientResources(action);
try { try {
if (!MacroActionRunner.waitForGuiBeforeAction(mc, action)) return; if (!MacroActionRunner.waitForGuiBeforeAction(mc, action)) return;
@ -28,7 +28,7 @@ final class MacroDispatcher {
if (action instanceof DelayAction) { if (action instanceof DelayAction) {
DelayAction da = (DelayAction) action; DelayAction da = (DelayAction) action;
if (da.useTicks) { if (da.useTicks) {
for (int t = 0; t < da.delayTicks && MacroExecutor.isCurrentRunActive(); t++) { for (int t = 0; t < da.delayTicks && MacroLifecycle.isCurrentRunActive(); t++) {
CompletableFuture<Void> tf = MacroConditionRegistry.waitForNextTick(); CompletableFuture<Void> tf = MacroConditionRegistry.waitForNextTick();
MacroRunLoop.waitForCondition(tf); MacroRunLoop.waitForCondition(tf);
} }
@ -36,7 +36,7 @@ final class MacroDispatcher {
Thread.sleep(da.delayMs); Thread.sleep(da.delayMs);
} }
} else if (action instanceof CustomMenuAction customMenu) { } else if (action instanceof CustomMenuAction customMenu) {
MacroExecutor.setCurrentStatus(customMenu.getDisplayName()); MacroLifecycle.setCurrentStatus(customMenu.getDisplayName());
customMenu.execute(mc); customMenu.execute(mc);
} else if (action instanceof WaitForPacketAction packetAction) { } else if (action instanceof WaitForPacketAction packetAction) {
packetAction.matchedPacket = null; packetAction.matchedPacket = null;
@ -51,29 +51,29 @@ final class MacroDispatcher {
MacroPacketWait.awaitPacket(""); MacroPacketWait.awaitPacket("");
} else { } else {
for (String target : targets) { for (String target : targets) {
if (!MacroExecutor.isCurrentRunActive()) break; if (!MacroLifecycle.isCurrentRunActive()) break;
MacroPacketWait.awaitPacket(target); MacroPacketWait.awaitPacket(target);
} }
} }
MacroPrearm.copyLastMatchedPacket(packetAction); MacroPrearm.copyLastMatchedPacket(packetAction);
} else if (action instanceof WaitPacketMatchAction wpma) { } else if (action instanceof WaitPacketMatchAction wpma) {
MacroExecutor.setCurrentStatus(wpma.getDisplayName()); MacroLifecycle.setCurrentStatus(wpma.getDisplayName());
MacroPrearm.waitForPacketMatch(wpma); MacroPrearm.waitForPacketMatch(wpma);
} else if (action instanceof WaitInventoryPredicateAction wipa) { } else if (action instanceof WaitInventoryPredicateAction wipa) {
MacroExecutor.setCurrentStatus(wipa.getDisplayName()); MacroLifecycle.setCurrentStatus(wipa.getDisplayName());
MacroRunLoop.waitForPredicate(() -> wipa.matches(mc), wipa.timeoutMs); MacroRunLoop.waitForPredicate(() -> wipa.matches(mc), wipa.timeoutMs);
} else if (action instanceof WaitDurabilityAction wda) { } else if (action instanceof WaitDurabilityAction wda) {
MacroExecutor.setCurrentStatus(wda.getDisplayName()); MacroLifecycle.setCurrentStatus(wda.getDisplayName());
if (wda.useNext) MacroDurability.waitForDurabilityUseNext(mc, wda); if (wda.useNext) MacroDurability.waitForDurabilityUseNext(mc, wda);
else MacroRunLoop.waitForPredicate(() -> wda.matches(mc), wda.timeoutMs); else MacroRunLoop.waitForPredicate(() -> wda.matches(mc), wda.timeoutMs);
} else if (action instanceof WaitFreeSlotsAction wfsa) { } else if (action instanceof WaitFreeSlotsAction wfsa) {
MacroExecutor.setCurrentStatus(wfsa.getDisplayName()); MacroLifecycle.setCurrentStatus(wfsa.getDisplayName());
MacroRunLoop.waitForPredicate(() -> wfsa.matches(mc), wfsa.timeoutMs); MacroRunLoop.waitForPredicate(() -> wfsa.matches(mc), wfsa.timeoutMs);
} else if (action instanceof WaitEntityTargetAction weta) { } else if (action instanceof WaitEntityTargetAction weta) {
MacroExecutor.setCurrentStatus(weta.getDisplayName()); MacroLifecycle.setCurrentStatus(weta.getDisplayName());
MacroRunLoop.waitForPredicate(() -> weta.matches(mc), weta.timeoutMs); MacroRunLoop.waitForPredicate(() -> weta.matches(mc), weta.timeoutMs);
} else if (action instanceof WaitGuiTypeAction wgta) { } else if (action instanceof WaitGuiTypeAction wgta) {
MacroExecutor.setCurrentStatus(wgta.getDisplayName()); MacroLifecycle.setCurrentStatus(wgta.getDisplayName());
MacroPrearm.clearCaptureOutputs(wgta); MacroPrearm.clearCaptureOutputs(wgta);
if (wgta.waitMode == WaitGuiTypeAction.WaitMode.CLOSE) MacroRunLoop.waitForPredicate(MacroRunLoop.guiClosePredicate(wgta, mc), wgta.timeoutMs); if (wgta.waitMode == WaitGuiTypeAction.WaitMode.CLOSE) MacroRunLoop.waitForPredicate(MacroRunLoop.guiClosePredicate(wgta, mc), wgta.timeoutMs);
else MacroRunLoop.waitForPredicate(() -> { else MacroRunLoop.waitForPredicate(() -> {
@ -88,14 +88,14 @@ final class MacroDispatcher {
postGuiFuture = MacroActionRunner.runTargetWaitInteractionAction(mc, action); postGuiFuture = MacroActionRunner.runTargetWaitInteractionAction(mc, action);
} else if (action instanceof WaitForHealthAction) { } else if (action instanceof WaitForHealthAction) {
WaitForHealthAction wh = (WaitForHealthAction) action; WaitForHealthAction wh = (WaitForHealthAction) action;
MacroExecutor.setCurrentStatus(wh.waitingStatusText()); MacroLifecycle.setCurrentStatus(wh.waitingStatusText());
try { try {
CompletableFuture<Void> future = MacroConditionRegistry.waitForHealth(wh.healthThreshold, wh.below); CompletableFuture<Void> future = MacroConditionRegistry.waitForHealth(wh.healthThreshold, wh.below);
MacroRunLoop.waitForCondition(future); MacroRunLoop.waitForCondition(future);
} catch (CancellationException e) { } } catch (CancellationException e) { }
} else if (action instanceof WaitForBlockAction) { } else if (action instanceof WaitForBlockAction) {
WaitForBlockAction wba = (WaitForBlockAction) action; WaitForBlockAction wba = (WaitForBlockAction) action;
MacroExecutor.setCurrentStatus(wba.getDisplayName()); MacroLifecycle.setCurrentStatus(wba.getDisplayName());
try { try {
CompletableFuture<Void> future = MacroConditionRegistry.waitForBlock(wba); CompletableFuture<Void> future = MacroConditionRegistry.waitForBlock(wba);
MacroRunLoop.waitForCondition(future); MacroRunLoop.waitForCondition(future);
@ -104,10 +104,10 @@ final class MacroDispatcher {
WaitForGuiAction wga = (WaitForGuiAction) action; WaitForGuiAction wga = (WaitForGuiAction) action;
MacroPrearm.clearCaptureOutputs(wga); MacroPrearm.clearCaptureOutputs(wga);
if (wga.waitMode == WaitForGuiAction.WaitMode.CLOSE) { if (wga.waitMode == WaitForGuiAction.WaitMode.CLOSE) {
MacroExecutor.setCurrentStatus("Waiting for GUI close: " + wga.guiTitle); MacroLifecycle.setCurrentStatus("Waiting for GUI close: " + wga.guiTitle);
MacroRunLoop.waitForPredicate(MacroRunLoop.guiClosePredicate(wga, mc), wga.timeoutMs); MacroRunLoop.waitForPredicate(MacroRunLoop.guiClosePredicate(wga, mc), wga.timeoutMs);
} else { } else {
MacroExecutor.setCurrentStatus("Waiting for GUI: " + wga.guiTitle); MacroLifecycle.setCurrentStatus("Waiting for GUI: " + wga.guiTitle);
MacroRunLoop.waitForPredicate(() -> { MacroRunLoop.waitForPredicate(() -> {
var captured = wga.captureGui(mc.gui.screen()); var captured = wga.captureGui(mc.gui.screen());
captured.ifPresent(values -> MacroPrearm.stageCapture(wga, values)); captured.ifPresent(values -> MacroPrearm.stageCapture(wga, values));
@ -120,7 +120,7 @@ final class MacroDispatcher {
ItemTarget cooldownTarget = MacroWorldActions.resolveItemTarget(wca.itemTarget, wca.itemName).resolveTemplate(mc); ItemTarget cooldownTarget = MacroWorldActions.resolveItemTarget(wca.itemTarget, wca.itemName).resolveTemplate(mc);
if (cooldownTarget == null) return; if (cooldownTarget == null) return;
String cooldownLabel = MacroWorldActions.describeItemTarget(cooldownTarget); String cooldownLabel = MacroWorldActions.describeItemTarget(cooldownTarget);
MacroExecutor.setCurrentStatus("Waiting for cooldown: " + MacroLifecycle.setCurrentStatus("Waiting for cooldown: " +
(!cooldownLabel.isEmpty() ? cooldownLabel : (wca.checkMainInteractionHand ? "Main Hand" : "Off Hand"))); (!cooldownLabel.isEmpty() ? cooldownLabel : (wca.checkMainInteractionHand ? "Main Hand" : "Off Hand")));
try { try {
CompletableFuture<Void> future = MacroConditionRegistry.waitForCooldown(cooldownTarget, wca.checkMainInteractionHand); CompletableFuture<Void> future = MacroConditionRegistry.waitForCooldown(cooldownTarget, wca.checkMainInteractionHand);
@ -128,7 +128,7 @@ final class MacroDispatcher {
} catch (CancellationException e) { } } catch (CancellationException e) { }
} else if (action instanceof WaitPosAction) { } else if (action instanceof WaitPosAction) {
WaitPosAction wpa = (WaitPosAction) action; WaitPosAction wpa = (WaitPosAction) action;
MacroExecutor.setCurrentStatus("Waiting for Pos: " + String.format("%.0f, %.0f, %.0f", wpa.x, wpa.y, wpa.z)); MacroLifecycle.setCurrentStatus("Waiting for Pos: " + String.format("%.0f, %.0f, %.0f", wpa.x, wpa.y, wpa.z));
try { try {
CompletableFuture<Void> future = MacroConditionRegistry.waitForPos( CompletableFuture<Void> future = MacroConditionRegistry.waitForPos(
wpa.x, wpa.y, wpa.z, wpa.leeway, wpa.checkRotation, wpa.yaw, wpa.pitch, wpa.rotLeeway); wpa.x, wpa.y, wpa.z, wpa.leeway, wpa.checkRotation, wpa.yaw, wpa.pitch, wpa.rotLeeway);
@ -138,69 +138,69 @@ final class MacroDispatcher {
MacroCaptureAutofill.runCaptureValueAction(mc, captureValue); MacroCaptureAutofill.runCaptureValueAction(mc, captureValue);
} else if (action instanceof WaitForChatAction) { } else if (action instanceof WaitForChatAction) {
WaitForChatAction wca = (WaitForChatAction) action; WaitForChatAction wca = (WaitForChatAction) action;
MacroExecutor.setCurrentStatus("Waiting for chat: " + wca.pattern); MacroLifecycle.setCurrentStatus("Waiting for chat: " + wca.pattern);
MacroPacketWait.awaitChat(wca); MacroPacketWait.awaitChat(wca);
} else if (action instanceof WaitForEntityAction) { } else if (action instanceof WaitForEntityAction) {
WaitForEntityAction wea = (WaitForEntityAction) action; WaitForEntityAction wea = (WaitForEntityAction) action;
MacroExecutor.setCurrentStatus(wea.getDisplayName()); MacroLifecycle.setCurrentStatus(wea.getDisplayName());
try { try {
MacroRunLoop.waitForPredicate(() -> wea.matchesEntityTarget(mc), wea.timeoutMs); MacroRunLoop.waitForPredicate(() -> wea.matchesEntityTarget(mc), wea.timeoutMs);
} catch (CancellationException e) { } } catch (CancellationException e) { }
} else if (action instanceof WaitForSoundAction) { } else if (action instanceof WaitForSoundAction) {
WaitForSoundAction wsa = (WaitForSoundAction) action; WaitForSoundAction wsa = (WaitForSoundAction) action;
String sndDesc = wsa.soundIds.isEmpty() ? "any" : wsa.soundIds.get(0); String sndDesc = wsa.soundIds.isEmpty() ? "any" : wsa.soundIds.get(0);
MacroExecutor.setCurrentStatus("Waiting for sound: " + sndDesc); MacroLifecycle.setCurrentStatus("Waiting for sound: " + sndDesc);
try { try {
CompletableFuture<Void> future = MacroConditionRegistry.waitForSound(wsa); CompletableFuture<Void> future = MacroConditionRegistry.waitForSound(wsa);
MacroRunLoop.waitForCondition(future); MacroRunLoop.waitForCondition(future);
} catch (CancellationException e) { } } catch (CancellationException e) { }
} else if (action instanceof WaitForSlotChangeAction) { } else if (action instanceof WaitForSlotChangeAction) {
WaitForSlotChangeAction wsca = (WaitForSlotChangeAction) action; WaitForSlotChangeAction wsca = (WaitForSlotChangeAction) action;
MacroExecutor.setCurrentStatus(wsca.getDisplayName()); MacroLifecycle.setCurrentStatus(wsca.getDisplayName());
try { try {
CompletableFuture<Void> future = MacroConditionRegistry.waitForSlotChange(wsca); CompletableFuture<Void> future = MacroConditionRegistry.waitForSlotChange(wsca);
MacroRunLoop.waitForCondition(future); MacroRunLoop.waitForCondition(future);
} catch (CancellationException e) { } } catch (CancellationException e) { }
} else if (action instanceof WaitForWorldChangeAction world) { } else if (action instanceof WaitForWorldChangeAction world) {
MacroExecutor.setCurrentStatus(world.getDisplayName()); MacroLifecycle.setCurrentStatus(world.getDisplayName());
try { try {
CompletableFuture<?> future = MacroRace.raceConditionFuture(mc, world); CompletableFuture<?> future = MacroRace.raceConditionFuture(mc, world);
MacroRace.waitForFutureDone(future, 0); MacroRace.waitForFutureDone(future, 0);
} catch (CancellationException e) { } } catch (CancellationException e) { }
} else if (action instanceof WaitForPositionDeltaAction wpda) { } else if (action instanceof WaitForPositionDeltaAction wpda) {
MacroExecutor.setCurrentStatus(wpda.getDisplayName()); MacroLifecycle.setCurrentStatus(wpda.getDisplayName());
try { try {
CompletableFuture<Void> future = MacroConditionRegistry.waitForPositionDelta(wpda.distance, wpda.horizontalOnly); CompletableFuture<Void> future = MacroConditionRegistry.waitForPositionDelta(wpda.distance, wpda.horizontalOnly);
MacroRunLoop.waitForCondition(future); MacroRunLoop.waitForCondition(future);
} catch (CancellationException e) { } } catch (CancellationException e) { }
} else if (action instanceof WaitForTeleportAction teleport) { } else if (action instanceof WaitForTeleportAction teleport) {
MacroExecutor.setCurrentStatus(teleport.getDisplayName()); MacroLifecycle.setCurrentStatus(teleport.getDisplayName());
try { try {
CompletableFuture<?> future = MacroRace.raceConditionFuture(mc, teleport); CompletableFuture<?> future = MacroRace.raceConditionFuture(mc, teleport);
MacroRace.waitForFutureDone(future, 0); MacroRace.waitForFutureDone(future, 0);
} catch (CancellationException e) { } } catch (CancellationException e) { }
} else if (action instanceof WaitGamemodeChangeAction gm) { } else if (action instanceof WaitGamemodeChangeAction gm) {
MacroExecutor.setCurrentStatus(gm.getDisplayName()); MacroLifecycle.setCurrentStatus(gm.getDisplayName());
try { try {
CompletableFuture<Void> future = MacroConditionRegistry.waitForGamemodeChange(gm); CompletableFuture<Void> future = MacroConditionRegistry.waitForGamemodeChange(gm);
MacroRace.waitForFutureDone(future, gm.timeoutMs); MacroRace.waitForFutureDone(future, gm.timeoutMs);
} catch (CancellationException e) { } } catch (CancellationException e) { }
} else if (action instanceof WaitMovementAction wm) { } else if (action instanceof WaitMovementAction wm) {
MacroExecutor.setCurrentStatus(wm.getDisplayName()); MacroLifecycle.setCurrentStatus(wm.getDisplayName());
try { try {
CompletableFuture<?> future = MacroRace.raceConditionFuture(mc, wm.resolveSubAction()); CompletableFuture<?> future = MacroRace.raceConditionFuture(mc, wm.resolveSubAction());
MacroRace.waitForFutureDone(future, 0); MacroRace.waitForFutureDone(future, 0);
} catch (CancellationException e) { } } catch (CancellationException e) { }
} else if (action instanceof WaitForLanStepAction) { } else if (action instanceof WaitForLanStepAction) {
WaitForLanStepAction wla = (WaitForLanStepAction) action; WaitForLanStepAction wla = (WaitForLanStepAction) action;
MacroExecutor.setCurrentStatus(wla.getDisplayName()); MacroLifecycle.setCurrentStatus(wla.getDisplayName());
try { try {
CompletableFuture<Void> future = MacroConditionRegistry.waitForLanStep(wla); CompletableFuture<Void> future = MacroConditionRegistry.waitForLanStep(wla);
MacroRunLoop.waitForCondition(future); MacroRunLoop.waitForCondition(future);
} catch (CancellationException e) { } } catch (CancellationException e) { }
} else if (action instanceof WaitForMacroStepAction) { } else if (action instanceof WaitForMacroStepAction) {
WaitForMacroStepAction wma = (WaitForMacroStepAction) action; WaitForMacroStepAction wma = (WaitForMacroStepAction) action;
MacroExecutor.setCurrentStatus(wma.getDisplayName()); MacroLifecycle.setCurrentStatus(wma.getDisplayName());
MacroRace.waitForMacroStep(wma); MacroRace.waitForMacroStep(wma);
} else if (action instanceof GoToAction) { } else if (action instanceof GoToAction) {
GoToAction ga = (GoToAction) action; GoToAction ga = (GoToAction) action;
@ -209,15 +209,15 @@ final class MacroDispatcher {
MoveAction ma = (MoveAction) action; MoveAction ma = (MoveAction) action;
if (ma.nonBlocking) { if (ma.nonBlocking) {
mc.execute(() -> ma.execute(mc)); mc.execute(() -> ma.execute(mc));
MacroExecutor.currentBackgroundMoves().put(ma, new int[]{ma.durationTicks - 1}); MacroLifecycle.currentBackgroundMoves().put(ma, new int[]{ma.durationTicks - 1});
} else { } else {
for (int t = 0; t < ma.durationTicks && MacroExecutor.isCurrentRunActive(); t++) { for (int t = 0; t < ma.durationTicks && MacroLifecycle.isCurrentRunActive(); t++) {
mc.execute(() -> ma.execute(mc)); mc.execute(() -> ma.execute(mc));
CompletableFuture<Void> tickFuture = MacroConditionRegistry.waitForNextTick(); CompletableFuture<Void> tickFuture = MacroConditionRegistry.waitForNextTick();
MacroRunLoop.waitForCondition(tickFuture); MacroRunLoop.waitForCondition(tickFuture);
} }
MacroExecutor.RunState movementRun = MacroExecutor.CURRENT_RUN.get(); MacroExecutor.RunState movementRun = MacroExecutor.CURRENT_RUN.get();
mc.execute(() -> MacroExecutor.releaseMoveIfUnused(movementRun, ma, mc)); mc.execute(() -> MacroLifecycle.releaseMoveIfUnused(movementRun, ma, mc));
} }
} else if (action instanceof LookAtBlockAction) { } else if (action instanceof LookAtBlockAction) {
LookAtBlockAction la = (LookAtBlockAction) action; LookAtBlockAction la = (LookAtBlockAction) action;
@ -265,7 +265,7 @@ final class MacroDispatcher {
CompletableFuture<Void> tickFuture = MacroConditionRegistry.waitForNextTick(); CompletableFuture<Void> tickFuture = MacroConditionRegistry.waitForNextTick();
MacroRunLoop.waitForCondition(tickFuture); MacroRunLoop.waitForCondition(tickFuture);
} else { } else {
for (int t = 0; t < ja.durationTicks && MacroExecutor.isCurrentRunActive(); t++) { for (int t = 0; t < ja.durationTicks && MacroLifecycle.isCurrentRunActive(); t++) {
CompletableFuture<Void> tickFuture = MacroConditionRegistry.waitForNextTick(); CompletableFuture<Void> tickFuture = MacroConditionRegistry.waitForNextTick();
MacroRunLoop.waitForCondition(tickFuture); MacroRunLoop.waitForCondition(tickFuture);
} }
@ -274,29 +274,29 @@ final class MacroDispatcher {
} else if (action instanceof SneakAction) { } else if (action instanceof SneakAction) {
SneakAction sna = (SneakAction) action; SneakAction sna = (SneakAction) action;
if (sna.persistent && sna.sneak) { if (sna.persistent && sna.sneak) {
MacroExecutor.currentPersistentActions().removeIf(p -> p instanceof SneakAction); MacroLifecycle.currentPersistentActions().removeIf(p -> p instanceof SneakAction);
MacroExecutor.currentPersistentActions().add(sna); MacroLifecycle.currentPersistentActions().add(sna);
} else if (!sna.sneak) { } else if (!sna.sneak) {
MacroExecutor.currentPersistentActions().removeIf(p -> p instanceof SneakAction); MacroLifecycle.currentPersistentActions().removeIf(p -> p instanceof SneakAction);
} }
if (sna.persistent || !sna.sneak) MacroClientThread.postOnClientThread(mc, () -> MacroExecutor.applyAggregateSneakState(mc), sna.isTickAligned()); if (sna.persistent || !sna.sneak) MacroClientThread.postOnClientThread(mc, () -> MacroLifecycle.applyAggregateSneakState(mc), sna.isTickAligned());
else MacroClientThread.postOnClientThread(mc, () -> sna.execute(mc), sna.isTickAligned()); else MacroClientThread.postOnClientThread(mc, () -> sna.execute(mc), sna.isTickAligned());
} else if (action instanceof SprintAction) { } else if (action instanceof SprintAction) {
SprintAction spa = (SprintAction) action; SprintAction spa = (SprintAction) action;
if (spa.persistent && spa.sprint) { if (spa.persistent && spa.sprint) {
MacroExecutor.currentPersistentActions().removeIf(p -> p instanceof SprintAction); MacroLifecycle.currentPersistentActions().removeIf(p -> p instanceof SprintAction);
MacroExecutor.currentPersistentActions().add(spa); MacroLifecycle.currentPersistentActions().add(spa);
} else if (!spa.sprint) { } else if (!spa.sprint) {
MacroExecutor.currentPersistentActions().removeIf(p -> p instanceof SprintAction); MacroLifecycle.currentPersistentActions().removeIf(p -> p instanceof SprintAction);
} }
if (spa.persistent || !spa.sprint) MacroClientThread.postOnClientThread(mc, () -> MacroExecutor.applyAggregateSprintState(mc), spa.isTickAligned()); if (spa.persistent || !spa.sprint) MacroClientThread.postOnClientThread(mc, () -> MacroLifecycle.applyAggregateSprintState(mc), spa.isTickAligned());
else MacroClientThread.postOnClientThread(mc, () -> spa.execute(mc), spa.isTickAligned()); else MacroClientThread.postOnClientThread(mc, () -> spa.execute(mc), spa.isTickAligned());
} else if (action instanceof NbtBookAction nba) { } else if (action instanceof NbtBookAction nba) {
int totalBooks = Math.max(1, nba.bookCount); int totalBooks = Math.max(1, nba.bookCount);
long delayMs = Math.max(1, nba.delayTicks) * 50L; long delayMs = Math.max(1, nba.delayTicks) * 50L;
boolean signedAny = false; boolean signedAny = false;
for (int b = 0; b < totalBooks; b++) { for (int b = 0; b < totalBooks; b++) {
if (!MacroExecutor.isCurrentRunActive()) break; if (!MacroLifecycle.isCurrentRunActive()) break;
final int bookIdx = b; final int bookIdx = b;
java.util.concurrent.CompletableFuture<Boolean> result = new java.util.concurrent.CompletableFuture<>(); java.util.concurrent.CompletableFuture<Boolean> result = new java.util.concurrent.CompletableFuture<>();
mc.execute(() -> result.complete(nba.executeSingleBook(mc, bookIdx, totalBooks))); mc.execute(() -> result.complete(nba.executeSingleBook(mc, bookIdx, totalBooks)));
@ -354,14 +354,14 @@ final class MacroDispatcher {
&& (xsa.transferMode == XCarryAction.TransferMode.CLICK && (xsa.transferMode == XCarryAction.TransferMode.CLICK
|| xsa.transferMode == XCarryAction.TransferMode.SAFE_CLICK)) { || xsa.transferMode == XCarryAction.TransferMode.SAFE_CLICK)) {
if (xsa.transferMode == XCarryAction.TransferMode.SAFE_CLICK) { if (xsa.transferMode == XCarryAction.TransferMode.SAFE_CLICK) {
MacroExecutor.setCurrentStatus("XCarry Safe"); MacroLifecycle.setCurrentStatus("XCarry Safe");
MacroXCarry.runXCarrySafeClickPutIn(mc, xsa); MacroXCarry.runXCarrySafeClickPutIn(mc, xsa);
} else { } else {
MacroExecutor.setCurrentStatus("XCarry Click"); MacroLifecycle.setCurrentStatus("XCarry Click");
MacroXCarry.runXCarryClickPutIn(mc, xsa); MacroXCarry.runXCarryClickPutIn(mc, xsa);
} }
} else { } else {
MacroExecutor.setCurrentStatus(switch (xsa.mode) { MacroLifecycle.setCurrentStatus(switch (xsa.mode) {
case PUT_IN -> "XCarry"; case PUT_IN -> "XCarry";
case TAKE_OUT -> "XCarry Out"; case TAKE_OUT -> "XCarry Out";
case DROP -> "XCarry Drop"; case DROP -> "XCarry Drop";
@ -378,10 +378,10 @@ final class MacroDispatcher {
MacroWorldActions.runCraftAction(mc, (CraftAction) action); MacroWorldActions.runCraftAction(mc, (CraftAction) action);
} else if (action instanceof autismclient.util.macro.StoreItemAction) { } else if (action instanceof autismclient.util.macro.StoreItemAction) {
autismclient.util.macro.StoreItemAction sia = (autismclient.util.macro.StoreItemAction) action; autismclient.util.macro.StoreItemAction sia = (autismclient.util.macro.StoreItemAction) action;
MacroExecutor.setCurrentStatus((sia.mode == autismclient.util.macro.StoreItemAction.Mode.LOOT ? "Looting" : "Storing") MacroLifecycle.setCurrentStatus((sia.mode == autismclient.util.macro.StoreItemAction.Mode.LOOT ? "Looting" : "Storing")
+ (sia.persistent ? " \u221e" : "")); + (sia.persistent ? " \u221e" : ""));
if (sia.persistent) { if (sia.persistent) {
while (MacroExecutor.isCurrentRunActive()) { while (MacroLifecycle.isCurrentRunActive()) {
try { MacroActionRunner.runStoreItemAction(mc, sia); } try { MacroActionRunner.runStoreItemAction(mc, sia); }
catch (InterruptedException e) { Thread.currentThread().interrupt(); break; } catch (InterruptedException e) { Thread.currentThread().interrupt(); break; }
catch (Exception e) { AutismClientMessaging.sendPrefixed("Store error: " + e.getMessage()); } catch (Exception e) { AutismClientMessaging.sendPrefixed("Store error: " + e.getMessage()); }
@ -396,7 +396,7 @@ final class MacroDispatcher {
} else if (action instanceof InventoryAuditAction auditAction } else if (action instanceof InventoryAuditAction auditAction
&& (auditAction.mode == InventoryAuditAction.Mode.DUPE && (auditAction.mode == InventoryAuditAction.Mode.DUPE
|| auditAction.mode == InventoryAuditAction.Mode.DUPE_SPAM)) { || auditAction.mode == InventoryAuditAction.Mode.DUPE_SPAM)) {
MacroExecutor.setCurrentStatus("Dupe: " + auditAction.dupeVector.name() + " " + auditAction.openMode.name()); MacroLifecycle.setCurrentStatus("Dupe: " + auditAction.dupeVector.name() + " " + auditAction.openMode.name());
try { try {
auditAction.executeDupe(mc); auditAction.executeDupe(mc);
} catch (InterruptedException ie) { } catch (InterruptedException ie) {
@ -414,11 +414,11 @@ final class MacroDispatcher {
java.util.List<net.minecraft.network.protocol.Packet<?>> preGenerated = java.util.List<net.minecraft.network.protocol.Packet<?>> preGenerated =
MacroActionRunner.preGeneratePacketsForRepeat(tsa.preGenCount, mc); MacroActionRunner.preGeneratePacketsForRepeat(tsa.preGenCount, mc);
long targetTick = mc.level.getGameTime() + tsa.tickOffset; long targetTick = mc.level.getGameTime() + tsa.tickOffset;
MacroExecutor.setCurrentStatus("Tick Sync -> " + targetTick + " (" + preGenerated.size() + " pkts)"); MacroLifecycle.setCurrentStatus("Tick Sync -> " + targetTick + " (" + preGenerated.size() + " pkts)");
while (MacroExecutor.isCurrentRunActive() && mc.level.getGameTime() < targetTick) { while (MacroLifecycle.isCurrentRunActive() && mc.level.getGameTime() < targetTick) {
java.util.concurrent.locks.LockSupport.parkNanos(1_000_000L); java.util.concurrent.locks.LockSupport.parkNanos(1_000_000L);
} }
if (MacroExecutor.isCurrentRunActive()) { if (MacroLifecycle.isCurrentRunActive()) {
MacroRender.executePreGeneratedBurst(mc, preGenerated); MacroRender.executePreGeneratedBurst(mc, preGenerated);
MacroExecutor.RepeatPacketContext context = MacroExecutor.REPEAT_PACKET_CONTEXT.get(); MacroExecutor.RepeatPacketContext context = MacroExecutor.REPEAT_PACKET_CONTEXT.get();
if (context != null) MacroExecutor.REPEAT_PACKET_SKIP.set(MacroRender.countPreGeneratedActions(context.macro(), context.startIdx(), preGenerated.size(), context.endIdx())); if (context != null) MacroExecutor.REPEAT_PACKET_SKIP.set(MacroRender.countPreGeneratedActions(context.macro(), context.startIdx(), preGenerated.size(), context.endIdx()));
@ -430,13 +430,13 @@ final class MacroDispatcher {
MacroActionRunner.preGeneratePacketsForRepeat(rsa.preGenCount, mc); MacroActionRunner.preGeneratePacketsForRepeat(rsa.preGenCount, mc);
int baseRevision = mc.player.containerMenu.getStateId(); int baseRevision = mc.player.containerMenu.getStateId();
int targetRevision = baseRevision + rsa.revisionOffset; int targetRevision = baseRevision + rsa.revisionOffset;
MacroExecutor.setCurrentStatus("Rev Sync -> " + targetRevision + " (" + preGenerated.size() + " pkts)"); MacroLifecycle.setCurrentStatus("Rev Sync -> " + targetRevision + " (" + preGenerated.size() + " pkts)");
while (MacroExecutor.isCurrentRunActive()) { while (MacroLifecycle.isCurrentRunActive()) {
if (mc.player == null || mc.player.containerMenu == null) break; if (mc.player == null || mc.player.containerMenu == null) break;
if (mc.player.containerMenu.getStateId() >= targetRevision) break; if (mc.player.containerMenu.getStateId() >= targetRevision) break;
java.util.concurrent.locks.LockSupport.parkNanos(500_000L); java.util.concurrent.locks.LockSupport.parkNanos(500_000L);
} }
if (MacroExecutor.isCurrentRunActive() && mc.player != null && mc.player.containerMenu != null) { if (MacroLifecycle.isCurrentRunActive() && mc.player != null && mc.player.containerMenu != null) {
MacroRender.executePreGeneratedBurst(mc, preGenerated); MacroRender.executePreGeneratedBurst(mc, preGenerated);
MacroExecutor.RepeatPacketContext context = MacroExecutor.REPEAT_PACKET_CONTEXT.get(); MacroExecutor.RepeatPacketContext context = MacroExecutor.REPEAT_PACKET_CONTEXT.get();
if (context != null) MacroExecutor.REPEAT_PACKET_SKIP.set(MacroRender.countPreGeneratedActions(context.macro(), context.startIdx(), preGenerated.size(), context.endIdx())); if (context != null) MacroExecutor.REPEAT_PACKET_SKIP.set(MacroRender.countPreGeneratedActions(context.macro(), context.startIdx(), preGenerated.size(), context.endIdx()));
@ -447,22 +447,22 @@ final class MacroDispatcher {
java.util.List<net.minecraft.network.protocol.Packet<?>> preGenerated = java.util.List<net.minecraft.network.protocol.Packet<?>> preGenerated =
MacroActionRunner.preGeneratePacketsForRepeat(stsa.preGenCount, mc); MacroActionRunner.preGeneratePacketsForRepeat(stsa.preGenCount, mc);
int sampleWaitMs = 0; int sampleWaitMs = 0;
while (MacroExecutor.isCurrentRunActive() && !ServerTickTracker.isReady() && sampleWaitMs < stsa.maxWaitMs) { while (MacroLifecycle.isCurrentRunActive() && !ServerTickTracker.isReady() && sampleWaitMs < stsa.maxWaitMs) {
float progress = ServerTickTracker.getWarmupProgress(); float progress = ServerTickTracker.getWarmupProgress();
MacroExecutor.setCurrentStatus(String.format("ServerSync warmup %.0f%% (%d samples, %dms)", MacroLifecycle.setCurrentStatus(String.format("ServerSync warmup %.0f%% (%d samples, %dms)",
progress * 100, ServerTickTracker.getSampleCount(), ServerTickTracker.getTrackingTimeMs())); progress * 100, ServerTickTracker.getSampleCount(), ServerTickTracker.getTrackingTimeMs()));
Thread.sleep(50); Thread.sleep(50);
sampleWaitMs += 50; sampleWaitMs += 50;
} }
if (!MacroExecutor.isCurrentRunActive()) return; if (!MacroLifecycle.isCurrentRunActive()) return;
long optimalTime = ServerTickTracker.getOptimalSendTime(stsa.bufferMs, stsa.ignorePing); long optimalTime = ServerTickTracker.getOptimalSendTime(stsa.bufferMs, stsa.ignorePing);
long msUntil = (optimalTime - System.nanoTime()) / 1_000_000L; long msUntil = (optimalTime - System.nanoTime()) / 1_000_000L;
int ping = ServerTickTracker.getPingMs(); int ping = ServerTickTracker.getPingMs();
String pingStr = stsa.ignorePing ? " (no ping)" : " ping:" + ping + "ms"; String pingStr = stsa.ignorePing ? " (no ping)" : " ping:" + ping + "ms";
MacroExecutor.setCurrentStatus("ServerSync in " + Math.max(0, msUntil) + "ms" + pingStr + " (" + preGenerated.size() + " pkts)"); MacroLifecycle.setCurrentStatus("ServerSync in " + Math.max(0, msUntil) + "ms" + pingStr + " (" + preGenerated.size() + " pkts)");
long startWait = System.nanoTime(); long startWait = System.nanoTime();
long maxWaitNanos = stsa.maxWaitMs * 1_000_000L; long maxWaitNanos = stsa.maxWaitMs * 1_000_000L;
while (MacroExecutor.isCurrentRunActive()) { while (MacroLifecycle.isCurrentRunActive()) {
long now = System.nanoTime(); long now = System.nanoTime();
if ((now - startWait) >= maxWaitNanos) break; if ((now - startWait) >= maxWaitNanos) break;
if (now >= optimalTime) break; if (now >= optimalTime) break;
@ -473,7 +473,7 @@ final class MacroDispatcher {
Thread.onSpinWait(); Thread.onSpinWait();
} }
} }
if (MacroExecutor.isCurrentRunActive()) { if (MacroLifecycle.isCurrentRunActive()) {
MacroRender.executePreGeneratedBurst(mc, preGenerated); MacroRender.executePreGeneratedBurst(mc, preGenerated);
MacroExecutor.RepeatPacketContext context = MacroExecutor.REPEAT_PACKET_CONTEXT.get(); MacroExecutor.RepeatPacketContext context = MacroExecutor.REPEAT_PACKET_CONTEXT.get();
if (context != null) MacroExecutor.REPEAT_PACKET_SKIP.set(MacroRender.countPreGeneratedActions(context.macro(), context.startIdx(), preGenerated.size(), context.endIdx())); if (context != null) MacroExecutor.REPEAT_PACKET_SKIP.set(MacroRender.countPreGeneratedActions(context.macro(), context.startIdx(), preGenerated.size(), context.endIdx()));
@ -481,10 +481,10 @@ final class MacroDispatcher {
AutismClientMessaging.sendPrefixed("ServerSync: " + preGenerated.size() + " pkts (+" + actualDelay + "ms)"); AutismClientMessaging.sendPrefixed("ServerSync: " + preGenerated.size() + " pkts (+" + actualDelay + "ms)");
} }
} else if (action instanceof BundleDupeV2Action bundleV2) { } else if (action instanceof BundleDupeV2Action bundleV2) {
MacroExecutor.setCurrentStatus("Bundle Dupe V2"); MacroLifecycle.setCurrentStatus("Bundle Dupe V2");
bundleV2.execute(mc); bundleV2.execute(mc);
} else if (action instanceof RollbackAction rollback) { } else if (action instanceof RollbackAction rollback) {
MacroExecutor.setCurrentStatus("Rollback"); MacroLifecycle.setCurrentStatus("Rollback");
try { try {
rollback.executeRollback(mc); rollback.executeRollback(mc);
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -494,7 +494,7 @@ final class MacroDispatcher {
} }
} else if (action instanceof StopMacroAction) { } else if (action instanceof StopMacroAction) {
StopMacroAction stopAction = (StopMacroAction) action; StopMacroAction stopAction = (StopMacroAction) action;
if (stopAction.target == StopMacroAction.StopTarget.SELF) MacroExecutor.stopCurrentRun(); if (stopAction.target == StopMacroAction.StopTarget.SELF) MacroLifecycle.stopCurrentRun();
else stopAction.execute(mc); else stopAction.execute(mc);
} else if (action instanceof UseItemPhaseAction phaseAction) { } else if (action instanceof UseItemPhaseAction phaseAction) {
MacroActionRunner.runUseItemPhaseAction(mc, phaseAction); MacroActionRunner.runUseItemPhaseAction(mc, phaseAction);
@ -508,7 +508,7 @@ final class MacroDispatcher {
} else if (module != null && module.useInstantExecutionMode()) { } else if (module != null && module.useInstantExecutionMode()) {
java.util.concurrent.CountDownLatch latch = new java.util.concurrent.CountDownLatch(1); java.util.concurrent.CountDownLatch latch = new java.util.concurrent.CountDownLatch(1);
MacroExecutor.RunState scheduledRun = MacroExecutor.CURRENT_RUN.get(); MacroExecutor.RunState scheduledRun = MacroExecutor.CURRENT_RUN.get();
mc.execute(() -> MacroExecutor.withRunContext(scheduledRun, () -> { mc.execute(() -> MacroLifecycle.withRunContext(scheduledRun, () -> {
try { try {
action.execute(mc); action.execute(mc);
} catch (Exception e) { } catch (Exception e) {
@ -529,20 +529,20 @@ final class MacroDispatcher {
MacroPrearm.commitConditionOutput(action, mc); MacroPrearm.commitConditionOutput(action, mc);
if (postGuiFuture != null && MacroExecutor.isCurrentRunActive()) { if (postGuiFuture != null && MacroLifecycle.isCurrentRunActive()) {
try { try {
MacroRunLoop.waitForCondition(postGuiFuture); MacroRunLoop.waitForCondition(postGuiFuture);
} catch (java.util.concurrent.CancellationException e) { } } catch (java.util.concurrent.CancellationException e) { }
} }
if (MacroExecutor.isCurrentRunActive() && !MacroActionRunner.isInstantInventoryAction(action) && module != null && module.useInstantExecutionMode()) { if (MacroLifecycle.isCurrentRunActive() && !MacroActionRunner.isInstantInventoryAction(action) && module != null && module.useInstantExecutionMode()) {
int delayUs = module.getActionDelayUs(); int delayUs = module.getActionDelayUs();
if (delayUs > 0) java.util.concurrent.locks.LockSupport.parkNanos(delayUs * 1000L); if (delayUs > 0) java.util.concurrent.locks.LockSupport.parkNanos(delayUs * 1000L);
else Thread.onSpinWait(); else Thread.onSpinWait();
} }
} finally { } finally {
MacroRaycastAim.release(); MacroRaycastAim.release();
MacroExecutor.releaseClientResources(heldResources); MacroLifecycle.releaseClientResources(heldResources);
} }
} }
} }

View file

@ -15,7 +15,7 @@ final class MacroDurability {
public static void waitForDurabilityUseNext(Minecraft mc, WaitDurabilityAction action) throws InterruptedException { public static void waitForDurabilityUseNext(Minecraft mc, WaitDurabilityAction action) throws InterruptedException {
AtomicReference<DurabilityUseNextSession> sessionRef = new AtomicReference<>(); AtomicReference<DurabilityUseNextSession> sessionRef = new AtomicReference<>();
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
while (MacroExecutor.isCurrentRunActive()) { while (MacroLifecycle.isCurrentRunActive()) {
if (Boolean.TRUE.equals(MacroClientThread.callOnClientThread(mc, () -> tickDurabilityUseNext(mc, action, sessionRef), Boolean.FALSE))) { if (Boolean.TRUE.equals(MacroClientThread.callOnClientThread(mc, () -> tickDurabilityUseNext(mc, action, sessionRef), Boolean.FALSE))) {
return; return;
} }

View file

@ -92,22 +92,22 @@ public class MacroExecutor {
SHARED_RESOURCE_LOCKS.put(resource, new ReentrantLock(true)); SHARED_RESOURCE_LOCKS.put(resource, new ReentrantLock(true));
} }
} }
private static final AtomicLong NEXT_RUN_ID = new AtomicLong(1L); static final AtomicLong NEXT_RUN_ID = new AtomicLong(1L);
static final java.util.LinkedHashMap<Long, RunState> ACTIVE_RUNS = new java.util.LinkedHashMap<>(); static final java.util.LinkedHashMap<Long, RunState> ACTIVE_RUNS = new java.util.LinkedHashMap<>();
private static final java.util.concurrent.ConcurrentHashMap<Long, RunState> RUNS_BY_ID = new java.util.concurrent.ConcurrentHashMap<>(); static final java.util.concurrent.ConcurrentHashMap<Long, RunState> RUNS_BY_ID = new java.util.concurrent.ConcurrentHashMap<>();
private static final AtomicLong RUN_STATE_REVISION = new AtomicLong(); static final AtomicLong RUN_STATE_REVISION = new AtomicLong();
static final ThreadLocal<RunState> CURRENT_RUN = new ThreadLocal<>(); static final ThreadLocal<RunState> CURRENT_RUN = new ThreadLocal<>();
static final ThreadLocal<Boolean> SUPPRESS_POST_GUI_AFTER = ThreadLocal.withInitial(() -> false); static final ThreadLocal<Boolean> SUPPRESS_POST_GUI_AFTER = ThreadLocal.withInitial(() -> false);
private static volatile RunState primaryRun = null; static volatile RunState primaryRun = null;
private static volatile boolean visibleRunActive; static volatile boolean visibleRunActive;
private static AutismMacro currentMacro = null; static AutismMacro currentMacro = null;
private static Thread macroThread = null; static Thread macroThread = null;
static final AtomicReference<String> lastReceivedPacket = new AtomicReference<>(""); static final AtomicReference<String> lastReceivedPacket = new AtomicReference<>("");
private static String currentStatus = ""; static String currentStatus = "";
private static volatile int currentStepIndex = -1; static volatile int currentStepIndex = -1;
static volatile int totalSteps = 0; static volatile int totalSteps = 0;
static final AtomicBoolean isWaitingForPacket = new AtomicBoolean(false); static final AtomicBoolean isWaitingForPacket = new AtomicBoolean(false);
@ -142,10 +142,10 @@ public class MacroExecutor {
static volatile double rotationSpeed; static volatile double rotationSpeed;
static volatile int rotationAlignedFrames; static volatile int rotationAlignedFrames;
private static final java.util.concurrent.CopyOnWriteArrayList<MacroAction> persistentActions = static final java.util.concurrent.CopyOnWriteArrayList<MacroAction> persistentActions =
new java.util.concurrent.CopyOnWriteArrayList<>(); new java.util.concurrent.CopyOnWriteArrayList<>();
private static final java.util.concurrent.ConcurrentHashMap<MoveAction, int[]> backgroundMoves = static final java.util.concurrent.ConcurrentHashMap<MoveAction, int[]> backgroundMoves =
new java.util.concurrent.ConcurrentHashMap<>(); new java.util.concurrent.ConcurrentHashMap<>();
static final ThreadLocal<RepeatPacketContext> REPEAT_PACKET_CONTEXT = new ThreadLocal<>(); static final ThreadLocal<RepeatPacketContext> REPEAT_PACKET_CONTEXT = new ThreadLocal<>();
static final ThreadLocal<Integer> REPEAT_PACKET_SKIP = ThreadLocal.withInitial(() -> 0); static final ThreadLocal<Integer> REPEAT_PACKET_SKIP = ThreadLocal.withInitial(() -> 0);
@ -262,609 +262,54 @@ public class MacroExecutor {
} }
} }
private static final int FLOW_JUMP_BURST_CAP = 100_000; static final int FLOW_JUMP_BURST_CAP = 100_000;
private static final int FLOW_JUMP_HARD_CAP = 5_000_000; static final int FLOW_JUMP_HARD_CAP = 5_000_000;
private static java.util.Map<String, Integer> flowLabels(RunState run, AutismMacro macro) {
java.util.Map<String, Integer> cached = run.labelIndex;
if (cached != null) return cached;
java.util.LinkedHashMap<String, Integer> built = new java.util.LinkedHashMap<>();
for (int k = 0; k < macro.actions.size(); k++) {
if (macro.actions.get(k) instanceof LabelAction la) {
String key = la.normalizedName();
if (!key.isEmpty() && !built.containsKey(key)) built.put(key, k);
}
}
run.labelIndex = built;
return built;
}
private static Integer resolveFlowTarget(RunState run, AutismMacro macro, int i, FlowAction flow, Minecraft mc) {
return switch (flow.target) {
case STOP -> null;
case TOP -> 0;
case END -> macro.actions.size();
case FORWARD -> i + 1 + Math.max(0, flow.amount);
case BACK -> i - Math.max(0, flow.amount);
case STEP -> Math.max(1, flow.amount) - 1;
case LABEL -> {
String name = LabelAction.normalize(MacroVariables.expand(flow.labelName, mc));
Integer idx = flowLabels(run, macro).get(name);
if (idx == null) {
AutismClientMessaging.sendPrefixed("§eFlow: label '" + flow.labelName + "' not found.");
yield flow.onMissingLabel == FlowAction.MissingPolicy.STOP ? null : i + 1;
}
yield idx;
}
};
}
static int performFlowJump(RunState run, AutismMacro macro, int currentI, FlowAction flow, Minecraft mc) {
run.branchElseStart = -1;
run.branchElseCount = 0;
Integer dest = resolveFlowTarget(run, macro, currentI, flow, mc);
if (dest == null) return Integer.MIN_VALUE;
int size = macro.actions.size();
int target = Math.max(0, Math.min(size, dest));
if (target <= currentI) {
run.totalJumpsThisRun++;
run.jumpBudget++;
if (FLOW_JUMP_HARD_CAP >= 0 && run.totalJumpsThisRun > FLOW_JUMP_HARD_CAP) {
AutismClientMessaging.sendPrefixed("§cMacro aborted: jump limit exceeded (runaway loop).");
return Integer.MIN_VALUE;
}
if (run.jumpBudget >= FLOW_JUMP_BURST_CAP) {
run.jumpBudget = 0;
try { MacroRunLoop.waitForCondition(MacroConditionRegistry.waitForNextTick()); } catch (Exception ignored) { }
}
} else {
run.jumpBudget = 0;
}
return target - 1;
}
static boolean isCurrentRunActive() {
if (PackHideState.isHardLocked()) return false;
RunState run = CURRENT_RUN.get();
if (run != null) return run.running.get();
return isRunning.get();
}
public static boolean isCurrentActionRunActive() { public static boolean isCurrentActionRunActive() {
return isCurrentRunActive(); return MacroLifecycle.isCurrentActionRunActive();
}
static CopyOnWriteArrayList<MacroAction> currentPersistentActions() {
RunState run = CURRENT_RUN.get();
return run != null ? run.persistentActions : persistentActions;
}
static ConcurrentHashMap<MoveAction, int[]> currentBackgroundMoves() {
RunState run = CURRENT_RUN.get();
return run != null ? run.backgroundMoves : backgroundMoves;
}
static void setCurrentStatus(String status) {
RunState run = CURRENT_RUN.get();
if (run != null) run.status = status == null ? "" : status;
currentStatus = status == null ? "" : status;
}
static void setCurrentStep(int step, int total) {
RunState run = CURRENT_RUN.get();
if (run != null) {
run.currentStepIndex = step;
run.totalSteps = total;
}
currentStepIndex = step;
totalSteps = total;
}
static void markStepCompleted(int stepOneBased) {
RunState run = CURRENT_RUN.get();
if (run != null) {
run.lastCompletedStep = Math.max(run.lastCompletedStep, stepOneBased);
}
}
static int stepOverrideEndIndex(AutismMacro macro, int headerIndex, int coveredRows) {
int last = macro == null ? headerIndex : macro.actions.size() - 1;
long end = (long) headerIndex + Math.max(0, coveredRows);
return (int) Math.max(headerIndex, Math.min(last, end));
}
static void armFpsStepOverride(RunState run, int headerIndex, int endIndexInclusive, int fpsLimit) {
if (run == null) return;
run.fpsStepHeaderIndex = headerIndex;
run.fpsStepEndIndex = endIndexInclusive;
FpsLimitController.applyUntilCleared(run.id, fpsLimit);
}
static void armPingStepOverride(RunState run, int headerIndex, int endIndexInclusive,
int delayMs, boolean realIncoming, boolean realOutgoing) {
if (run == null) return;
run.pingStepHeaderIndex = headerIndex;
run.pingStepEndIndex = endIndexInclusive;
PingSpoofController.applyUntilCleared(run.id, delayMs, realIncoming, realOutgoing);
}
static void clearFpsStepOverride(RunState run) {
if (run == null || run.fpsStepHeaderIndex < 0) return;
run.fpsStepHeaderIndex = -1;
run.fpsStepEndIndex = -1;
FpsLimitController.clear(run.id);
}
static void clearPingStepOverride(RunState run) {
if (run == null || run.pingStepHeaderIndex < 0) return;
run.pingStepHeaderIndex = -1;
run.pingStepEndIndex = -1;
PingSpoofController.clearMacro(run.id);
}
static void awaitBackgroundTimedOverrides(RunState run) throws InterruptedException {
if (run == null) return;
long deadline = Math.max(run.fpsBackgroundDeadlineNanos, run.pingBackgroundDeadlineNanos);
long remaining;
while (isCurrentRunActive() && (remaining = deadline - System.nanoTime()) > 0L) {
Thread.sleep(Math.min(25L, remaining / 1_000_000L + 1L));
}
}
static void updateStepBoundOverrides(RunState run, int index) {
if (run == null) return;
if (run.fpsStepHeaderIndex >= 0 && (index > run.fpsStepEndIndex || index <= run.fpsStepHeaderIndex)) {
clearFpsStepOverride(run);
}
if (run.pingStepHeaderIndex >= 0 && (index > run.pingStepEndIndex || index <= run.pingStepHeaderIndex)) {
clearPingStepOverride(run);
}
}
static void stopCurrentRun() {
RunState run = CURRENT_RUN.get();
if (run != null) {
run.running.set(false);
} else {
stop();
}
}
static void stopCurrentActionRun() {
stopCurrentRun();
}
private static EnumSet<SharedClientResource> resourcesForAction(MacroAction action) {
return MacroActionResources.resourcesForAction(action);
}
static EnumSet<SharedClientResource> acquireClientResources(MacroAction action) throws InterruptedException {
return acquireClientResources(resourcesForAction(action));
}
static EnumSet<SharedClientResource> acquireClientResources(EnumSet<SharedClientResource> resources) throws InterruptedException {
EnumSet<SharedClientResource> acquired = EnumSet.noneOf(SharedClientResource.class);
try {
for (SharedClientResource resource : SharedClientResource.values()) {
if (resources.contains(resource)) {
if (!isCurrentRunActive()) throw new InterruptedException("Macro stopped");
SHARED_RESOURCE_LOCKS.get(resource).lockInterruptibly();
acquired.add(resource);
if (!isCurrentRunActive()) throw new InterruptedException("Macro stopped");
}
}
} catch (InterruptedException e) {
releaseClientResources(acquired);
throw e;
}
return acquired;
}
static EnumSet<SharedClientResource> resourcesForActions(java.util.List<MacroAction> actions) {
return MacroActionResources.resourcesForActions(actions);
}
static void releaseClientResources(EnumSet<SharedClientResource> resources) {
if (resources == null || resources.isEmpty()) return;
SharedClientResource[] ordered = SharedClientResource.values();
for (int i = ordered.length - 1; i >= 0; i--) {
SharedClientResource resource = ordered[i];
if (resources.contains(resource)) {
ReentrantLock lock = SHARED_RESOURCE_LOCKS.get(resource);
if (lock.isHeldByCurrentThread()) lock.unlock();
}
}
}
static MacroVariableContext currentVariableContext() {
RunState run = CURRENT_RUN.get();
return run == null ? null : run.variables;
}
static void withRunContext(RunState run, Runnable task) {
RunState previous = CURRENT_RUN.get();
if (run != null) CURRENT_RUN.set(run);
try {
task.run();
} finally {
if (previous != null) CURRENT_RUN.set(previous);
else CURRENT_RUN.remove();
}
}
static InlineNextActions collectInlineNextActions(java.util.List<MacroAction> actions, int currentIndex) {
if (actions == null || currentIndex < 0 || currentIndex >= actions.size() - 1) return InlineNextActions.empty();
java.util.ArrayList<MacroAction> collected = new java.util.ArrayList<>();
int lastIndex = -1;
for (int j = currentIndex + 1; j < actions.size(); j++) {
MacroAction candidate = actions.get(j);
if (candidate instanceof DisconnectAction
|| candidate instanceof RaceAction
|| candidate instanceof ReportAction
|| candidate instanceof RepeatAction
|| candidate instanceof BranchAction
|| candidate instanceof FinallyAction) {
break;
}
if (candidate == null || !candidate.isEnabled()) continue;
if (!RaceAction.isBodyAction(candidate)) continue;
collected.add(candidate);
lastIndex = j;
}
return collected.isEmpty() ? InlineNextActions.empty() : new InlineNextActions(java.util.List.copyOf(collected), lastIndex);
}
private static volatile java.util.List<RunState> ACTIVE_RUN_LIST = java.util.List.of();
private static void rebuildActiveRunListLocked() {
ACTIVE_RUN_LIST = java.util.List.copyOf(ACTIVE_RUNS.values());
}
static java.util.List<RunState> activeRunSnapshot() {
return ACTIVE_RUN_LIST;
}
static void finishCurrentRun() {
RunState run = CURRENT_RUN.get();
if (run == null) return;
if (!run.finished.compareAndSet(false, true)) return;
requestStop(run, false);
clearFpsStepOverride(run);
clearPingStepOverride(run);
synchronized (RUN_LOCK) {
ACTIVE_RUNS.remove(run.id);
RUNS_BY_ID.remove(run.id);
rebuildActiveRunListLocked();
if (ACTIVE_RUNS.isEmpty()) MacroCaptureAutofill.allRunsStoppedAtMs = System.currentTimeMillis();
RUN_STATE_REVISION.incrementAndGet();
refreshPrimaryRunLocked();
}
if (!isRunning.get()) {
AutismInstaBreakRenderer.clear();
FpsLimitController.clearAll();
PingSpoofController.clearAllMacros();
}
CURRENT_RUN.remove();
}
private static boolean hasRunningRunsLocked() {
for (RunState run : ACTIVE_RUNS.values()) {
if (run.running.get()) return true;
}
return false;
}
private static RunState firstVisibleRunLocked() {
for (RunState run : ACTIVE_RUNS.values()) {
if (run.running.get() && !run.options.hiddenFromProgressHud()) return run;
}
return null;
}
private static int activeRunCountLocked() {
int count = 0;
for (RunState run : ACTIVE_RUNS.values()) {
if (run.running.get()) count++;
}
return count;
}
static boolean hasMacroCapacity(int activeCount) {
return Math.max(0, activeCount) < MAX_CONCURRENT_MACROS;
}
private static void refreshPrimaryRunLocked() {
primaryRun = firstVisibleRunLocked();
visibleRunActive = primaryRun != null;
currentMacro = primaryRun != null ? primaryRun.macro : null;
currentStatus = primaryRun != null ? primaryRun.status : "";
currentStepIndex = primaryRun != null ? primaryRun.currentStepIndex : -1;
totalSteps = primaryRun != null ? primaryRun.totalSteps : 0;
isRunning.set(hasRunningRunsLocked());
}
private static boolean hasRunningRuns() {
synchronized (RUN_LOCK) {
return hasRunningRunsLocked();
}
} }
public static boolean isVisibleRunning() { public static boolean isVisibleRunning() {
return visibleRunActive; return MacroLifecycle.isVisibleRunning();
} }
public static boolean isControllingInput() { public static boolean isControllingInput() {
ReentrantLock inputLock = SHARED_RESOURCE_LOCKS.get(SharedClientResource.INPUT); return MacroLifecycle.isControllingInput();
if (inputLock != null && inputLock.isLocked()) return true;
if (!backgroundMoves.isEmpty()) return true;
for (MacroAction action : persistentActions) {
if (action instanceof MoveAction || action instanceof JumpAction || action instanceof SneakAction || action instanceof SprintAction) return true;
}
synchronized (RUN_LOCK) {
for (RunState run : ACTIVE_RUNS.values()) {
if (run == null || !run.running.get()) continue;
if (!run.backgroundMoves.isEmpty()) return true;
for (MacroAction action : run.persistentActions) {
if (action instanceof MoveAction || action instanceof JumpAction || action instanceof SneakAction || action instanceof SprintAction) return true;
}
}
}
return false;
}
static void broadcastStepProgress(RunState run, int step, int total, String macroName) {
if (run != null && run.options.skipLanProgress()) return;
try {
autismclient.util.AutismLANSync sync = autismclient.util.AutismLANSync.getInstance();
if (sync.isInSession()) {
sync.broadcastStepProgress(step, total, macroName);
}
} catch (Exception ignored) { }
}
private static void requestStop(RunState run, boolean interruptThread) {
if (run == null) return;
if (run.running.getAndSet(false)) {
RUN_STATE_REVISION.incrementAndGet();
}
run.persistentActions.clear();
for (PrearmedWait wait : new ArrayList<>(run.prearmedWaits.values())) {
wait.cleanup();
}
run.prearmedWaits.clear();
releaseBackgroundMoves(run.backgroundMoves, Minecraft.getInstance(), run);
run.backgroundMoves.clear();
reconcilePersistentInput(Minecraft.getInstance());
synchronized (run.packetWaitLock) {
if (run.packetFuture != null) run.packetFuture.cancel(true);
run.packetFuture = null;
run.waitingForPacket.set(false);
run.waitingPacketName.set("");
}
CompletableFuture<Void> chatFuture = run.chatFuture;
if (chatFuture != null) chatFuture.cancel(true);
run.chatFuture = null;
run.waitingForChat.set(false);
run.waitingChatAction = null;
CompletableFuture<Void> baritoneFuture = run.baritoneGoalFuture;
if (baritoneFuture != null) baritoneFuture.cancel(true);
run.baritoneGoalFuture = null;
run.activeMineTracker = null;
Minecraft mc = Minecraft.getInstance();
PacketGateManager.clearOwnerAndFlushConfigured(run.id, mc == null ? null : mc.getConnection());
FpsLimitController.clear(run.id);
PingSpoofController.clearMacro(run.id);
MacroRender.cancelRotation(run);
MacroWorldActions.requestOwnedBaritoneStop(run, mc);
Thread thread = run.macroThread;
if (interruptThread && thread != null && thread != Thread.currentThread()) {
thread.interrupt();
}
}
static void releaseBackgroundMoves(ConcurrentHashMap<MoveAction, int[]> moves, Minecraft mc, RunState owner) {
if (moves == null || moves.isEmpty() || mc == null) return;
List<MoveAction> toRelease = new ArrayList<>(moves.keySet());
mc.execute(() -> {
for (MoveAction move : toRelease) {
try {
releaseMoveIfUnused(owner, move, mc);
} catch (Exception ignored) { }
}
});
}
static void releaseMoveIfUnused(RunState owner, MoveAction move, Minecraft mc) {
if (move == null || mc == null) return;
boolean stillOwned = false;
synchronized (RUN_LOCK) {
for (RunState active : ACTIVE_RUNS.values()) {
if (active == owner || !active.running.get()) continue;
for (MoveAction other : active.backgroundMoves.keySet()) {
if (other.direction == move.direction) {
stillOwned = true;
break;
}
}
if (stillOwned) break;
}
}
if (!stillOwned && owner != null) {
for (MoveAction other : backgroundMoves.keySet()) {
if (other.direction == move.direction) {
stillOwned = true;
break;
}
}
}
if (!stillOwned) move.release(mc);
}
private static void reconcilePersistentInput(Minecraft mc) {
if (mc == null) return;
mc.execute(() -> {
applyAggregateSneakState(mc);
applyAggregateSprintState(mc);
});
}
static void applyAggregateSneakState(Minecraft mc) {
if (mc == null || mc.options == null || mc.options.keyShift == null) return;
boolean held = hasPersistentInput(SneakAction.class);
mc.options.keyShift.setDown(held);
}
static void applyAggregateSprintState(Minecraft mc) {
if (mc == null) return;
boolean held = hasPersistentInput(SprintAction.class);
if (mc.options != null && mc.options.keySprint != null) mc.options.keySprint.setDown(held);
if (mc.player != null) mc.player.setSprinting(held);
}
private static boolean hasPersistentInput(Class<? extends MacroAction> type) {
for (MacroAction action : persistentActions) {
if (type.isInstance(action)) return true;
}
synchronized (RUN_LOCK) {
for (RunState run : ACTIVE_RUNS.values()) {
if (!run.running.get()) continue;
for (MacroAction action : run.persistentActions) {
if (type.isInstance(action)) return true;
}
}
}
return false;
}
private static String macroKey(String macroName) {
return macroName == null ? "" : macroName.trim().toLowerCase(Locale.ROOT);
}
private static String macroName(AutismMacro macro) {
return macro != null && macro.name != null ? macro.name : "";
}
private static boolean matchesMacro(RunState run, AutismMacro macro, String macroName) {
if (run == null || !run.running.get()) return false;
if (macro != null && (run.sourceMacro == macro || run.macro == macro)) return true;
String targetKey = macroKey(macroName);
if (targetKey.isEmpty() && macro != null) targetKey = macroKey(macro.name);
return !targetKey.isEmpty() && macroKey(macroName(run.macro)).equals(targetKey);
} }
public static void execute(AutismMacro macro) { public static void execute(AutismMacro macro) {
executeTracked(macro); MacroLifecycle.execute(macro);
} }
public static long executeTracked(AutismMacro macro) { public static long executeTracked(AutismMacro macro) {
return executeTracked(macro, RunOptions.NORMAL); return MacroLifecycle.executeTracked(macro);
} }
public static long executeTracked(AutismMacro macro, RunOptions options) { public static long executeTracked(AutismMacro macro, RunOptions options) {
if (PackHideState.isHardLocked()) return -1L; return MacroLifecycle.executeTracked(macro, options);
RunOptions runOptions = options == null ? RunOptions.NORMAL : options;
if (macro == null || macro.actions == null || macro.actions.isEmpty()) {
if (runOptions.silentLifecycle()) return -1L;
AutismClientMessaging.sendPrefixed("\u00a7cMacro has no actions!");
return -1L;
}
AutismMacro executionMacro;
try {
executionMacro = macro.deepCopy();
} catch (Throwable copyError) {
if (!runOptions.silentLifecycle()) AutismClientMessaging.sendPrefixed("\u00a7cCould not prepare macro run.");
return -1L;
}
if (executionMacro == null || executionMacro.actions == null || executionMacro.actions.isEmpty()) return -1L;
RunState runState;
synchronized (RUN_LOCK) {
String name = macro.name == null ? "" : macro.name;
String nameKey = macroKey(name);
if (!runOptions.backgroundRun()) {
for (RunState active : ACTIVE_RUNS.values()) {
if (active.options.backgroundRun()) continue;
String activeName = active.macro != null && active.macro.name != null ? active.macro.name : "";
if (active.running.get() && macroKey(activeName).equals(nameKey)) {
if (!runOptions.silentLifecycle()) AutismClientMessaging.sendPrefixed("\u00a7eMacro already running: " + name);
return -1L;
}
}
if (!hasMacroCapacity(activeRunCountLocked())) {
if (!runOptions.silentLifecycle()) AutismClientMessaging.sendPrefixed("\u00a7cOnly " + MAX_CONCURRENT_MACROS + " macros can run at the same time.");
return -1L;
}
} else if (!hasMacroCapacity(activeRunCountLocked())) {
return -1L;
}
runState = new RunState(NEXT_RUN_ID.getAndIncrement(), macro, executionMacro, runOptions);
if (ACTIVE_RUNS.isEmpty()) MacroCaptureAutofill.expireSuggestionCacheAfterIdle();
ACTIVE_RUNS.put(runState.id, runState);
RUNS_BY_ID.put(runState.id, runState);
rebuildActiveRunListLocked();
RUN_STATE_REVISION.incrementAndGet();
refreshPrimaryRunLocked();
}
if (!runOptions.silentLifecycle()) AutismClientMessaging.sendPrefixed("\u00a7aStarted macro: " + macro.name);
broadcastStepProgress(runState, 0, executionMacro.actions.size(), executionMacro.name);
Thread thread = new Thread(() -> MacroRunLoop.run(runState), "Autism-Macro-" + runState.id);
thread.setDaemon(true);
macroThread = thread;
runState.macroThread = thread;
try {
thread.start();
} catch (Throwable startError) {
requestStop(runState, false);
synchronized (RUN_LOCK) {
ACTIVE_RUNS.remove(runState.id);
RUNS_BY_ID.remove(runState.id);
rebuildActiveRunListLocked();
if (ACTIVE_RUNS.isEmpty()) MacroCaptureAutofill.allRunsStoppedAtMs = System.currentTimeMillis();
RUN_STATE_REVISION.incrementAndGet();
refreshPrimaryRunLocked();
}
return -1L;
}
return runState.id;
} }
public static boolean isRunActive(long id) { public static boolean isRunActive(long id) {
if (id < 0L) return false; return MacroLifecycle.isRunActive(id);
RunState run = RUNS_BY_ID.get(id);
return run != null && run.running.get();
} }
public static long runStateRevision() { public static long runStateRevision() {
return RUN_STATE_REVISION.get(); return MacroLifecycle.runStateRevision();
} }
public static long currentRunId() { public static long currentRunId() {
RunState run = CURRENT_RUN.get(); return MacroLifecycle.currentRunId();
return run == null ? -1L : run.id;
} }
public static void stopRun(long id) { public static void stopRun(long id) {
if (id < 0L) return; MacroLifecycle.stopRun(id);
RunState run;
synchronized (RUN_LOCK) {
run = ACTIVE_RUNS.get(id);
}
if (run == null) return;
requestStop(run, true);
synchronized (RUN_LOCK) {
refreshPrimaryRunLocked();
}
} }
static void stopCurrentActionRun() {
MacroLifecycle.stopCurrentActionRun();
}
@ -898,13 +343,13 @@ public class MacroExecutor {
public static void stop() { public static void stop() {
String macroName = (currentMacro != null && currentMacro.name != null) ? currentMacro.name : ""; String macroName = (currentMacro != null && currentMacro.name != null) ? currentMacro.name : "";
for (RunState run : activeRunSnapshot()) { for (RunState run : MacroLifecycle.activeRunSnapshot()) {
requestStop(run, true); MacroLifecycle.requestStop(run, true);
} }
synchronized (RUN_LOCK) { synchronized (RUN_LOCK) {
ACTIVE_RUNS.clear(); ACTIVE_RUNS.clear();
RUNS_BY_ID.clear(); RUNS_BY_ID.clear();
rebuildActiveRunListLocked(); MacroLifecycle.rebuildActiveRunListLocked();
primaryRun = null; primaryRun = null;
visibleRunActive = false; visibleRunActive = false;
} }
@ -914,9 +359,9 @@ public class MacroExecutor {
autismclient.util.AutismContainerHold.releaseAllAndFlush(mcInst == null ? null : mcInst.getConnection()); autismclient.util.AutismContainerHold.releaseAllAndFlush(mcInst == null ? null : mcInst.getConnection());
} catch (Throwable ignored) { } } catch (Throwable ignored) { }
persistentActions.clear(); persistentActions.clear();
releaseBackgroundMoves(backgroundMoves, Minecraft.getInstance(), null); MacroLifecycle.releaseBackgroundMoves(backgroundMoves, Minecraft.getInstance(), null);
backgroundMoves.clear(); backgroundMoves.clear();
reconcilePersistentInput(Minecraft.getInstance()); MacroLifecycle.reconcilePersistentInput(Minecraft.getInstance());
MacroConditionRegistry.cancelAll(); MacroConditionRegistry.cancelAll();
MacroPacketObserve.drainOneShotListeners(); MacroPacketObserve.drainOneShotListeners();
isWaitingForChat.set(false); isWaitingForChat.set(false);
@ -948,7 +393,7 @@ public class MacroExecutor {
macroThread = null; macroThread = null;
currentMacro = null; currentMacro = null;
setCurrentStatus(""); MacroLifecycle.setCurrentStatus("");
synchronized (ROTATION_STATE_LOCK) { synchronized (ROTATION_STATE_LOCK) {
ROTATION_OWNER.set(null); ROTATION_OWNER.set(null);
isRotating.set(false); isRotating.set(false);
@ -967,7 +412,7 @@ public class MacroExecutor {
public static int getActiveRunCount() { public static int getActiveRunCount() {
synchronized (RUN_LOCK) { synchronized (RUN_LOCK) {
return activeRunCountLocked(); return MacroLifecycle.activeRunCountLocked();
} }
} }
@ -984,9 +429,9 @@ public class MacroExecutor {
public static boolean isMacroRunning(String macroName) { public static boolean isMacroRunning(String macroName) {
if (macroName == null) return false; if (macroName == null) return false;
String targetKey = macroKey(macroName); String targetKey = MacroLifecycle.macroKey(macroName);
for (RunState run : RUNS_BY_ID.values()) { for (RunState run : RUNS_BY_ID.values()) {
if (run.running.get() && macroKey(macroName(run.macro)).equals(targetKey)) return true; if (run.running.get() && MacroLifecycle.macroKey(MacroLifecycle.macroName(run.macro)).equals(targetKey)) return true;
} }
return false; return false;
} }
@ -994,7 +439,7 @@ public class MacroExecutor {
public static boolean isMacroRunning(AutismMacro macro) { public static boolean isMacroRunning(AutismMacro macro) {
if (macro == null) return false; if (macro == null) return false;
for (RunState run : RUNS_BY_ID.values()) { for (RunState run : RUNS_BY_ID.values()) {
if (matchesMacro(run, macro, macro.name)) return true; if (MacroLifecycle.matchesMacro(run, macro, macro.name)) return true;
} }
return false; return false;
} }
@ -1022,17 +467,17 @@ public class MacroExecutor {
public static void stopMacro(String macroName) { public static void stopMacro(String macroName) {
if (macroName == null || macroName.isBlank()) return; if (macroName == null || macroName.isBlank()) return;
String targetKey = macroKey(macroName); String targetKey = MacroLifecycle.macroKey(macroName);
boolean stopped = false; boolean stopped = false;
for (RunState run : activeRunSnapshot()) { for (RunState run : MacroLifecycle.activeRunSnapshot()) {
if (run.running.get() && macroKey(macroName(run.macro)).equals(targetKey)) { if (run.running.get() && MacroLifecycle.macroKey(MacroLifecycle.macroName(run.macro)).equals(targetKey)) {
requestStop(run, true); MacroLifecycle.requestStop(run, true);
stopped = true; stopped = true;
} }
} }
if (stopped) { if (stopped) {
synchronized (RUN_LOCK) { synchronized (RUN_LOCK) {
refreshPrimaryRunLocked(); MacroLifecycle.refreshPrimaryRunLocked();
} }
AutismClientMessaging.sendPrefixed("\u00a7cMacro stopped: " + macroName); AutismClientMessaging.sendPrefixed("\u00a7cMacro stopped: " + macroName);
} }
@ -1041,16 +486,16 @@ public class MacroExecutor {
public static void stopMacro(AutismMacro macro) { public static void stopMacro(AutismMacro macro) {
if (macro == null) return; if (macro == null) return;
boolean stopped = false; boolean stopped = false;
String displayName = macroName(macro); String displayName = MacroLifecycle.macroName(macro);
for (RunState run : activeRunSnapshot()) { for (RunState run : MacroLifecycle.activeRunSnapshot()) {
if (matchesMacro(run, macro, displayName)) { if (MacroLifecycle.matchesMacro(run, macro, displayName)) {
requestStop(run, true); MacroLifecycle.requestStop(run, true);
stopped = true; stopped = true;
} }
} }
if (stopped) { if (stopped) {
synchronized (RUN_LOCK) { synchronized (RUN_LOCK) {
refreshPrimaryRunLocked(); MacroLifecycle.refreshPrimaryRunLocked();
} }
AutismClientMessaging.sendPrefixed("\u00a7cMacro stopped: " + (displayName.isBlank() ? "macro" : displayName)); AutismClientMessaging.sendPrefixed("\u00a7cMacro stopped: " + (displayName.isBlank() ? "macro" : displayName));
} }

View file

@ -0,0 +1,623 @@
package autismclient.util.macro;
import autismclient.modules.PackHideState;
import autismclient.util.AutismClientMessaging;
import autismclient.util.AutismInstaBreakRenderer;
import autismclient.util.AutismMacro;
import autismclient.util.macro.MacroActionResources.SharedClientResource;
import net.minecraft.client.Minecraft;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;
final class MacroLifecycle {
private MacroLifecycle() {
}
private static java.util.Map<String, Integer> flowLabels(MacroExecutor.RunState run, AutismMacro macro) {
java.util.Map<String, Integer> cached = run.labelIndex;
if (cached != null) return cached;
java.util.LinkedHashMap<String, Integer> built = new java.util.LinkedHashMap<>();
for (int k = 0; k < macro.actions.size(); k++) {
if (macro.actions.get(k) instanceof LabelAction la) {
String key = la.normalizedName();
if (!key.isEmpty() && !built.containsKey(key)) built.put(key, k);
}
}
run.labelIndex = built;
return built;
}
private static Integer resolveFlowTarget(MacroExecutor.RunState run, AutismMacro macro, int i, FlowAction flow, Minecraft mc) {
return switch (flow.target) {
case STOP -> null;
case TOP -> 0;
case END -> macro.actions.size();
case FORWARD -> i + 1 + Math.max(0, flow.amount);
case BACK -> i - Math.max(0, flow.amount);
case STEP -> Math.max(1, flow.amount) - 1;
case LABEL -> {
String name = LabelAction.normalize(MacroVariables.expand(flow.labelName, mc));
Integer idx = flowLabels(run, macro).get(name);
if (idx == null) {
AutismClientMessaging.sendPrefixed("§eFlow: label '" + flow.labelName + "' not found.");
yield flow.onMissingLabel == FlowAction.MissingPolicy.STOP ? null : i + 1;
}
yield idx;
}
};
}
static int performFlowJump(MacroExecutor.RunState run, AutismMacro macro, int currentI, FlowAction flow, Minecraft mc) {
run.branchElseStart = -1;
run.branchElseCount = 0;
Integer dest = resolveFlowTarget(run, macro, currentI, flow, mc);
if (dest == null) return Integer.MIN_VALUE;
int size = macro.actions.size();
int target = Math.max(0, Math.min(size, dest));
if (target <= currentI) {
run.totalJumpsThisRun++;
run.jumpBudget++;
if (MacroExecutor.FLOW_JUMP_HARD_CAP >= 0 && run.totalJumpsThisRun > MacroExecutor.FLOW_JUMP_HARD_CAP) {
AutismClientMessaging.sendPrefixed("§cMacro aborted: jump limit exceeded (runaway loop).");
return Integer.MIN_VALUE;
}
if (run.jumpBudget >= MacroExecutor.FLOW_JUMP_BURST_CAP) {
run.jumpBudget = 0;
try { MacroRunLoop.waitForCondition(MacroConditionRegistry.waitForNextTick()); } catch (Exception ignored) { }
}
} else {
run.jumpBudget = 0;
}
return target - 1;
}
static boolean isCurrentRunActive() {
if (PackHideState.isHardLocked()) return false;
MacroExecutor.RunState run = MacroExecutor.CURRENT_RUN.get();
if (run != null) return run.running.get();
return MacroExecutor.isRunning.get();
}
public static boolean isCurrentActionRunActive() {
return isCurrentRunActive();
}
static CopyOnWriteArrayList<MacroAction> currentPersistentActions() {
MacroExecutor.RunState run = MacroExecutor.CURRENT_RUN.get();
return run != null ? run.persistentActions : MacroExecutor.persistentActions;
}
static ConcurrentHashMap<MoveAction, int[]> currentBackgroundMoves() {
MacroExecutor.RunState run = MacroExecutor.CURRENT_RUN.get();
return run != null ? run.backgroundMoves : MacroExecutor.backgroundMoves;
}
static void setCurrentStatus(String status) {
MacroExecutor.RunState run = MacroExecutor.CURRENT_RUN.get();
if (run != null) run.status = status == null ? "" : status;
MacroExecutor.currentStatus = status == null ? "" : status;
}
static void setCurrentStep(int step, int total) {
MacroExecutor.RunState run = MacroExecutor.CURRENT_RUN.get();
if (run != null) {
run.currentStepIndex = step;
run.totalSteps = total;
}
MacroExecutor.currentStepIndex = step;
MacroExecutor.totalSteps = total;
}
static void markStepCompleted(int stepOneBased) {
MacroExecutor.RunState run = MacroExecutor.CURRENT_RUN.get();
if (run != null) {
run.lastCompletedStep = Math.max(run.lastCompletedStep, stepOneBased);
}
}
static int stepOverrideEndIndex(AutismMacro macro, int headerIndex, int coveredRows) {
int last = macro == null ? headerIndex : macro.actions.size() - 1;
long end = (long) headerIndex + Math.max(0, coveredRows);
return (int) Math.max(headerIndex, Math.min(last, end));
}
static void armFpsStepOverride(MacroExecutor.RunState run, int headerIndex, int endIndexInclusive, int fpsLimit) {
if (run == null) return;
run.fpsStepHeaderIndex = headerIndex;
run.fpsStepEndIndex = endIndexInclusive;
FpsLimitController.applyUntilCleared(run.id, fpsLimit);
}
static void armPingStepOverride(MacroExecutor.RunState run, int headerIndex, int endIndexInclusive,
int delayMs, boolean realIncoming, boolean realOutgoing) {
if (run == null) return;
run.pingStepHeaderIndex = headerIndex;
run.pingStepEndIndex = endIndexInclusive;
PingSpoofController.applyUntilCleared(run.id, delayMs, realIncoming, realOutgoing);
}
static void clearFpsStepOverride(MacroExecutor.RunState run) {
if (run == null || run.fpsStepHeaderIndex < 0) return;
run.fpsStepHeaderIndex = -1;
run.fpsStepEndIndex = -1;
FpsLimitController.clear(run.id);
}
static void clearPingStepOverride(MacroExecutor.RunState run) {
if (run == null || run.pingStepHeaderIndex < 0) return;
run.pingStepHeaderIndex = -1;
run.pingStepEndIndex = -1;
PingSpoofController.clearMacro(run.id);
}
static void awaitBackgroundTimedOverrides(MacroExecutor.RunState run) throws InterruptedException {
if (run == null) return;
long deadline = Math.max(run.fpsBackgroundDeadlineNanos, run.pingBackgroundDeadlineNanos);
long remaining;
while (isCurrentRunActive() && (remaining = deadline - System.nanoTime()) > 0L) {
Thread.sleep(Math.min(25L, remaining / 1_000_000L + 1L));
}
}
static void updateStepBoundOverrides(MacroExecutor.RunState run, int index) {
if (run == null) return;
if (run.fpsStepHeaderIndex >= 0 && (index > run.fpsStepEndIndex || index <= run.fpsStepHeaderIndex)) {
clearFpsStepOverride(run);
}
if (run.pingStepHeaderIndex >= 0 && (index > run.pingStepEndIndex || index <= run.pingStepHeaderIndex)) {
clearPingStepOverride(run);
}
}
static void stopCurrentRun() {
MacroExecutor.RunState run = MacroExecutor.CURRENT_RUN.get();
if (run != null) {
run.running.set(false);
} else {
MacroExecutor.stop();
}
}
static void stopCurrentActionRun() {
stopCurrentRun();
}
private static EnumSet<SharedClientResource> resourcesForAction(MacroAction action) {
return MacroActionResources.resourcesForAction(action);
}
static EnumSet<SharedClientResource> acquireClientResources(MacroAction action) throws InterruptedException {
return acquireClientResources(resourcesForAction(action));
}
static EnumSet<SharedClientResource> acquireClientResources(EnumSet<SharedClientResource> resources) throws InterruptedException {
EnumSet<SharedClientResource> acquired = EnumSet.noneOf(SharedClientResource.class);
try {
for (SharedClientResource resource : SharedClientResource.values()) {
if (resources.contains(resource)) {
if (!isCurrentRunActive()) throw new InterruptedException("Macro stopped");
MacroExecutor.SHARED_RESOURCE_LOCKS.get(resource).lockInterruptibly();
acquired.add(resource);
if (!isCurrentRunActive()) throw new InterruptedException("Macro stopped");
}
}
} catch (InterruptedException e) {
releaseClientResources(acquired);
throw e;
}
return acquired;
}
static EnumSet<SharedClientResource> resourcesForActions(java.util.List<MacroAction> actions) {
return MacroActionResources.resourcesForActions(actions);
}
static void releaseClientResources(EnumSet<SharedClientResource> resources) {
if (resources == null || resources.isEmpty()) return;
SharedClientResource[] ordered = SharedClientResource.values();
for (int i = ordered.length - 1; i >= 0; i--) {
SharedClientResource resource = ordered[i];
if (resources.contains(resource)) {
ReentrantLock lock = MacroExecutor.SHARED_RESOURCE_LOCKS.get(resource);
if (lock.isHeldByCurrentThread()) lock.unlock();
}
}
}
static MacroVariableContext currentVariableContext() {
MacroExecutor.RunState run = MacroExecutor.CURRENT_RUN.get();
return run == null ? null : run.variables;
}
static void withRunContext(MacroExecutor.RunState run, Runnable task) {
MacroExecutor.RunState previous = MacroExecutor.CURRENT_RUN.get();
if (run != null) MacroExecutor.CURRENT_RUN.set(run);
try {
task.run();
} finally {
if (previous != null) MacroExecutor.CURRENT_RUN.set(previous);
else MacroExecutor.CURRENT_RUN.remove();
}
}
static MacroExecutor.InlineNextActions collectInlineNextActions(java.util.List<MacroAction> actions, int currentIndex) {
if (actions == null || currentIndex < 0 || currentIndex >= actions.size() - 1) return MacroExecutor.InlineNextActions.empty();
java.util.ArrayList<MacroAction> collected = new java.util.ArrayList<>();
int lastIndex = -1;
for (int j = currentIndex + 1; j < actions.size(); j++) {
MacroAction candidate = actions.get(j);
if (candidate instanceof DisconnectAction
|| candidate instanceof RaceAction
|| candidate instanceof ReportAction
|| candidate instanceof RepeatAction
|| candidate instanceof BranchAction
|| candidate instanceof FinallyAction) {
break;
}
if (candidate == null || !candidate.isEnabled()) continue;
if (!RaceAction.isBodyAction(candidate)) continue;
collected.add(candidate);
lastIndex = j;
}
return collected.isEmpty() ? MacroExecutor.InlineNextActions.empty() : new MacroExecutor.InlineNextActions(java.util.List.copyOf(collected), lastIndex);
}
private static volatile java.util.List<MacroExecutor.RunState> ACTIVE_RUN_LIST = java.util.List.of();
public static void rebuildActiveRunListLocked() {
ACTIVE_RUN_LIST = java.util.List.copyOf(MacroExecutor.ACTIVE_RUNS.values());
}
static java.util.List<MacroExecutor.RunState> activeRunSnapshot() {
return ACTIVE_RUN_LIST;
}
static void finishCurrentRun() {
MacroExecutor.RunState run = MacroExecutor.CURRENT_RUN.get();
if (run == null) return;
if (!run.finished.compareAndSet(false, true)) return;
requestStop(run, false);
clearFpsStepOverride(run);
clearPingStepOverride(run);
synchronized (MacroExecutor.RUN_LOCK) {
MacroExecutor.ACTIVE_RUNS.remove(run.id);
MacroExecutor.RUNS_BY_ID.remove(run.id);
rebuildActiveRunListLocked();
if (MacroExecutor.ACTIVE_RUNS.isEmpty()) MacroCaptureAutofill.allRunsStoppedAtMs = System.currentTimeMillis();
MacroExecutor.RUN_STATE_REVISION.incrementAndGet();
refreshPrimaryRunLocked();
}
if (!MacroExecutor.isRunning.get()) {
AutismInstaBreakRenderer.clear();
FpsLimitController.clearAll();
PingSpoofController.clearAllMacros();
}
MacroExecutor.CURRENT_RUN.remove();
}
private static boolean hasRunningRunsLocked() {
for (MacroExecutor.RunState run : MacroExecutor.ACTIVE_RUNS.values()) {
if (run.running.get()) return true;
}
return false;
}
private static MacroExecutor.RunState firstVisibleRunLocked() {
for (MacroExecutor.RunState run : MacroExecutor.ACTIVE_RUNS.values()) {
if (run.running.get() && !run.options.hiddenFromProgressHud()) return run;
}
return null;
}
public static int activeRunCountLocked() {
int count = 0;
for (MacroExecutor.RunState run : MacroExecutor.ACTIVE_RUNS.values()) {
if (run.running.get()) count++;
}
return count;
}
static boolean hasMacroCapacity(int activeCount) {
return Math.max(0, activeCount) < MacroExecutor.MAX_CONCURRENT_MACROS;
}
public static void refreshPrimaryRunLocked() {
MacroExecutor.primaryRun = firstVisibleRunLocked();
MacroExecutor.visibleRunActive = MacroExecutor.primaryRun != null;
MacroExecutor.currentMacro = MacroExecutor.primaryRun != null ? MacroExecutor.primaryRun.macro : null;
MacroExecutor.currentStatus = MacroExecutor.primaryRun != null ? MacroExecutor.primaryRun.status : "";
MacroExecutor.currentStepIndex = MacroExecutor.primaryRun != null ? MacroExecutor.primaryRun.currentStepIndex : -1;
MacroExecutor.totalSteps = MacroExecutor.primaryRun != null ? MacroExecutor.primaryRun.totalSteps : 0;
MacroExecutor.isRunning.set(hasRunningRunsLocked());
}
public static boolean hasRunningRuns() {
synchronized (MacroExecutor.RUN_LOCK) {
return hasRunningRunsLocked();
}
}
public static boolean isVisibleRunning() {
return MacroExecutor.visibleRunActive;
}
public static boolean isControllingInput() {
ReentrantLock inputLock = MacroExecutor.SHARED_RESOURCE_LOCKS.get(SharedClientResource.INPUT);
if (inputLock != null && inputLock.isLocked()) return true;
if (!MacroExecutor.backgroundMoves.isEmpty()) return true;
for (MacroAction action : MacroExecutor.persistentActions) {
if (action instanceof MoveAction || action instanceof JumpAction || action instanceof SneakAction || action instanceof SprintAction) return true;
}
synchronized (MacroExecutor.RUN_LOCK) {
for (MacroExecutor.RunState run : MacroExecutor.ACTIVE_RUNS.values()) {
if (run == null || !run.running.get()) continue;
if (!run.backgroundMoves.isEmpty()) return true;
for (MacroAction action : run.persistentActions) {
if (action instanceof MoveAction || action instanceof JumpAction || action instanceof SneakAction || action instanceof SprintAction) return true;
}
}
}
return false;
}
static void broadcastStepProgress(MacroExecutor.RunState run, int step, int total, String macroName) {
if (run != null && run.options.skipLanProgress()) return;
try {
autismclient.util.AutismLANSync sync = autismclient.util.AutismLANSync.getInstance();
if (sync.isInSession()) {
sync.broadcastStepProgress(step, total, macroName);
}
} catch (Exception ignored) { }
}
public static void requestStop(MacroExecutor.RunState run, boolean interruptThread) {
if (run == null) return;
if (run.running.getAndSet(false)) {
MacroExecutor.RUN_STATE_REVISION.incrementAndGet();
}
run.persistentActions.clear();
for (MacroExecutor.PrearmedWait wait : new ArrayList<>(run.prearmedWaits.values())) {
wait.cleanup();
}
run.prearmedWaits.clear();
releaseBackgroundMoves(run.backgroundMoves, Minecraft.getInstance(), run);
run.backgroundMoves.clear();
reconcilePersistentInput(Minecraft.getInstance());
synchronized (run.packetWaitLock) {
if (run.packetFuture != null) run.packetFuture.cancel(true);
run.packetFuture = null;
run.waitingForPacket.set(false);
run.waitingPacketName.set("");
}
CompletableFuture<Void> chatFuture = run.chatFuture;
if (chatFuture != null) chatFuture.cancel(true);
run.chatFuture = null;
run.waitingForChat.set(false);
run.waitingChatAction = null;
CompletableFuture<Void> baritoneFuture = run.baritoneGoalFuture;
if (baritoneFuture != null) baritoneFuture.cancel(true);
run.baritoneGoalFuture = null;
run.activeMineTracker = null;
Minecraft mc = Minecraft.getInstance();
PacketGateManager.clearOwnerAndFlushConfigured(run.id, mc == null ? null : mc.getConnection());
FpsLimitController.clear(run.id);
PingSpoofController.clearMacro(run.id);
MacroRender.cancelRotation(run);
MacroWorldActions.requestOwnedBaritoneStop(run, mc);
Thread thread = run.macroThread;
if (interruptThread && thread != null && thread != Thread.currentThread()) {
thread.interrupt();
}
}
static void releaseBackgroundMoves(ConcurrentHashMap<MoveAction, int[]> moves, Minecraft mc, MacroExecutor.RunState owner) {
if (moves == null || moves.isEmpty() || mc == null) return;
List<MoveAction> toRelease = new ArrayList<>(moves.keySet());
mc.execute(() -> {
for (MoveAction move : toRelease) {
try {
releaseMoveIfUnused(owner, move, mc);
} catch (Exception ignored) { }
}
});
}
static void releaseMoveIfUnused(MacroExecutor.RunState owner, MoveAction move, Minecraft mc) {
if (move == null || mc == null) return;
boolean stillOwned = false;
synchronized (MacroExecutor.RUN_LOCK) {
for (MacroExecutor.RunState active : MacroExecutor.ACTIVE_RUNS.values()) {
if (active == owner || !active.running.get()) continue;
for (MoveAction other : active.backgroundMoves.keySet()) {
if (other.direction == move.direction) {
stillOwned = true;
break;
}
}
if (stillOwned) break;
}
}
if (!stillOwned && owner != null) {
for (MoveAction other : MacroExecutor.backgroundMoves.keySet()) {
if (other.direction == move.direction) {
stillOwned = true;
break;
}
}
}
if (!stillOwned) move.release(mc);
}
public static void reconcilePersistentInput(Minecraft mc) {
if (mc == null) return;
mc.execute(() -> {
applyAggregateSneakState(mc);
applyAggregateSprintState(mc);
});
}
static void applyAggregateSneakState(Minecraft mc) {
if (mc == null || mc.options == null || mc.options.keyShift == null) return;
boolean held = hasPersistentInput(SneakAction.class);
mc.options.keyShift.setDown(held);
}
static void applyAggregateSprintState(Minecraft mc) {
if (mc == null) return;
boolean held = hasPersistentInput(SprintAction.class);
if (mc.options != null && mc.options.keySprint != null) mc.options.keySprint.setDown(held);
if (mc.player != null) mc.player.setSprinting(held);
}
private static boolean hasPersistentInput(Class<? extends MacroAction> type) {
for (MacroAction action : MacroExecutor.persistentActions) {
if (type.isInstance(action)) return true;
}
synchronized (MacroExecutor.RUN_LOCK) {
for (MacroExecutor.RunState run : MacroExecutor.ACTIVE_RUNS.values()) {
if (!run.running.get()) continue;
for (MacroAction action : run.persistentActions) {
if (type.isInstance(action)) return true;
}
}
}
return false;
}
public static String macroKey(String macroName) {
return macroName == null ? "" : macroName.trim().toLowerCase(Locale.ROOT);
}
public static String macroName(AutismMacro macro) {
return macro != null && macro.name != null ? macro.name : "";
}
public static boolean matchesMacro(MacroExecutor.RunState run, AutismMacro macro, String macroName) {
if (run == null || !run.running.get()) return false;
if (macro != null && (run.sourceMacro == macro || run.macro == macro)) return true;
String targetKey = macroKey(macroName);
if (targetKey.isEmpty() && macro != null) targetKey = macroKey(macro.name);
return !targetKey.isEmpty() && macroKey(macroName(run.macro)).equals(targetKey);
}
public static void execute(AutismMacro macro) {
executeTracked(macro);
}
public static long executeTracked(AutismMacro macro) {
return executeTracked(macro, MacroExecutor.RunOptions.NORMAL);
}
public static long executeTracked(AutismMacro macro, MacroExecutor.RunOptions options) {
if (PackHideState.isHardLocked()) return -1L;
MacroExecutor.RunOptions runOptions = options == null ? MacroExecutor.RunOptions.NORMAL : options;
if (macro == null || macro.actions == null || macro.actions.isEmpty()) {
if (runOptions.silentLifecycle()) return -1L;
AutismClientMessaging.sendPrefixed("\u00a7cMacro has no actions!");
return -1L;
}
AutismMacro executionMacro;
try {
executionMacro = macro.deepCopy();
} catch (Throwable copyError) {
if (!runOptions.silentLifecycle()) AutismClientMessaging.sendPrefixed("\u00a7cCould not prepare macro run.");
return -1L;
}
if (executionMacro == null || executionMacro.actions == null || executionMacro.actions.isEmpty()) return -1L;
MacroExecutor.RunState runState;
synchronized (MacroExecutor.RUN_LOCK) {
String name = macro.name == null ? "" : macro.name;
String nameKey = macroKey(name);
if (!runOptions.backgroundRun()) {
for (MacroExecutor.RunState active : MacroExecutor.ACTIVE_RUNS.values()) {
if (active.options.backgroundRun()) continue;
String activeName = active.macro != null && active.macro.name != null ? active.macro.name : "";
if (active.running.get() && macroKey(activeName).equals(nameKey)) {
if (!runOptions.silentLifecycle()) AutismClientMessaging.sendPrefixed("\u00a7eMacro already running: " + name);
return -1L;
}
}
if (!hasMacroCapacity(activeRunCountLocked())) {
if (!runOptions.silentLifecycle()) AutismClientMessaging.sendPrefixed("\u00a7cOnly " + MacroExecutor.MAX_CONCURRENT_MACROS + " macros can run at the same time.");
return -1L;
}
} else if (!hasMacroCapacity(activeRunCountLocked())) {
return -1L;
}
runState = new MacroExecutor.RunState(MacroExecutor.NEXT_RUN_ID.getAndIncrement(), macro, executionMacro, runOptions);
if (MacroExecutor.ACTIVE_RUNS.isEmpty()) MacroCaptureAutofill.expireSuggestionCacheAfterIdle();
MacroExecutor.ACTIVE_RUNS.put(runState.id, runState);
MacroExecutor.RUNS_BY_ID.put(runState.id, runState);
rebuildActiveRunListLocked();
MacroExecutor.RUN_STATE_REVISION.incrementAndGet();
refreshPrimaryRunLocked();
}
if (!runOptions.silentLifecycle()) AutismClientMessaging.sendPrefixed("\u00a7aStarted macro: " + macro.name);
broadcastStepProgress(runState, 0, executionMacro.actions.size(), executionMacro.name);
Thread thread = new Thread(() -> MacroRunLoop.run(runState), "Autism-Macro-" + runState.id);
thread.setDaemon(true);
MacroExecutor.macroThread = thread;
runState.macroThread = thread;
try {
thread.start();
} catch (Throwable startError) {
requestStop(runState, false);
synchronized (MacroExecutor.RUN_LOCK) {
MacroExecutor.ACTIVE_RUNS.remove(runState.id);
MacroExecutor.RUNS_BY_ID.remove(runState.id);
rebuildActiveRunListLocked();
if (MacroExecutor.ACTIVE_RUNS.isEmpty()) MacroCaptureAutofill.allRunsStoppedAtMs = System.currentTimeMillis();
MacroExecutor.RUN_STATE_REVISION.incrementAndGet();
refreshPrimaryRunLocked();
}
return -1L;
}
return runState.id;
}
public static boolean isRunActive(long id) {
if (id < 0L) return false;
MacroExecutor.RunState run = MacroExecutor.RUNS_BY_ID.get(id);
return run != null && run.running.get();
}
public static long runStateRevision() {
return MacroExecutor.RUN_STATE_REVISION.get();
}
public static long currentRunId() {
MacroExecutor.RunState run = MacroExecutor.CURRENT_RUN.get();
return run == null ? -1L : run.id;
}
public static void stopRun(long id) {
if (id < 0L) return;
MacroExecutor.RunState run;
synchronized (MacroExecutor.RUN_LOCK) {
run = MacroExecutor.ACTIVE_RUNS.get(id);
}
if (run == null) return;
requestStop(run, true);
synchronized (MacroExecutor.RUN_LOCK) {
refreshPrimaryRunLocked();
}
}
}

View file

@ -147,7 +147,7 @@ final class MacroPacketObserve {
if (PackHideState.isHardLocked()) return; if (PackHideState.isHardLocked()) return;
MacroChatObserve.syncRecentChatServerContext(); MacroChatObserve.syncRecentChatServerContext();
java.util.List<MacroExecutor.RunState> runs = MacroExecutor.activeRunSnapshot(); java.util.List<MacroExecutor.RunState> runs = MacroLifecycle.activeRunSnapshot();
boolean s2c = "S2C".equals(direction); boolean s2c = "S2C".equals(direction);
boolean chatWork = false; boolean chatWork = false;
boolean mineWork = false; boolean mineWork = false;
@ -174,7 +174,7 @@ final class MacroPacketObserve {
if (f != null) f.complete(null); if (f != null) f.complete(null);
} }
} }
if (MacroExecutor.isCurrentRunActive() && MacroExecutor.isWaitingForChat.get() && MacroChatObserve.matchesWaitingChat(capture)) { if (MacroLifecycle.isCurrentRunActive() && MacroExecutor.isWaitingForChat.get() && MacroChatObserve.matchesWaitingChat(capture)) {
MacroExecutor.lastMatchedChat.set(capture.displayText()); MacroExecutor.lastMatchedChat.set(capture.displayText());
CompletableFuture<Void> f = MacroExecutor.activeChatFuture; CompletableFuture<Void> f = MacroExecutor.activeChatFuture;
if (f != null) f.complete(null); if (f != null) f.complete(null);
@ -190,7 +190,7 @@ final class MacroPacketObserve {
} }
} }
if (!MacroExecutor.isCurrentRunActive()) return; if (!MacroLifecycle.isCurrentRunActive()) return;
if (packetWork) { if (packetWork) {
for (MacroExecutor.RunState run : runs) { for (MacroExecutor.RunState run : runs) {

View file

@ -78,7 +78,7 @@ final class MacroPacketWait {
run.waitingForPacket.set(true); run.waitingForPacket.set(true);
} }
try { try {
MacroExecutor.setCurrentStatus(normalizedTarget.isEmpty() MacroLifecycle.setCurrentStatus(normalizedTarget.isEmpty()
? "Waiting for packet: Any" ? "Waiting for packet: Any"
: "Waiting for packet: " + WaitForPacketAction.getDisplayLabel(normalizedTarget)); : "Waiting for packet: " + WaitForPacketAction.getDisplayLabel(normalizedTarget));
MacroRunLoop.waitForCondition(future); MacroRunLoop.waitForCondition(future);
@ -102,7 +102,7 @@ final class MacroPacketWait {
MacroExecutor.isWaitingForPacket.set(true); MacroExecutor.isWaitingForPacket.set(true);
} }
try { try {
MacroExecutor.setCurrentStatus(normalizedTarget.isEmpty() MacroLifecycle.setCurrentStatus(normalizedTarget.isEmpty()
? "Waiting for packet: Any" ? "Waiting for packet: Any"
: "Waiting for packet: " + WaitForPacketAction.getDisplayLabel(normalizedTarget)); : "Waiting for packet: " + WaitForPacketAction.getDisplayLabel(normalizedTarget));
MacroRunLoop.waitForCondition(future); MacroRunLoop.waitForCondition(future);

View file

@ -22,9 +22,9 @@ final class MacroPrearm {
public static CompletableFuture<Void> predicateFuture(java.util.function.BooleanSupplier predicate, int timeoutMs) { public static CompletableFuture<Void> predicateFuture(java.util.function.BooleanSupplier predicate, int timeoutMs) {
CompletableFuture<Void> future = new CompletableFuture<>(); CompletableFuture<Void> future = new CompletableFuture<>();
MacroExecutor.RunState run = MacroExecutor.CURRENT_RUN.get(); MacroExecutor.RunState run = MacroExecutor.CURRENT_RUN.get();
Thread worker = new Thread(() -> MacroExecutor.withRunContext(run, () -> { Thread worker = new Thread(() -> MacroLifecycle.withRunContext(run, () -> {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
while (!future.isDone() && MacroExecutor.isCurrentRunActive()) { while (!future.isDone() && MacroLifecycle.isCurrentRunActive()) {
try { try {
if (predicate.getAsBoolean()) { if (predicate.getAsBoolean()) {
future.complete(null); future.complete(null);
@ -400,9 +400,9 @@ final class MacroPrearm {
java.util.concurrent.atomic.AtomicBoolean active = new java.util.concurrent.atomic.AtomicBoolean(true); java.util.concurrent.atomic.AtomicBoolean active = new java.util.concurrent.atomic.AtomicBoolean(true);
CompletableFuture<Void> future = new CompletableFuture<>(); CompletableFuture<Void> future = new CompletableFuture<>();
MacroExecutor.RunState run = MacroExecutor.CURRENT_RUN.get(); MacroExecutor.RunState run = MacroExecutor.CURRENT_RUN.get();
Thread worker = new Thread(() -> MacroExecutor.withRunContext(run, () -> { Thread worker = new Thread(() -> MacroLifecycle.withRunContext(run, () -> {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
while (active.get() && MacroExecutor.isCurrentRunActive() && !future.isDone()) { while (active.get() && MacroLifecycle.isCurrentRunActive() && !future.isDone()) {
try { try {
if (predicate.getAsBoolean()) { if (predicate.getAsBoolean()) {
future.complete(null); future.complete(null);

View file

@ -92,7 +92,7 @@ final class MacroRace {
public static void waitForMacroStep(WaitForMacroStepAction action) { public static void waitForMacroStep(WaitForMacroStepAction action) {
long startMs = System.currentTimeMillis(); long startMs = System.currentTimeMillis();
while (MacroExecutor.isCurrentRunActive()) { while (MacroLifecycle.isCurrentRunActive()) {
if (isMacroStepSatisfied(action)) return; if (isMacroStepSatisfied(action)) return;
if (action.timeoutMs > 0 && System.currentTimeMillis() - startMs >= action.timeoutMs) return; if (action.timeoutMs > 0 && System.currentTimeMillis() - startMs >= action.timeoutMs) return;
CompletableFuture<Void> tick = MacroConditionRegistry.waitForNextTick(); CompletableFuture<Void> tick = MacroConditionRegistry.waitForNextTick();
@ -129,7 +129,7 @@ final class MacroRace {
else if (RaceAction.isBodyAction(child)) bodyActions.add(child); else if (RaceAction.isBodyAction(child)) bodyActions.add(child);
} }
MacroExecutor.setCurrentStatus(conditions.isEmpty() MacroLifecycle.setCurrentStatus(conditions.isEmpty()
? "Race: dispatching" ? "Race: dispatching"
: "Race: waiting for " + (conditions.size() == 1 ? conditions.get(0).getDisplayName() : conditions.size() + " conditions")); : "Race: waiting for " + (conditions.size() == 1 ? conditions.get(0).getDisplayName() : conditions.size() + " conditions"));
@ -154,11 +154,11 @@ final class MacroRace {
triggerFuture.cancel(true); triggerFuture.cancel(true);
bodyFuture.cancel(true); bodyFuture.cancel(true);
AutismClientMessaging.sendPrefixed("\u00A7eRace timed out: " + (race.label == null || race.label.isBlank() ? "Race" : race.label)); AutismClientMessaging.sendPrefixed("\u00A7eRace timed out: " + (race.label == null || race.label.isBlank() ? "Race" : race.label));
MacroExecutor.setCurrentStatus("Race: timeout"); MacroLifecycle.setCurrentStatus("Race: timeout");
return bodyCount; return bodyCount;
} }
MacroExecutor.setCurrentStatus("Race: fired"); MacroLifecycle.setCurrentStatus("Race: fired");
waitForTimedFuture(bodyFuture, 250); waitForTimedFuture(bodyFuture, 250);
return bodyCount; return bodyCount;
} }
@ -208,7 +208,7 @@ final class MacroRace {
public static int runReportGroup(Minecraft mc, java.util.List<MacroAction> actions, int headerIndex, ReportAction report) throws InterruptedException { public static int runReportGroup(Minecraft mc, java.util.List<MacroAction> actions, int headerIndex, ReportAction report) throws InterruptedException {
int conditionCount = report.normalizedConditionCount(actions, headerIndex); int conditionCount = report.normalizedConditionCount(actions, headerIndex);
if (conditionCount < 2 || headerIndex + 2 >= actions.size()) { if (conditionCount < 2 || headerIndex + 2 >= actions.size()) {
MacroExecutor.setCurrentStatus(report.getDisplayName()); MacroLifecycle.setCurrentStatus(report.getDisplayName());
report.execute(mc); report.execute(mc);
return conditionCount; return conditionCount;
} }
@ -218,13 +218,13 @@ final class MacroRace {
if (RaceAction.isBodyAction(startCondition) && RaceAction.isConditionAction(endCondition)) { if (RaceAction.isBodyAction(startCondition) && RaceAction.isConditionAction(endCondition)) {
int timeoutMs = Math.max(100, report.timeoutMs); int timeoutMs = Math.max(100, report.timeoutMs);
String label = report.reportLabel == null || report.reportLabel.isBlank() ? "Report" : report.reportLabel.trim(); String label = report.reportLabel == null || report.reportLabel.isBlank() ? "Report" : report.reportLabel.trim();
MacroExecutor.setCurrentStatus("Report: start " + startCondition.getDisplayName()); MacroLifecycle.setCurrentStatus("Report: start " + startCondition.getDisplayName());
CompletableFuture<MacroExecutor.MacroEvent> startAnchor = startActionAnchorFuture(startCondition); CompletableFuture<MacroExecutor.MacroEvent> startAnchor = startActionAnchorFuture(startCondition);
MacroDispatcher.executeSingleActionWithWaits(mc, startCondition, null); MacroDispatcher.executeSingleActionWithWaits(mc, startCondition, null);
if (!MacroExecutor.isCurrentRunActive()) return conditionCount; if (!MacroLifecycle.isCurrentRunActive()) return conditionCount;
MacroExecutor.MacroEvent startEvent = waitForAnchorOrNow(startAnchor, 250, startCondition.getDisplayName(), "client action"); MacroExecutor.MacroEvent startEvent = waitForAnchorOrNow(startAnchor, 250, startCondition.getDisplayName(), "client action");
MacroExecutor.setCurrentStatus("Report: waiting end " + endCondition.getDisplayName()); MacroLifecycle.setCurrentStatus("Report: waiting end " + endCondition.getDisplayName());
CompletableFuture<MacroExecutor.MacroEvent> endFuture = timedConditionFuture(mc, endCondition); CompletableFuture<MacroExecutor.MacroEvent> endFuture = timedConditionFuture(mc, endCondition);
MacroExecutor.MacroEvent endEvent = waitForTimedEvent(endFuture, timeoutMs); MacroExecutor.MacroEvent endEvent = waitForTimedEvent(endFuture, timeoutMs);
if (endEvent == null) { if (endEvent == null) {
@ -251,7 +251,7 @@ final class MacroRace {
int timeoutMs = Math.max(100, report.timeoutMs); int timeoutMs = Math.max(100, report.timeoutMs);
long startWaitNanos = System.nanoTime(); long startWaitNanos = System.nanoTime();
MacroExecutor.setCurrentStatus("Report: waiting start " + startCondition.getDisplayName()); MacroLifecycle.setCurrentStatus("Report: waiting start " + startCondition.getDisplayName());
boolean startFired = waitForMacroCondition(mc, startCondition, timeoutMs); boolean startFired = waitForMacroCondition(mc, startCondition, timeoutMs);
if (!startFired) { if (!startFired) {
AutismClientMessaging.sendPrefixed("\u00A7eReport \"" + report.reportLabel + "\": timeout waiting for start condition"); AutismClientMessaging.sendPrefixed("\u00A7eReport \"" + report.reportLabel + "\": timeout waiting for start condition");
@ -261,7 +261,7 @@ final class MacroRace {
MacroExecutor.MacroEvent startEvent = new MacroExecutor.MacroEvent(null, "condition " + startCondition.getDisplayName(), System.nanoTime(), null); MacroExecutor.MacroEvent startEvent = new MacroExecutor.MacroEvent(null, "condition " + startCondition.getDisplayName(), System.nanoTime(), null);
long spentMs = (startEvent.nanoTime() - startWaitNanos) / 1_000_000L; long spentMs = (startEvent.nanoTime() - startWaitNanos) / 1_000_000L;
int remainingMs = (int) Math.max(1, timeoutMs - spentMs); int remainingMs = (int) Math.max(1, timeoutMs - spentMs);
MacroExecutor.setCurrentStatus("Report: waiting end " + endCondition.getDisplayName()); MacroLifecycle.setCurrentStatus("Report: waiting end " + endCondition.getDisplayName());
CompletableFuture<MacroExecutor.MacroEvent> endFuture = timedConditionFuture(mc, endCondition); CompletableFuture<MacroExecutor.MacroEvent> endFuture = timedConditionFuture(mc, endCondition);
MacroExecutor.MacroEvent endEvent = waitForTimedEvent(endFuture, remainingMs); MacroExecutor.MacroEvent endEvent = waitForTimedEvent(endFuture, remainingMs);
if (endEvent == null) { if (endEvent == null) {
@ -318,7 +318,7 @@ final class MacroRace {
if (multi.connectIfDown) { if (multi.connectIfDown) {
if (!manager.isActive()) { if (!manager.isActive()) {
MacroExecutor.setCurrentStatus("Multi: starting batch"); MacroLifecycle.setCurrentStatus("Multi: starting batch");
autismclient.util.multi.MultiManager.StartResult started = manager.start(profile); autismclient.util.multi.MultiManager.StartResult started = manager.start(profile);
if (!started.ok()) { if (!started.ok()) {
@ -335,17 +335,17 @@ final class MacroRace {
} }
} }
} }
if (!MacroExecutor.isCurrentRunActive()) return stepCount; if (!MacroLifecycle.isCurrentRunActive()) return stepCount;
int waitMs = Math.max(0, multi.waitMs); int waitMs = Math.max(0, multi.waitMs);
if (MultiAction.WAIT_UNTIL_READY.equals(multi.waitMode)) { if (MultiAction.WAIT_UNTIL_READY.equals(multi.waitMode)) {
MacroExecutor.setCurrentStatus("Multi: waiting for " + scope.size() + (scope.size() == 1 ? " account" : " accounts")); MacroLifecycle.setCurrentStatus("Multi: waiting for " + scope.size() + (scope.size() == 1 ? " account" : " accounts"));
multiWaitUntilReady(manager, scope, waitMs); multiWaitUntilReady(manager, scope, waitMs);
} else if (MultiAction.WAIT_FIXED_DELAY.equals(multi.waitMode) && waitMs > 0) { } else if (MultiAction.WAIT_FIXED_DELAY.equals(multi.waitMode) && waitMs > 0) {
MacroExecutor.setCurrentStatus("Multi: delay " + waitMs + " ms"); MacroLifecycle.setCurrentStatus("Multi: delay " + waitMs + " ms");
multiSleepCancellable(waitMs); multiSleepCancellable(waitMs);
} }
if (!MacroExecutor.isCurrentRunActive()) return stepCount; if (!MacroLifecycle.isCurrentRunActive()) return stepCount;
AutismMacro subMacro = new AutismMacro(); AutismMacro subMacro = new AutismMacro();
subMacro.name = (macroName == null || macroName.isBlank() ? "Macro" : macroName) + " (Multi)"; subMacro.name = (macroName == null || macroName.isBlank() ? "Macro" : macroName) + " (Multi)";
@ -356,13 +356,13 @@ final class MacroRace {
if (copy != null) subMacro.actions.add(copy); if (copy != null) subMacro.actions.add(copy);
} }
MacroExecutor.setCurrentStatus("Multi: running on " + scope.size() + (scope.size() == 1 ? " account" : " accounts")); MacroLifecycle.setCurrentStatus("Multi: running on " + scope.size() + (scope.size() == 1 ? " account" : " accounts"));
autismclient.util.multi.MultiManager.BroadcastResult result = manager.runMacroDirect(subMacro, scope); autismclient.util.multi.MultiManager.BroadcastResult result = manager.runMacroDirect(subMacro, scope);
AutismClientMessaging.sendPrefixed("\u00A7bMulti: " + result.summary()); AutismClientMessaging.sendPrefixed("\u00A7bMulti: " + result.summary());
MacroExecutor.setCurrentStatus("Multi: waiting for completion"); MacroLifecycle.setCurrentStatus("Multi: waiting for completion");
multiWaitForCompletion(manager, scope, subMacro.name); multiWaitForCompletion(manager, scope, subMacro.name);
if (!MacroExecutor.isCurrentRunActive()) return stepCount; if (!MacroLifecycle.isCurrentRunActive()) return stepCount;
if (multi.disconnectAfter) { if (multi.disconnectAfter) {
for (String accountId : scope) { for (String accountId : scope) {
@ -386,14 +386,14 @@ final class MacroRace {
long deadline = System.nanoTime() + Math.max(0L, totalMs) * 1_000_000L; long deadline = System.nanoTime() + Math.max(0L, totalMs) * 1_000_000L;
long remaining; long remaining;
while ((remaining = deadline - System.nanoTime()) > 0L) { while ((remaining = deadline - System.nanoTime()) > 0L) {
if (!MacroExecutor.isCurrentRunActive()) return; if (!MacroLifecycle.isCurrentRunActive()) return;
Thread.sleep(Math.min(100L, Math.max(1L, remaining / 1_000_000L))); Thread.sleep(Math.min(100L, Math.max(1L, remaining / 1_000_000L)));
} }
} }
private static void multiWaitUntilReady(autismclient.util.multi.MultiManager manager, java.util.Set<String> scope, long timeoutMs) throws InterruptedException { private static void multiWaitUntilReady(autismclient.util.multi.MultiManager manager, java.util.Set<String> scope, long timeoutMs) throws InterruptedException {
long deadline = System.nanoTime() + Math.max(0L, timeoutMs) * 1_000_000L; long deadline = System.nanoTime() + Math.max(0L, timeoutMs) * 1_000_000L;
while (MacroExecutor.isCurrentRunActive()) { while (MacroLifecycle.isCurrentRunActive()) {
boolean allReady = true; boolean allReady = true;
java.util.Map<String, autismclient.util.multi.MultiSession.Snapshot> byId = multiSnapshotsById(manager); java.util.Map<String, autismclient.util.multi.MultiSession.Snapshot> byId = multiSnapshotsById(manager);
for (String accountId : scope) { for (String accountId : scope) {
@ -415,7 +415,7 @@ final class MacroRace {
private static void multiWaitForCompletion(autismclient.util.multi.MultiManager manager, java.util.Set<String> scope, String subMacroName) throws InterruptedException { private static void multiWaitForCompletion(autismclient.util.multi.MultiManager manager, java.util.Set<String> scope, String subMacroName) throws InterruptedException {
long deadline = System.nanoTime() + 10L * 60L * 1_000_000_000L; long deadline = System.nanoTime() + 10L * 60L * 1_000_000_000L;
Thread.sleep(200L); Thread.sleep(200L);
while (MacroExecutor.isCurrentRunActive()) { while (MacroLifecycle.isCurrentRunActive()) {
boolean anyPending = false; boolean anyPending = false;
java.util.Map<String, autismclient.util.multi.MultiSession.Snapshot> byId = multiSnapshotsById(manager); java.util.Map<String, autismclient.util.multi.MultiSession.Snapshot> byId = multiSnapshotsById(manager);
for (String accountId : scope) { for (String accountId : scope) {
@ -464,7 +464,7 @@ final class MacroRace {
if (run != null) MacroExecutor.CURRENT_RUN.set(run); if (run != null) MacroExecutor.CURRENT_RUN.set(run);
EnumSet<SharedClientResource> heldResources = EnumSet.noneOf(SharedClientResource.class); EnumSet<SharedClientResource> heldResources = EnumSet.noneOf(SharedClientResource.class);
try { try {
heldResources = MacroExecutor.acquireClientResources(MacroExecutor.resourcesForActions(bodyActions)); heldResources = MacroLifecycle.acquireClientResources(MacroLifecycle.resourcesForActions(bodyActions));
Throwable firstFailure = null; Throwable firstFailure = null;
for (MacroAction body : bodyActions) { for (MacroAction body : bodyActions) {
if (body == null || !body.isEnabled() || !RaceAction.isBodyAction(body)) continue; if (body == null || !body.isEnabled() || !RaceAction.isBodyAction(body)) continue;
@ -490,7 +490,7 @@ final class MacroRace {
AutismClientMessaging.sendPrefixed("\u00A7cRace action failed: " + safeThrowableMessage(t)); AutismClientMessaging.sendPrefixed("\u00A7cRace action failed: " + safeThrowableMessage(t));
bodyFuture.completeExceptionally(t); bodyFuture.completeExceptionally(t);
} finally { } finally {
MacroExecutor.releaseClientResources(heldResources); MacroLifecycle.releaseClientResources(heldResources);
if (previous != null) MacroExecutor.CURRENT_RUN.set(previous); if (previous != null) MacroExecutor.CURRENT_RUN.set(previous);
else MacroExecutor.CURRENT_RUN.remove(); else MacroExecutor.CURRENT_RUN.remove();
} }
@ -564,7 +564,7 @@ final class MacroRace {
try { try {
if (timeoutMs <= 0) future.get(); if (timeoutMs <= 0) future.get();
else future.get(timeoutMs, TimeUnit.MILLISECONDS); else future.get(timeoutMs, TimeUnit.MILLISECONDS);
return !future.isCancelled() && MacroExecutor.isCurrentRunActive(); return !future.isCancelled() && MacroLifecycle.isCurrentRunActive();
} catch (InterruptedException e) { } catch (InterruptedException e) {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
future.cancel(true); future.cancel(true);
@ -594,7 +594,7 @@ final class MacroRace {
return CompletableFuture.completedFuture(new MacroExecutor.MacroEvent(null, "condition", System.nanoTime(), null)); return CompletableFuture.completedFuture(new MacroExecutor.MacroEvent(null, "condition", System.nanoTime(), null));
} }
if (trigger instanceof WaitForChatAction chat) { if (trigger instanceof WaitForChatAction chat) {
MacroVariableContext context = MacroExecutor.currentVariableContext(); MacroVariableContext context = MacroLifecycle.currentVariableContext();
java.util.concurrent.atomic.AtomicReference<java.util.Map<String, MacroValue>> captures = java.util.concurrent.atomic.AtomicReference<java.util.Map<String, MacroValue>> captures =
new java.util.concurrent.atomic.AtomicReference<>(java.util.Map.of()); new java.util.concurrent.atomic.AtomicReference<>(java.util.Map.of());
MacroPacketObserve.TimedOneShotPacketListener listener = MacroPacketObserve.awaitTimedReceive((packet, direction, now) -> { MacroPacketObserve.TimedOneShotPacketListener listener = MacroPacketObserve.awaitTimedReceive((packet, direction, now) -> {
@ -693,7 +693,7 @@ final class MacroRace {
if (base == null) { if (base == null) {
CompletableFuture<MacroExecutor.MacroEvent> done = new CompletableFuture<>(); CompletableFuture<MacroExecutor.MacroEvent> done = new CompletableFuture<>();
MacroExecutor.RunState run = MacroExecutor.CURRENT_RUN.get(); MacroExecutor.RunState run = MacroExecutor.CURRENT_RUN.get();
mc.execute(() -> MacroExecutor.withRunContext(run, () -> { mc.execute(() -> MacroLifecycle.withRunContext(run, () -> {
try { try {
MacroDispatcher.executeSingleActionWithWaits(mc, trigger, null); MacroDispatcher.executeSingleActionWithWaits(mc, trigger, null);
done.complete(new MacroExecutor.MacroEvent(null, trigger.getDisplayName(), System.nanoTime(), null)); done.complete(new MacroExecutor.MacroEvent(null, trigger.getDisplayName(), System.nanoTime(), null));
@ -726,10 +726,10 @@ final class MacroRace {
} }
if (trigger instanceof DelayAction delay) { if (trigger instanceof DelayAction delay) {
MacroExecutor.RunState run = MacroExecutor.CURRENT_RUN.get(); MacroExecutor.RunState run = MacroExecutor.CURRENT_RUN.get();
return CompletableFuture.runAsync(() -> MacroExecutor.withRunContext(run, () -> { return CompletableFuture.runAsync(() -> MacroLifecycle.withRunContext(run, () -> {
try { try {
if (delay.useTicks) { if (delay.useTicks) {
for (int i = 0; i < delay.delayTicks && MacroExecutor.isCurrentRunActive(); i++) { for (int i = 0; i < delay.delayTicks && MacroLifecycle.isCurrentRunActive(); i++) {
MacroRunLoop.waitForCondition(MacroConditionRegistry.waitForNextTick()); MacroRunLoop.waitForCondition(MacroConditionRegistry.waitForNextTick());
} }
} else { } else {
@ -743,11 +743,11 @@ final class MacroRace {
if (trigger instanceof WaitForGuiAction gui) { if (trigger instanceof WaitForGuiAction gui) {
CompletableFuture<MacroExecutor.MacroEvent> done = new CompletableFuture<>(); CompletableFuture<MacroExecutor.MacroEvent> done = new CompletableFuture<>();
MacroExecutor.RunState run = MacroExecutor.CURRENT_RUN.get(); MacroExecutor.RunState run = MacroExecutor.CURRENT_RUN.get();
Thread worker = new Thread(() -> MacroExecutor.withRunContext(run, () -> { Thread worker = new Thread(() -> MacroLifecycle.withRunContext(run, () -> {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
boolean saw = false; boolean saw = false;
java.util.Map<String, MacroValue> observed = java.util.Map.of(); java.util.Map<String, MacroValue> observed = java.util.Map.of();
while (!done.isDone() && MacroExecutor.isCurrentRunActive()) { while (!done.isDone() && MacroLifecycle.isCurrentRunActive()) {
var captured = gui.captureGui(Minecraft.getInstance().gui.screen()); var captured = gui.captureGui(Minecraft.getInstance().gui.screen());
if (captured.isPresent()) { if (captured.isPresent()) {
saw = true; saw = true;
@ -773,7 +773,7 @@ final class MacroRace {
return done; return done;
} }
if (trigger instanceof WaitForChatAction chat) { if (trigger instanceof WaitForChatAction chat) {
MacroVariableContext context = MacroExecutor.currentVariableContext(); MacroVariableContext context = MacroLifecycle.currentVariableContext();
MacroExecutor.OneShotPacketListener listener = MacroExecutor.awaitReceive(packet -> { MacroExecutor.OneShotPacketListener listener = MacroExecutor.awaitReceive(packet -> {
MacroExecutor.ChatCapture capture = MacroChatObserve.extractIncomingChat(packet); MacroExecutor.ChatCapture capture = MacroChatObserve.extractIncomingChat(packet);
return capture != null && MacroChatObserve.captureChatAction(chat, capture, context).isPresent(); return capture != null && MacroChatObserve.captureChatAction(chat, capture, context).isPresent();
@ -900,7 +900,7 @@ final class MacroRace {
} }
if (trigger instanceof RevisionSyncAction) { if (trigger instanceof RevisionSyncAction) {
MacroExecutor.RunState run = MacroExecutor.CURRENT_RUN.get(); MacroExecutor.RunState run = MacroExecutor.CURRENT_RUN.get();
return CompletableFuture.runAsync(() -> MacroExecutor.withRunContext(run, () -> { return CompletableFuture.runAsync(() -> MacroLifecycle.withRunContext(run, () -> {
try { try {
MacroDispatcher.executeSingleActionWithWaits(mc, trigger, null); MacroDispatcher.executeSingleActionWithWaits(mc, trigger, null);
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -916,11 +916,11 @@ final class MacroRace {
long start = System.nanoTime(); long start = System.nanoTime();
long timeoutNanos = timeoutMs <= 0 ? Long.MAX_VALUE : timeoutMs * 1_000_000L; long timeoutNanos = timeoutMs <= 0 ? Long.MAX_VALUE : timeoutMs * 1_000_000L;
future.whenComplete((v, e) -> java.util.concurrent.locks.LockSupport.unpark(t)); future.whenComplete((v, e) -> java.util.concurrent.locks.LockSupport.unpark(t));
while (!future.isDone() && MacroExecutor.isCurrentRunActive()) { while (!future.isDone() && MacroLifecycle.isCurrentRunActive()) {
if (System.nanoTime() - start >= timeoutNanos) break; if (System.nanoTime() - start >= timeoutNanos) break;
java.util.concurrent.locks.LockSupport.parkNanos(MacroExecutor.MACRO_WAIT_POLL_NANOS); java.util.concurrent.locks.LockSupport.parkNanos(MacroExecutor.MACRO_WAIT_POLL_NANOS);
if (Thread.interrupted()) break; if (Thread.interrupted()) break;
} }
return future.isDone() && !future.isCancelled() && MacroExecutor.isCurrentRunActive(); return future.isDone() && !future.isCancelled() && MacroLifecycle.isCurrentRunActive();
} }
} }

View file

@ -92,7 +92,7 @@ final class MacroRender {
static void waitForSmoothRotationCompletion() { static void waitForSmoothRotationCompletion() {
MacroExecutor.RunState run = MacroExecutor.CURRENT_RUN.get(); MacroExecutor.RunState run = MacroExecutor.CURRENT_RUN.get();
while (MacroExecutor.isCurrentRunActive() && MacroExecutor.isRotating.get() while (MacroLifecycle.isCurrentRunActive() && MacroExecutor.isRotating.get()
&& (run == null || MacroExecutor.ROTATION_OWNER.get() == run)) { && (run == null || MacroExecutor.ROTATION_OWNER.get() == run)) {
java.util.concurrent.locks.LockSupport.parkNanos(1_000_000L); java.util.concurrent.locks.LockSupport.parkNanos(1_000_000L);
} }
@ -119,7 +119,7 @@ final class MacroRender {
latch.countDown(); latch.countDown();
} }
}); });
while (MacroExecutor.isCurrentRunActive()) { while (MacroLifecycle.isCurrentRunActive()) {
try { try {
if (latch.await(10, java.util.concurrent.TimeUnit.MILLISECONDS)) { if (latch.await(10, java.util.concurrent.TimeUnit.MILLISECONDS)) {
break; break;

View file

@ -29,7 +29,7 @@ final class MacroRunLoop {
try { AutismClientMessaging.sendPrefixed("\u00a7cMacro crashed: " + fatal.getMessage()); } catch (Throwable ignored) { } try { AutismClientMessaging.sendPrefixed("\u00a7cMacro crashed: " + fatal.getMessage()); } catch (Throwable ignored) { }
} }
} finally { } finally {
MacroExecutor.finishCurrentRun(); MacroLifecycle.finishCurrentRun();
MacroExecutor.CURRENT_RUN.remove(); MacroExecutor.CURRENT_RUN.remove();
} }
} }
@ -42,24 +42,24 @@ final class MacroRunLoop {
int loopCount = 0; int loopCount = 0;
int maxLoops = macro.loop ? (macro.loopCount == -1 ? Integer.MAX_VALUE : macro.loopCount) : 1; int maxLoops = macro.loop ? (macro.loopCount == -1 ? Integer.MAX_VALUE : macro.loopCount) : 1;
MacroExecutor.currentPersistentActions().clear(); MacroLifecycle.currentPersistentActions().clear();
MacroExecutor.currentBackgroundMoves().clear(); MacroLifecycle.currentBackgroundMoves().clear();
Thread persistentThread = new Thread(() -> { Thread persistentThread = new Thread(() -> {
MacroExecutor.CURRENT_RUN.set(runState); MacroExecutor.CURRENT_RUN.set(runState);
try { try {
while (MacroExecutor.isCurrentRunActive()) { while (MacroLifecycle.isCurrentRunActive()) {
if (!MacroExecutor.currentPersistentActions().isEmpty() || !MacroExecutor.currentBackgroundMoves().isEmpty()) { if (!MacroLifecycle.currentPersistentActions().isEmpty() || !MacroLifecycle.currentBackgroundMoves().isEmpty()) {
MacroExecutor.RunState scheduledRun = MacroExecutor.CURRENT_RUN.get(); MacroExecutor.RunState scheduledRun = MacroExecutor.CURRENT_RUN.get();
mc.execute(() -> MacroExecutor.withRunContext(scheduledRun, () -> { mc.execute(() -> MacroLifecycle.withRunContext(scheduledRun, () -> {
ReentrantLock inputLock = MacroExecutor.SHARED_RESOURCE_LOCKS.get(SharedClientResource.INPUT); ReentrantLock inputLock = MacroExecutor.SHARED_RESOURCE_LOCKS.get(SharedClientResource.INPUT);
inputLock.lock(); inputLock.lock();
try { try {
for (MacroAction pa : MacroExecutor.currentPersistentActions()) { for (MacroAction pa : MacroLifecycle.currentPersistentActions()) {
try { pa.execute(mc); } catch (Exception ignored) { } try { pa.execute(mc); } catch (Exception ignored) { }
} }
java.util.Iterator<java.util.Map.Entry<MoveAction, int[]>> it = MacroExecutor.currentBackgroundMoves().entrySet().iterator(); java.util.Iterator<java.util.Map.Entry<MoveAction, int[]>> it = MacroLifecycle.currentBackgroundMoves().entrySet().iterator();
while (it.hasNext()) { while (it.hasNext()) {
java.util.Map.Entry<MoveAction, int[]> entry = it.next(); java.util.Map.Entry<MoveAction, int[]> entry = it.next();
MoveAction bma = entry.getKey(); MoveAction bma = entry.getKey();
@ -68,8 +68,8 @@ final class MacroRunLoop {
bma.execute(mc); bma.execute(mc);
ticks[0]--; ticks[0]--;
} else { } else {
MacroExecutor.releaseMoveIfUnused(scheduledRun, bma, mc); MacroLifecycle.releaseMoveIfUnused(scheduledRun, bma, mc);
MacroExecutor.currentBackgroundMoves().remove(bma); MacroLifecycle.currentBackgroundMoves().remove(bma);
} }
} }
} finally { } finally {
@ -82,12 +82,12 @@ final class MacroRunLoop {
CompletableFuture<Void> tf = MacroConditionRegistry.waitForNextTick(); CompletableFuture<Void> tf = MacroConditionRegistry.waitForNextTick();
tf.get(100, java.util.concurrent.TimeUnit.MILLISECONDS); tf.get(100, java.util.concurrent.TimeUnit.MILLISECONDS);
} catch (Exception e) { } catch (Exception e) {
if (!MacroExecutor.isCurrentRunActive()) break; if (!MacroLifecycle.isCurrentRunActive()) break;
} }
} }
} finally { } finally {
MacroExecutor.releaseBackgroundMoves(MacroExecutor.currentBackgroundMoves(), mc, runState); MacroLifecycle.releaseBackgroundMoves(MacroLifecycle.currentBackgroundMoves(), mc, runState);
MacroExecutor.currentBackgroundMoves().clear(); MacroLifecycle.currentBackgroundMoves().clear();
MacroExecutor.CURRENT_RUN.remove(); MacroExecutor.CURRENT_RUN.remove();
} }
}, "Autism-Macro-Persistent-" + runState.id); }, "Autism-Macro-Persistent-" + runState.id);
@ -95,13 +95,13 @@ final class MacroRunLoop {
persistentThread.start(); persistentThread.start();
try { try {
while (MacroExecutor.isCurrentRunActive() && loopCount < maxLoops) { while (MacroLifecycle.isCurrentRunActive() && loopCount < maxLoops) {
if (macro.actions.isEmpty()) { if (macro.actions.isEmpty()) {
if (!runState.options.silentLifecycle()) AutismClientMessaging.sendPrefixed("\u00a7cMacro stopped: no actions left."); if (!runState.options.silentLifecycle()) AutismClientMessaging.sendPrefixed("\u00a7cMacro stopped: no actions left.");
MacroExecutor.stopCurrentRun(); MacroLifecycle.stopCurrentRun();
break; break;
} }
MacroExecutor.setCurrentStatus("Loop " + (loopCount + 1) + (maxLoops == Integer.MAX_VALUE ? "" : "/" + maxLoops)); MacroLifecycle.setCurrentStatus("Loop " + (loopCount + 1) + (maxLoops == Integer.MAX_VALUE ? "" : "/" + maxLoops));
AutismModule module = AutismModule.get(); AutismModule module = AutismModule.get();
boolean burstMode = module.usePacketBurstMode(); boolean burstMode = module.usePacketBurstMode();
@ -114,11 +114,11 @@ final class MacroRunLoop {
runState.lastCompletedStep = 0; runState.lastCompletedStep = 0;
for (int i = 0; i < macro.actions.size(); i++) { for (int i = 0; i < macro.actions.size(); i++) {
if (!MacroExecutor.isCurrentRunActive()) break; if (!MacroLifecycle.isCurrentRunActive()) break;
MacroExecutor.setCurrentStep(i, macro.actions.size()); MacroLifecycle.setCurrentStep(i, macro.actions.size());
MacroExecutor.updateStepBoundOverrides(runState, i); MacroLifecycle.updateStepBoundOverrides(runState, i);
if (runState.branchElseStart == i && runState.branchElseCount > 0) { if (runState.branchElseStart == i && runState.branchElseCount > 0) {
i += runState.branchElseCount - 1; i += runState.branchElseCount - 1;
runState.branchElseStart = -1; runState.branchElseStart = -1;
@ -182,10 +182,10 @@ final class MacroRunLoop {
if (action instanceof FlowAction flow) { if (action instanceof FlowAction flow) {
if (flow.shouldTake(mc)) { if (flow.shouldTake(mc)) {
int newI = MacroExecutor.performFlowJump(runState, macro, i, flow, mc); int newI = MacroLifecycle.performFlowJump(runState, macro, i, flow, mc);
if (newI == Integer.MIN_VALUE) { if (newI == Integer.MIN_VALUE) {
MacroExecutor.broadcastStepProgress(runState, i + 1, macro.actions.size(), macro.name); MacroLifecycle.broadcastStepProgress(runState, i + 1, macro.actions.size(), macro.name);
MacroExecutor.stopCurrentRun(); MacroLifecycle.stopCurrentRun();
break; break;
} }
i = newI; i = newI;
@ -195,7 +195,7 @@ final class MacroRunLoop {
MacroPrearm.prearmNextActionWait(mc, macro.actions, i); MacroPrearm.prearmNextActionWait(mc, macro.actions, i);
EnumSet<SharedClientResource> heldResources = MacroExecutor.acquireClientResources(action); EnumSet<SharedClientResource> heldResources = MacroLifecycle.acquireClientResources(action);
try { try {
if (!MacroActionRunner.waitForGuiBeforeAction(mc, action)) continue; if (!MacroActionRunner.waitForGuiBeforeAction(mc, action)) continue;
@ -225,7 +225,7 @@ final class MacroRunLoop {
if (da.useTicks) { if (da.useTicks) {
for (int t = 0; t < da.delayTicks; t++) { for (int t = 0; t < da.delayTicks; t++) {
if (!MacroExecutor.isCurrentRunActive()) break; if (!MacroLifecycle.isCurrentRunActive()) break;
CompletableFuture<Void> future = MacroConditionRegistry.waitForNextTick(); CompletableFuture<Void> future = MacroConditionRegistry.waitForNextTick();
waitForCondition(future); waitForCondition(future);
@ -236,14 +236,14 @@ final class MacroRunLoop {
} }
} }
else if (action instanceof CustomMenuAction customMenu) { else if (action instanceof CustomMenuAction customMenu) {
MacroExecutor.setCurrentStatus(customMenu.getDisplayName()); MacroLifecycle.setCurrentStatus(customMenu.getDisplayName());
customMenu.execute(mc); customMenu.execute(mc);
} }
else if (action instanceof FpsAction fps) { else if (action instanceof FpsAction fps) {
MacroExecutor.setCurrentStatus(fps.getDisplayName()); MacroLifecycle.setCurrentStatus(fps.getDisplayName());
if (fps.endMode() == FpsAction.EndMode.TIMEOUT) { if (fps.endMode() == FpsAction.EndMode.TIMEOUT) {
MacroExecutor.clearFpsStepOverride(runState); MacroLifecycle.clearFpsStepOverride(runState);
long fpsDurationNanos = fps.durationMillis() * 1_000_000L; long fpsDurationNanos = fps.durationMillis() * 1_000_000L;
long fpsDeadline = System.nanoTime() + fpsDurationNanos; long fpsDeadline = System.nanoTime() + fpsDurationNanos;
FpsLimitController.apply(runState.id, Math.max(0, fps.maxFps), fpsDurationNanos); FpsLimitController.apply(runState.id, Math.max(0, fps.maxFps), fpsDurationNanos);
@ -253,7 +253,7 @@ final class MacroRunLoop {
} else { } else {
long fpsRemaining; long fpsRemaining;
while (MacroExecutor.isCurrentRunActive() && (fpsRemaining = fpsDeadline - System.nanoTime()) > 0L) { while (MacroLifecycle.isCurrentRunActive() && (fpsRemaining = fpsDeadline - System.nanoTime()) > 0L) {
Thread.sleep(Math.min(25L, fpsRemaining / 1_000_000L + 1L)); Thread.sleep(Math.min(25L, fpsRemaining / 1_000_000L + 1L));
} }
FpsLimitController.clear(runState.id); FpsLimitController.clear(runState.id);
@ -264,17 +264,17 @@ final class MacroRunLoop {
int covered = fps.endMode() == FpsAction.EndMode.END int covered = fps.endMode() == FpsAction.EndMode.END
? macro.actions.size() - 1 - i ? macro.actions.size() - 1 - i
: fps.normalizedStepCount(); : fps.normalizedStepCount();
int endIndex = MacroExecutor.stepOverrideEndIndex(macro, i, covered); int endIndex = MacroLifecycle.stepOverrideEndIndex(macro, i, covered);
MacroExecutor.armFpsStepOverride(runState, i, endIndex, Math.max(1, fps.maxFps)); MacroLifecycle.armFpsStepOverride(runState, i, endIndex, Math.max(1, fps.maxFps));
runState.fpsBackgroundDeadlineNanos = 0L; runState.fpsBackgroundDeadlineNanos = 0L;
} }
} }
else if (action instanceof SPingAction sping) { else if (action instanceof SPingAction sping) {
MacroExecutor.setCurrentStatus(sping.getDisplayName()); MacroLifecycle.setCurrentStatus(sping.getDisplayName());
if (sping.endMode() == SPingAction.EndMode.TIMEOUT) { if (sping.endMode() == SPingAction.EndMode.TIMEOUT) {
MacroExecutor.clearPingStepOverride(runState); MacroLifecycle.clearPingStepOverride(runState);
long spingDurationNanos = sping.durationMillis() * 1_000_000L; long spingDurationNanos = sping.durationMillis() * 1_000_000L;
long spingDeadline = System.nanoTime() + spingDurationNanos; long spingDeadline = System.nanoTime() + spingDurationNanos;
PingSpoofController.apply(runState.id, Math.max(0, sping.pingDelayMs), PingSpoofController.apply(runState.id, Math.max(0, sping.pingDelayMs),
@ -285,7 +285,7 @@ final class MacroRunLoop {
} else { } else {
long spingRemaining; long spingRemaining;
while (MacroExecutor.isCurrentRunActive() && (spingRemaining = spingDeadline - System.nanoTime()) > 0L) { while (MacroLifecycle.isCurrentRunActive() && (spingRemaining = spingDeadline - System.nanoTime()) > 0L) {
Thread.sleep(Math.min(25L, spingRemaining / 1_000_000L + 1L)); Thread.sleep(Math.min(25L, spingRemaining / 1_000_000L + 1L));
} }
PingSpoofController.clearMacro(runState.id); PingSpoofController.clearMacro(runState.id);
@ -295,8 +295,8 @@ final class MacroRunLoop {
int covered = sping.endMode() == SPingAction.EndMode.END int covered = sping.endMode() == SPingAction.EndMode.END
? macro.actions.size() - 1 - i ? macro.actions.size() - 1 - i
: sping.normalizedStepCount(); : sping.normalizedStepCount();
int endIndex = MacroExecutor.stepOverrideEndIndex(macro, i, covered); int endIndex = MacroLifecycle.stepOverrideEndIndex(macro, i, covered);
MacroExecutor.armPingStepOverride(runState, i, endIndex, MacroLifecycle.armPingStepOverride(runState, i, endIndex,
Math.max(0, sping.pingDelayMs), sping.realIncoming, sping.realOutgoing); Math.max(0, sping.pingDelayMs), sping.realIncoming, sping.realOutgoing);
runState.pingBackgroundDeadlineNanos = 0L; runState.pingBackgroundDeadlineNanos = 0L;
} }
@ -325,35 +325,35 @@ final class MacroRunLoop {
if (prearmed == null) MacroPacketWait.awaitPacket(""); if (prearmed == null) MacroPacketWait.awaitPacket("");
} else { } else {
for (int targetIndex = Math.min(startTarget, targets.size()); targetIndex < targets.size(); targetIndex++) { for (int targetIndex = Math.min(startTarget, targets.size()); targetIndex < targets.size(); targetIndex++) {
if (!MacroExecutor.isCurrentRunActive()) break; if (!MacroLifecycle.isCurrentRunActive()) break;
MacroPacketWait.awaitPacket(targets.get(targetIndex)); MacroPacketWait.awaitPacket(targets.get(targetIndex));
} }
} }
MacroPrearm.copyLastMatchedPacket(packetAction); MacroPrearm.copyLastMatchedPacket(packetAction);
} }
else if (action instanceof WaitPacketMatchAction wpma) { else if (action instanceof WaitPacketMatchAction wpma) {
MacroExecutor.setCurrentStatus(wpma.getDisplayName()); MacroLifecycle.setCurrentStatus(wpma.getDisplayName());
if (!MacroPrearm.waitForPrearmed(wpma, wpma.timeoutMs)) MacroPrearm.waitForPacketMatch(wpma); if (!MacroPrearm.waitForPrearmed(wpma, wpma.timeoutMs)) MacroPrearm.waitForPacketMatch(wpma);
} }
else if (action instanceof WaitInventoryPredicateAction wipa) { else if (action instanceof WaitInventoryPredicateAction wipa) {
MacroExecutor.setCurrentStatus(wipa.getDisplayName()); MacroLifecycle.setCurrentStatus(wipa.getDisplayName());
if (!MacroPrearm.waitForPrearmed(wipa, wipa.timeoutMs)) waitForPredicate(() -> wipa.matches(mc), wipa.timeoutMs); if (!MacroPrearm.waitForPrearmed(wipa, wipa.timeoutMs)) waitForPredicate(() -> wipa.matches(mc), wipa.timeoutMs);
} }
else if (action instanceof WaitDurabilityAction wda) { else if (action instanceof WaitDurabilityAction wda) {
MacroExecutor.setCurrentStatus(wda.getDisplayName()); MacroLifecycle.setCurrentStatus(wda.getDisplayName());
if (wda.useNext) MacroDurability.waitForDurabilityUseNext(mc, wda); if (wda.useNext) MacroDurability.waitForDurabilityUseNext(mc, wda);
else if (!MacroPrearm.waitForPrearmed(wda, wda.timeoutMs)) waitForPredicate(() -> wda.matches(mc), wda.timeoutMs); else if (!MacroPrearm.waitForPrearmed(wda, wda.timeoutMs)) waitForPredicate(() -> wda.matches(mc), wda.timeoutMs);
} }
else if (action instanceof WaitFreeSlotsAction wfsa) { else if (action instanceof WaitFreeSlotsAction wfsa) {
MacroExecutor.setCurrentStatus(wfsa.getDisplayName()); MacroLifecycle.setCurrentStatus(wfsa.getDisplayName());
if (!MacroPrearm.waitForPrearmed(wfsa, wfsa.timeoutMs)) waitForPredicate(() -> wfsa.matches(mc), wfsa.timeoutMs); if (!MacroPrearm.waitForPrearmed(wfsa, wfsa.timeoutMs)) waitForPredicate(() -> wfsa.matches(mc), wfsa.timeoutMs);
} }
else if (action instanceof WaitEntityTargetAction weta) { else if (action instanceof WaitEntityTargetAction weta) {
MacroExecutor.setCurrentStatus(weta.getDisplayName()); MacroLifecycle.setCurrentStatus(weta.getDisplayName());
if (!MacroPrearm.waitForPrearmed(weta, weta.timeoutMs)) waitForPredicate(() -> weta.matches(mc), weta.timeoutMs); if (!MacroPrearm.waitForPrearmed(weta, weta.timeoutMs)) waitForPredicate(() -> weta.matches(mc), weta.timeoutMs);
} }
else if (action instanceof WaitGuiTypeAction wgta) { else if (action instanceof WaitGuiTypeAction wgta) {
MacroExecutor.setCurrentStatus(wgta.getDisplayName()); MacroLifecycle.setCurrentStatus(wgta.getDisplayName());
if (!MacroPrearm.hasPrearmedWait(wgta)) MacroPrearm.clearCaptureOutputs(wgta); if (!MacroPrearm.hasPrearmedWait(wgta)) MacroPrearm.clearCaptureOutputs(wgta);
if (MacroPrearm.waitForPrearmed(wgta, wgta.timeoutMs)) { if (MacroPrearm.waitForPrearmed(wgta, wgta.timeoutMs)) {
} else if (wgta.waitMode == WaitGuiTypeAction.WaitMode.CLOSE) { } else if (wgta.waitMode == WaitGuiTypeAction.WaitMode.CLOSE) {
@ -370,7 +370,7 @@ final class MacroRunLoop {
} }
else if (action instanceof WaitForHealthAction) { else if (action instanceof WaitForHealthAction) {
WaitForHealthAction wh = (WaitForHealthAction) action; WaitForHealthAction wh = (WaitForHealthAction) action;
MacroExecutor.setCurrentStatus(wh.waitingStatusText()); MacroLifecycle.setCurrentStatus(wh.waitingStatusText());
try { try {
if (!MacroPrearm.waitForPrearmed(wh, 0)) { if (!MacroPrearm.waitForPrearmed(wh, 0)) {
CompletableFuture<Void> future = MacroConditionRegistry.waitForHealth( CompletableFuture<Void> future = MacroConditionRegistry.waitForHealth(
@ -381,7 +381,7 @@ final class MacroRunLoop {
} }
else if (action instanceof WaitForBlockAction) { else if (action instanceof WaitForBlockAction) {
WaitForBlockAction wba = (WaitForBlockAction) action; WaitForBlockAction wba = (WaitForBlockAction) action;
MacroExecutor.setCurrentStatus(wba.getDisplayName()); MacroLifecycle.setCurrentStatus(wba.getDisplayName());
try { try {
if (!MacroPrearm.waitForPrearmed(wba, 0)) { if (!MacroPrearm.waitForPrearmed(wba, 0)) {
CompletableFuture<Void> future = MacroConditionRegistry.waitForBlock(wba); CompletableFuture<Void> future = MacroConditionRegistry.waitForBlock(wba);
@ -394,11 +394,11 @@ final class MacroRunLoop {
if (!MacroPrearm.hasPrearmedWait(wga)) MacroPrearm.clearCaptureOutputs(wga); if (!MacroPrearm.hasPrearmedWait(wga)) MacroPrearm.clearCaptureOutputs(wga);
if (MacroPrearm.waitForPrearmed(wga, 0)) { if (MacroPrearm.waitForPrearmed(wga, 0)) {
} else if (wga.waitMode == WaitForGuiAction.WaitMode.CLOSE) { } else if (wga.waitMode == WaitForGuiAction.WaitMode.CLOSE) {
MacroExecutor.setCurrentStatus("Waiting for GUI close: " + wga.guiTitle); MacroLifecycle.setCurrentStatus("Waiting for GUI close: " + wga.guiTitle);
waitForPredicate(guiClosePredicate(wga, mc), wga.timeoutMs); waitForPredicate(guiClosePredicate(wga, mc), wga.timeoutMs);
MacroPrearm.commitStagedCapture(wga); MacroPrearm.commitStagedCapture(wga);
} else { } else {
MacroExecutor.setCurrentStatus("Waiting for GUI: " + wga.guiTitle); MacroLifecycle.setCurrentStatus("Waiting for GUI: " + wga.guiTitle);
waitForPredicate(() -> { waitForPredicate(() -> {
var captured = wga.captureGui(mc.gui.screen()); var captured = wga.captureGui(mc.gui.screen());
captured.ifPresent(values -> MacroPrearm.stageCapture(wga, values)); captured.ifPresent(values -> MacroPrearm.stageCapture(wga, values));
@ -412,7 +412,7 @@ final class MacroRunLoop {
ItemTarget cooldownTarget = MacroWorldActions.resolveItemTarget(wca.itemTarget, wca.itemName).resolveTemplate(mc); ItemTarget cooldownTarget = MacroWorldActions.resolveItemTarget(wca.itemTarget, wca.itemName).resolveTemplate(mc);
if (cooldownTarget == null) continue; if (cooldownTarget == null) continue;
String cooldownLabel = MacroWorldActions.describeItemTarget(cooldownTarget); String cooldownLabel = MacroWorldActions.describeItemTarget(cooldownTarget);
MacroExecutor.setCurrentStatus("Waiting for cooldown: " + MacroLifecycle.setCurrentStatus("Waiting for cooldown: " +
(!cooldownLabel.isEmpty() ? cooldownLabel : (wca.checkMainInteractionHand ? "Main Hand" : "Off Hand"))); (!cooldownLabel.isEmpty() ? cooldownLabel : (wca.checkMainInteractionHand ? "Main Hand" : "Off Hand")));
try { try {
if (!MacroPrearm.waitForPrearmed(wca, 0)) { if (!MacroPrearm.waitForPrearmed(wca, 0)) {
@ -423,7 +423,7 @@ final class MacroRunLoop {
} }
else if (action instanceof WaitPosAction) { else if (action instanceof WaitPosAction) {
WaitPosAction wpa = (WaitPosAction) action; WaitPosAction wpa = (WaitPosAction) action;
MacroExecutor.setCurrentStatus("Waiting for Pos: " + String.format("%.0f, %.0f, %.0f", wpa.x, wpa.y, wpa.z)); MacroLifecycle.setCurrentStatus("Waiting for Pos: " + String.format("%.0f, %.0f, %.0f", wpa.x, wpa.y, wpa.z));
try { try {
if (!MacroPrearm.waitForPrearmed(wpa, 0)) { if (!MacroPrearm.waitForPrearmed(wpa, 0)) {
CompletableFuture<Void> future = MacroConditionRegistry.waitForPos( CompletableFuture<Void> future = MacroConditionRegistry.waitForPos(
@ -439,7 +439,7 @@ final class MacroRunLoop {
CompletableFuture<Void> tickFuture = MacroConditionRegistry.waitForNextTick(); CompletableFuture<Void> tickFuture = MacroConditionRegistry.waitForNextTick();
waitForCondition(tickFuture); waitForCondition(tickFuture);
} else { } else {
for (int t = 0; t < ja.durationTicks && MacroExecutor.isCurrentRunActive(); t++) { for (int t = 0; t < ja.durationTicks && MacroLifecycle.isCurrentRunActive(); t++) {
CompletableFuture<Void> tickFuture = MacroConditionRegistry.waitForNextTick(); CompletableFuture<Void> tickFuture = MacroConditionRegistry.waitForNextTick();
waitForCondition(tickFuture); waitForCondition(tickFuture);
} }
@ -449,37 +449,37 @@ final class MacroRunLoop {
else if (action instanceof SneakAction) { else if (action instanceof SneakAction) {
SneakAction sna = (SneakAction) action; SneakAction sna = (SneakAction) action;
if (sna.persistent && sna.sneak) { if (sna.persistent && sna.sneak) {
MacroExecutor.currentPersistentActions().removeIf(p -> p instanceof SneakAction); MacroLifecycle.currentPersistentActions().removeIf(p -> p instanceof SneakAction);
MacroExecutor.currentPersistentActions().add(sna); MacroLifecycle.currentPersistentActions().add(sna);
} else if (!sna.sneak) { } else if (!sna.sneak) {
MacroExecutor.currentPersistentActions().removeIf(p -> p instanceof SneakAction); MacroLifecycle.currentPersistentActions().removeIf(p -> p instanceof SneakAction);
} }
if (sna.persistent || !sna.sneak) MacroClientThread.postOnClientThread(mc, () -> MacroExecutor.applyAggregateSneakState(mc), sna.isTickAligned()); if (sna.persistent || !sna.sneak) MacroClientThread.postOnClientThread(mc, () -> MacroLifecycle.applyAggregateSneakState(mc), sna.isTickAligned());
else MacroClientThread.postOnClientThread(mc, () -> sna.execute(mc), sna.isTickAligned()); else MacroClientThread.postOnClientThread(mc, () -> sna.execute(mc), sna.isTickAligned());
} }
else if (action instanceof SprintAction) { else if (action instanceof SprintAction) {
SprintAction spa = (SprintAction) action; SprintAction spa = (SprintAction) action;
if (spa.persistent && spa.sprint) { if (spa.persistent && spa.sprint) {
MacroExecutor.currentPersistentActions().removeIf(p -> p instanceof SprintAction); MacroLifecycle.currentPersistentActions().removeIf(p -> p instanceof SprintAction);
MacroExecutor.currentPersistentActions().add(spa); MacroLifecycle.currentPersistentActions().add(spa);
} else if (!spa.sprint) { } else if (!spa.sprint) {
MacroExecutor.currentPersistentActions().removeIf(p -> p instanceof SprintAction); MacroLifecycle.currentPersistentActions().removeIf(p -> p instanceof SprintAction);
} }
if (spa.persistent || !spa.sprint) MacroClientThread.postOnClientThread(mc, () -> MacroExecutor.applyAggregateSprintState(mc), spa.isTickAligned()); if (spa.persistent || !spa.sprint) MacroClientThread.postOnClientThread(mc, () -> MacroLifecycle.applyAggregateSprintState(mc), spa.isTickAligned());
else MacroClientThread.postOnClientThread(mc, () -> spa.execute(mc), spa.isTickAligned()); else MacroClientThread.postOnClientThread(mc, () -> spa.execute(mc), spa.isTickAligned());
} }
else if (action instanceof DisconnectAction) { else if (action instanceof DisconnectAction) {
DisconnectAction da2 = (DisconnectAction) action; DisconnectAction da2 = (DisconnectAction) action;
MacroExecutor.broadcastStepProgress(runState, i + 1, macro.actions.size(), macro.name); MacroLifecycle.broadcastStepProgress(runState, i + 1, macro.actions.size(), macro.name);
if (da2.mode == DisconnectAction.DisconnectMode.DISCONNECT) { if (da2.mode == DisconnectAction.DisconnectMode.DISCONNECT) {
if (da2.delayMs > 0) Thread.sleep(da2.delayMs); if (da2.delayMs > 0) Thread.sleep(da2.delayMs);
mc.execute(() -> da2.execute(mc)); mc.execute(() -> da2.execute(mc));
} else if (da2.mode == DisconnectAction.DisconnectMode.AUTO_DISCONNECT) { } else if (da2.mode == DisconnectAction.DisconnectMode.AUTO_DISCONNECT) {
MacroExecutor.setCurrentStatus("Auto Disconnect: waiting for " + da2.trigger.name() + "..."); MacroLifecycle.setCurrentStatus("Auto Disconnect: waiting for " + da2.trigger.name() + "...");
da2.execute(mc); da2.execute(mc);
MacroExecutor.setCurrentStatus("Auto Disconnect: executed"); MacroLifecycle.setCurrentStatus("Auto Disconnect: executed");
} else if (da2.mode == DisconnectAction.DisconnectMode.KICK_DUPE && da2.useNextAction) { } else if (da2.mode == DisconnectAction.DisconnectMode.KICK_DUPE && da2.useNextAction) {
java.util.List<MacroAction> nextActs = new java.util.ArrayList<>(); java.util.List<MacroAction> nextActs = new java.util.ArrayList<>();
@ -516,7 +516,7 @@ final class MacroRunLoop {
mc.execute(() -> da2.execute(mc)); mc.execute(() -> da2.execute(mc));
} }
MacroExecutor.stopCurrentRun(); MacroLifecycle.stopCurrentRun();
break; break;
} }
else if (action instanceof RaceAction race) { else if (action instanceof RaceAction race) {
@ -536,7 +536,7 @@ final class MacroRunLoop {
long delayMs = Math.max(1, nba.delayTicks) * 50L; long delayMs = Math.max(1, nba.delayTicks) * 50L;
boolean signedAny = false; boolean signedAny = false;
for (int b = 0; b < totalBooks; b++) { for (int b = 0; b < totalBooks; b++) {
if (!MacroExecutor.isCurrentRunActive()) break; if (!MacroLifecycle.isCurrentRunActive()) break;
final int bookIdx = b; final int bookIdx = b;
java.util.concurrent.CompletableFuture<Boolean> result = new java.util.concurrent.CompletableFuture<>(); java.util.concurrent.CompletableFuture<Boolean> result = new java.util.concurrent.CompletableFuture<>();
mc.execute(() -> result.complete(nba.executeSingleBook(mc, bookIdx, totalBooks))); mc.execute(() -> result.complete(nba.executeSingleBook(mc, bookIdx, totalBooks)));
@ -562,17 +562,17 @@ final class MacroRunLoop {
if (ma.nonBlocking) { if (ma.nonBlocking) {
mc.execute(() -> ma.execute(mc)); mc.execute(() -> ma.execute(mc));
MacroExecutor.currentBackgroundMoves().put(ma, new int[]{ma.durationTicks - 1}); MacroLifecycle.currentBackgroundMoves().put(ma, new int[]{ma.durationTicks - 1});
} else { } else {
for (int t = 0; t < ma.durationTicks && MacroExecutor.isCurrentRunActive(); t++) { for (int t = 0; t < ma.durationTicks && MacroLifecycle.isCurrentRunActive(); t++) {
mc.execute(() -> ma.execute(mc)); mc.execute(() -> ma.execute(mc));
CompletableFuture<Void> tickFuture = MacroConditionRegistry.waitForNextTick(); CompletableFuture<Void> tickFuture = MacroConditionRegistry.waitForNextTick();
waitForCondition(tickFuture); waitForCondition(tickFuture);
} }
MacroExecutor.RunState movementRun = MacroExecutor.CURRENT_RUN.get(); MacroExecutor.RunState movementRun = MacroExecutor.CURRENT_RUN.get();
mc.execute(() -> MacroExecutor.releaseMoveIfUnused(movementRun, ma, mc)); mc.execute(() -> MacroLifecycle.releaseMoveIfUnused(movementRun, ma, mc));
} }
} }
else if (action instanceof LookAtBlockAction) { else if (action instanceof LookAtBlockAction) {
@ -599,9 +599,9 @@ final class MacroRunLoop {
int startIdx = i + 1; int startIdx = i + 1;
int endIdx = Math.min(startIdx + ra.stepCount, macro.actions.size()); int endIdx = Math.min(startIdx + ra.stepCount, macro.actions.size());
for (int rep = 0; rep < ra.repeatCount && MacroExecutor.isCurrentRunActive(); rep++) { for (int rep = 0; rep < ra.repeatCount && MacroLifecycle.isCurrentRunActive(); rep++) {
MacroExecutor.setCurrentStatus("Repeat " + (rep + 1) + "/" + ra.repeatCount); MacroLifecycle.setCurrentStatus("Repeat " + (rep + 1) + "/" + ra.repeatCount);
for (int j = startIdx; j < endIdx && MacroExecutor.isCurrentRunActive(); j++) { for (int j = startIdx; j < endIdx && MacroLifecycle.isCurrentRunActive(); j++) {
MacroAction subAction = macro.actions.get(j); MacroAction subAction = macro.actions.get(j);
if (!subAction.isEnabled()) continue; if (!subAction.isEnabled()) continue;
@ -623,12 +623,12 @@ final class MacroRunLoop {
} }
else if (action instanceof WaitForChatAction) { else if (action instanceof WaitForChatAction) {
WaitForChatAction wca = (WaitForChatAction) action; WaitForChatAction wca = (WaitForChatAction) action;
MacroExecutor.setCurrentStatus("Waiting for chat: " + wca.pattern); MacroLifecycle.setCurrentStatus("Waiting for chat: " + wca.pattern);
if (!MacroPrearm.waitForPrearmed(wca, wca.timeoutMs)) MacroPacketWait.awaitChat(wca); if (!MacroPrearm.waitForPrearmed(wca, wca.timeoutMs)) MacroPacketWait.awaitChat(wca);
} }
else if (action instanceof WaitForEntityAction) { else if (action instanceof WaitForEntityAction) {
WaitForEntityAction wea = (WaitForEntityAction) action; WaitForEntityAction wea = (WaitForEntityAction) action;
MacroExecutor.setCurrentStatus(wea.getDisplayName()); MacroLifecycle.setCurrentStatus(wea.getDisplayName());
try { try {
if (!MacroPrearm.waitForPrearmed(wea, 0)) { if (!MacroPrearm.waitForPrearmed(wea, 0)) {
waitForPredicate(() -> wea.matchesEntityTarget(mc), wea.timeoutMs); waitForPredicate(() -> wea.matchesEntityTarget(mc), wea.timeoutMs);
@ -638,7 +638,7 @@ final class MacroRunLoop {
else if (action instanceof WaitForSoundAction) { else if (action instanceof WaitForSoundAction) {
WaitForSoundAction wsa = (WaitForSoundAction) action; WaitForSoundAction wsa = (WaitForSoundAction) action;
String sndDesc = wsa.soundIds.isEmpty() ? "any" : wsa.soundIds.get(0); String sndDesc = wsa.soundIds.isEmpty() ? "any" : wsa.soundIds.get(0);
MacroExecutor.setCurrentStatus("Waiting for sound: " + sndDesc); MacroLifecycle.setCurrentStatus("Waiting for sound: " + sndDesc);
try { try {
if (!MacroPrearm.waitForPrearmed(wsa, 0)) { if (!MacroPrearm.waitForPrearmed(wsa, 0)) {
CompletableFuture<Void> future = MacroConditionRegistry.waitForSound(wsa); CompletableFuture<Void> future = MacroConditionRegistry.waitForSound(wsa);
@ -656,7 +656,7 @@ final class MacroRunLoop {
else if (action instanceof BreakAction breakAction) { else if (action instanceof BreakAction breakAction) {
MacroExecutor.InlineNextActions nextActions = MacroExecutor.InlineNextActions.empty(); MacroExecutor.InlineNextActions nextActions = MacroExecutor.InlineNextActions.empty();
if (breakAction.interact && breakAction.runNextSteps) { if (breakAction.interact && breakAction.runNextSteps) {
nextActions = MacroExecutor.collectInlineNextActions(macro.actions, i); nextActions = MacroLifecycle.collectInlineNextActions(macro.actions, i);
breakAction.setNextActions(nextActions.actions()); breakAction.setNextActions(nextActions.actions());
} }
MacroBreak.runBreakAction(mc, breakAction); MacroBreak.runBreakAction(mc, breakAction);
@ -665,7 +665,7 @@ final class MacroRunLoop {
else if (action instanceof WaitForSlotChangeAction) { else if (action instanceof WaitForSlotChangeAction) {
WaitForSlotChangeAction wsca = (WaitForSlotChangeAction) action; WaitForSlotChangeAction wsca = (WaitForSlotChangeAction) action;
MacroExecutor.setCurrentStatus(wsca.getDisplayName()); MacroLifecycle.setCurrentStatus(wsca.getDisplayName());
try { try {
if (!MacroPrearm.waitForPrearmed(wsca, 0)) { if (!MacroPrearm.waitForPrearmed(wsca, 0)) {
CompletableFuture<Void> future = MacroConditionRegistry.waitForSlotChange(wsca); CompletableFuture<Void> future = MacroConditionRegistry.waitForSlotChange(wsca);
@ -674,7 +674,7 @@ final class MacroRunLoop {
} catch (CancellationException e) { } } catch (CancellationException e) { }
} }
else if (action instanceof WaitForWorldChangeAction world) { else if (action instanceof WaitForWorldChangeAction world) {
MacroExecutor.setCurrentStatus(world.getDisplayName()); MacroLifecycle.setCurrentStatus(world.getDisplayName());
try { try {
if (!MacroPrearm.waitForPrearmed(world, 0)) { if (!MacroPrearm.waitForPrearmed(world, 0)) {
CompletableFuture<Void> future = MacroConditionRegistry.waitForWorldChange(world); CompletableFuture<Void> future = MacroConditionRegistry.waitForWorldChange(world);
@ -683,7 +683,7 @@ final class MacroRunLoop {
} catch (CancellationException e) { } } catch (CancellationException e) { }
} }
else if (action instanceof WaitForPositionDeltaAction wpda) { else if (action instanceof WaitForPositionDeltaAction wpda) {
MacroExecutor.setCurrentStatus(wpda.getDisplayName()); MacroLifecycle.setCurrentStatus(wpda.getDisplayName());
try { try {
if (!MacroPrearm.waitForPrearmed(wpda, 0)) { if (!MacroPrearm.waitForPrearmed(wpda, 0)) {
CompletableFuture<Void> future = MacroConditionRegistry.waitForPositionDelta(wpda.distance, wpda.horizontalOnly); CompletableFuture<Void> future = MacroConditionRegistry.waitForPositionDelta(wpda.distance, wpda.horizontalOnly);
@ -692,7 +692,7 @@ final class MacroRunLoop {
} catch (CancellationException e) { } } catch (CancellationException e) { }
} }
else if (action instanceof WaitForTeleportAction teleport) { else if (action instanceof WaitForTeleportAction teleport) {
MacroExecutor.setCurrentStatus(teleport.getDisplayName()); MacroLifecycle.setCurrentStatus(teleport.getDisplayName());
try { try {
if (!MacroPrearm.waitForPrearmed(teleport, 0)) { if (!MacroPrearm.waitForPrearmed(teleport, 0)) {
CompletableFuture<?> future = MacroRace.raceConditionFuture(mc, teleport); CompletableFuture<?> future = MacroRace.raceConditionFuture(mc, teleport);
@ -701,7 +701,7 @@ final class MacroRunLoop {
} catch (CancellationException e) { } } catch (CancellationException e) { }
} }
else if (action instanceof WaitGamemodeChangeAction gm) { else if (action instanceof WaitGamemodeChangeAction gm) {
MacroExecutor.setCurrentStatus(gm.getDisplayName()); MacroLifecycle.setCurrentStatus(gm.getDisplayName());
try { try {
if (!MacroPrearm.waitForPrearmed(gm, gm.timeoutMs)) { if (!MacroPrearm.waitForPrearmed(gm, gm.timeoutMs)) {
CompletableFuture<Void> future = MacroConditionRegistry.waitForGamemodeChange(gm); CompletableFuture<Void> future = MacroConditionRegistry.waitForGamemodeChange(gm);
@ -710,7 +710,7 @@ final class MacroRunLoop {
} catch (CancellationException e) { } } catch (CancellationException e) { }
} }
else if (action instanceof WaitMovementAction wm) { else if (action instanceof WaitMovementAction wm) {
MacroExecutor.setCurrentStatus(wm.getDisplayName()); MacroLifecycle.setCurrentStatus(wm.getDisplayName());
try { try {
if (!MacroPrearm.waitForPrearmed(wm, 0)) { if (!MacroPrearm.waitForPrearmed(wm, 0)) {
CompletableFuture<?> future = MacroRace.raceConditionFuture(mc, wm.resolveSubAction()); CompletableFuture<?> future = MacroRace.raceConditionFuture(mc, wm.resolveSubAction());
@ -720,7 +720,7 @@ final class MacroRunLoop {
} }
else if (action instanceof WaitForLanStepAction) { else if (action instanceof WaitForLanStepAction) {
WaitForLanStepAction wla = (WaitForLanStepAction) action; WaitForLanStepAction wla = (WaitForLanStepAction) action;
MacroExecutor.setCurrentStatus(wla.getDisplayName()); MacroLifecycle.setCurrentStatus(wla.getDisplayName());
try { try {
if (!MacroPrearm.waitForPrearmed(wla, 0)) { if (!MacroPrearm.waitForPrearmed(wla, 0)) {
CompletableFuture<Void> future = MacroConditionRegistry.waitForLanStep(wla); CompletableFuture<Void> future = MacroConditionRegistry.waitForLanStep(wla);
@ -730,19 +730,19 @@ final class MacroRunLoop {
} }
else if (action instanceof WaitForMacroStepAction) { else if (action instanceof WaitForMacroStepAction) {
WaitForMacroStepAction wma = (WaitForMacroStepAction) action; WaitForMacroStepAction wma = (WaitForMacroStepAction) action;
MacroExecutor.setCurrentStatus(wma.getDisplayName()); MacroLifecycle.setCurrentStatus(wma.getDisplayName());
if (!MacroPrearm.waitForPrearmed(wma, wma.timeoutMs)) MacroRace.waitForMacroStep(wma); if (!MacroPrearm.waitForPrearmed(wma, wma.timeoutMs)) MacroRace.waitForMacroStep(wma);
} }
else if (action instanceof StopMacroAction) { else if (action instanceof StopMacroAction) {
MacroExecutor.setCurrentStatus("Stopping Macro"); MacroLifecycle.setCurrentStatus("Stopping Macro");
StopMacroAction stopAction = (StopMacroAction) action; StopMacroAction stopAction = (StopMacroAction) action;
if (stopAction.target != StopMacroAction.StopTarget.SELF) { if (stopAction.target != StopMacroAction.StopTarget.SELF) {
stopAction.execute(mc); stopAction.execute(mc);
break; break;
} }
MacroExecutor.broadcastStepProgress(runState, i + 1, macro.actions.size(), macro.name); MacroLifecycle.broadcastStepProgress(runState, i + 1, macro.actions.size(), macro.name);
MacroExecutor.stopCurrentRun(); MacroLifecycle.stopCurrentRun();
break; break;
} }
@ -755,13 +755,13 @@ final class MacroRunLoop {
MacroRender.preGeneratePackets(macro, i + 1, tsa.preGenCount); MacroRender.preGeneratePackets(macro, i + 1, tsa.preGenCount);
long targetTick = mc.level.getGameTime() + tsa.tickOffset; long targetTick = mc.level.getGameTime() + tsa.tickOffset;
MacroExecutor.setCurrentStatus("Tick Sync -> " + targetTick + " (" + preGenerated.size() + " pkts)"); MacroLifecycle.setCurrentStatus("Tick Sync -> " + targetTick + " (" + preGenerated.size() + " pkts)");
while (MacroExecutor.isCurrentRunActive() && mc.level.getGameTime() < targetTick) { while (MacroLifecycle.isCurrentRunActive() && mc.level.getGameTime() < targetTick) {
java.util.concurrent.locks.LockSupport.parkNanos(1_000_000L); java.util.concurrent.locks.LockSupport.parkNanos(1_000_000L);
} }
if (MacroExecutor.isCurrentRunActive()) { if (MacroLifecycle.isCurrentRunActive()) {
MacroRender.executePreGeneratedBurst(mc, preGenerated); MacroRender.executePreGeneratedBurst(mc, preGenerated);
i += MacroRender.countPreGeneratedActions(macro, i + 1, preGenerated.size()); i += MacroRender.countPreGeneratedActions(macro, i + 1, preGenerated.size());
AutismClientMessaging.sendPrefixed("Tick sync: " + preGenerated.size() + " pkts sent"); AutismClientMessaging.sendPrefixed("Tick sync: " + preGenerated.size() + " pkts sent");
@ -777,15 +777,15 @@ final class MacroRunLoop {
int baseRevision = mc.player.containerMenu.getStateId(); int baseRevision = mc.player.containerMenu.getStateId();
int targetRevision = baseRevision + rsa.revisionOffset; int targetRevision = baseRevision + rsa.revisionOffset;
MacroExecutor.setCurrentStatus("Rev Sync -> " + targetRevision + " (" + preGenerated.size() + " pkts)"); MacroLifecycle.setCurrentStatus("Rev Sync -> " + targetRevision + " (" + preGenerated.size() + " pkts)");
while (MacroExecutor.isCurrentRunActive()) { while (MacroLifecycle.isCurrentRunActive()) {
if (mc.player == null || mc.player.containerMenu == null) break; if (mc.player == null || mc.player.containerMenu == null) break;
if (mc.player.containerMenu.getStateId() >= targetRevision) break; if (mc.player.containerMenu.getStateId() >= targetRevision) break;
java.util.concurrent.locks.LockSupport.parkNanos(500_000L); java.util.concurrent.locks.LockSupport.parkNanos(500_000L);
} }
if (MacroExecutor.isCurrentRunActive() && mc.player != null && mc.player.containerMenu != null) { if (MacroLifecycle.isCurrentRunActive() && mc.player != null && mc.player.containerMenu != null) {
MacroRender.executePreGeneratedBurst(mc, preGenerated); MacroRender.executePreGeneratedBurst(mc, preGenerated);
i += MacroRender.countPreGeneratedActions(macro, i + 1, preGenerated.size()); i += MacroRender.countPreGeneratedActions(macro, i + 1, preGenerated.size());
AutismClientMessaging.sendPrefixed("Rev sync: " + preGenerated.size() + " pkts sent"); AutismClientMessaging.sendPrefixed("Rev sync: " + preGenerated.size() + " pkts sent");
@ -800,27 +800,27 @@ final class MacroRunLoop {
MacroRender.preGeneratePackets(macro, i + 1, stsa.preGenCount); MacroRender.preGeneratePackets(macro, i + 1, stsa.preGenCount);
int sampleWaitMs = 0; int sampleWaitMs = 0;
while (MacroExecutor.isCurrentRunActive() && !ServerTickTracker.isReady() && sampleWaitMs < stsa.maxWaitMs) { while (MacroLifecycle.isCurrentRunActive() && !ServerTickTracker.isReady() && sampleWaitMs < stsa.maxWaitMs) {
float progress = ServerTickTracker.getWarmupProgress(); float progress = ServerTickTracker.getWarmupProgress();
MacroExecutor.setCurrentStatus(String.format("ServerSync warmup %.0f%% (%d samples, %dms)", MacroLifecycle.setCurrentStatus(String.format("ServerSync warmup %.0f%% (%d samples, %dms)",
progress * 100, ServerTickTracker.getSampleCount(), ServerTickTracker.getTrackingTimeMs())); progress * 100, ServerTickTracker.getSampleCount(), ServerTickTracker.getTrackingTimeMs()));
Thread.sleep(50); Thread.sleep(50);
sampleWaitMs += 50; sampleWaitMs += 50;
} }
if (!MacroExecutor.isCurrentRunActive()) continue; if (!MacroLifecycle.isCurrentRunActive()) continue;
long optimalTime = ServerTickTracker.getOptimalSendTime(stsa.bufferMs, stsa.ignorePing); long optimalTime = ServerTickTracker.getOptimalSendTime(stsa.bufferMs, stsa.ignorePing);
long msUntil = (optimalTime - System.nanoTime()) / 1_000_000L; long msUntil = (optimalTime - System.nanoTime()) / 1_000_000L;
int ping = ServerTickTracker.getPingMs(); int ping = ServerTickTracker.getPingMs();
String pingStr = stsa.ignorePing ? " (no ping)" : " ping:" + ping + "ms"; String pingStr = stsa.ignorePing ? " (no ping)" : " ping:" + ping + "ms";
MacroExecutor.setCurrentStatus("ServerSync in " + Math.max(0, msUntil) + "ms" + pingStr + " (" + preGenerated.size() + " pkts)"); MacroLifecycle.setCurrentStatus("ServerSync in " + Math.max(0, msUntil) + "ms" + pingStr + " (" + preGenerated.size() + " pkts)");
long startWait = System.nanoTime(); long startWait = System.nanoTime();
long maxWaitNanos = stsa.maxWaitMs * 1_000_000L; long maxWaitNanos = stsa.maxWaitMs * 1_000_000L;
while (MacroExecutor.isCurrentRunActive()) { while (MacroLifecycle.isCurrentRunActive()) {
long now = System.nanoTime(); long now = System.nanoTime();
if ((now - startWait) >= maxWaitNanos) break; if ((now - startWait) >= maxWaitNanos) break;
if (now >= optimalTime) break; if (now >= optimalTime) break;
@ -833,7 +833,7 @@ final class MacroRunLoop {
} }
} }
if (MacroExecutor.isCurrentRunActive()) { if (MacroLifecycle.isCurrentRunActive()) {
MacroRender.executePreGeneratedBurst(mc, preGenerated); MacroRender.executePreGeneratedBurst(mc, preGenerated);
i += MacroRender.countPreGeneratedActions(macro, i + 1, preGenerated.size()); i += MacroRender.countPreGeneratedActions(macro, i + 1, preGenerated.size());
long actualDelay = (System.nanoTime() - optimalTime) / 1_000_000L; long actualDelay = (System.nanoTime() - optimalTime) / 1_000_000L;
@ -919,11 +919,11 @@ final class MacroRunLoop {
} }
else if (action instanceof autismclient.util.macro.StoreItemAction) { else if (action instanceof autismclient.util.macro.StoreItemAction) {
autismclient.util.macro.StoreItemAction sia = (autismclient.util.macro.StoreItemAction) action; autismclient.util.macro.StoreItemAction sia = (autismclient.util.macro.StoreItemAction) action;
MacroExecutor.setCurrentStatus((sia.mode == autismclient.util.macro.StoreItemAction.Mode.LOOT ? "Looting" : "Storing") MacroLifecycle.setCurrentStatus((sia.mode == autismclient.util.macro.StoreItemAction.Mode.LOOT ? "Looting" : "Storing")
+ (sia.persistent ? " \u221e" : "")); + (sia.persistent ? " \u221e" : ""));
if (sia.persistent) { if (sia.persistent) {
while (MacroExecutor.isCurrentRunActive()) { while (MacroLifecycle.isCurrentRunActive()) {
try { MacroActionRunner.runStoreItemAction(mc, sia); } try { MacroActionRunner.runStoreItemAction(mc, sia); }
catch (InterruptedException e) { Thread.currentThread().interrupt(); break; } catch (InterruptedException e) { Thread.currentThread().interrupt(); break; }
catch (Exception e) { AutismClientMessaging.sendPrefixed("Store error: " + e.getMessage()); } catch (Exception e) { AutismClientMessaging.sendPrefixed("Store error: " + e.getMessage()); }
@ -949,14 +949,14 @@ final class MacroRunLoop {
&& (xsa.transferMode == XCarryAction.TransferMode.CLICK && (xsa.transferMode == XCarryAction.TransferMode.CLICK
|| xsa.transferMode == XCarryAction.TransferMode.SAFE_CLICK)) { || xsa.transferMode == XCarryAction.TransferMode.SAFE_CLICK)) {
if (xsa.transferMode == XCarryAction.TransferMode.SAFE_CLICK) { if (xsa.transferMode == XCarryAction.TransferMode.SAFE_CLICK) {
MacroExecutor.setCurrentStatus("XCarry Safe"); MacroLifecycle.setCurrentStatus("XCarry Safe");
MacroXCarry.runXCarrySafeClickPutIn(mc, xsa); MacroXCarry.runXCarrySafeClickPutIn(mc, xsa);
} else { } else {
MacroExecutor.setCurrentStatus("XCarry Click"); MacroLifecycle.setCurrentStatus("XCarry Click");
MacroXCarry.runXCarryClickPutIn(mc, xsa); MacroXCarry.runXCarryClickPutIn(mc, xsa);
} }
} else { } else {
MacroExecutor.setCurrentStatus(switch (xsa.mode) { MacroLifecycle.setCurrentStatus(switch (xsa.mode) {
case PUT_IN -> "XCarry"; case PUT_IN -> "XCarry";
case TAKE_OUT -> "XCarry Out"; case TAKE_OUT -> "XCarry Out";
case DROP -> "XCarry Drop"; case DROP -> "XCarry Drop";
@ -973,7 +973,7 @@ final class MacroRunLoop {
else if (action instanceof InventoryAuditAction auditAction else if (action instanceof InventoryAuditAction auditAction
&& (auditAction.mode == InventoryAuditAction.Mode.DUPE && (auditAction.mode == InventoryAuditAction.Mode.DUPE
|| auditAction.mode == InventoryAuditAction.Mode.DUPE_SPAM)) { || auditAction.mode == InventoryAuditAction.Mode.DUPE_SPAM)) {
MacroExecutor.setCurrentStatus("Dupe: " + auditAction.dupeVector.name() + " " + auditAction.openMode.name()); MacroLifecycle.setCurrentStatus("Dupe: " + auditAction.dupeVector.name() + " " + auditAction.openMode.name());
try { try {
auditAction.executeDupe(mc); auditAction.executeDupe(mc);
} catch (InterruptedException ie) { } catch (InterruptedException ie) {
@ -989,11 +989,11 @@ final class MacroRunLoop {
MacroActionRunner.runPacketBurstAction(mc, burst); MacroActionRunner.runPacketBurstAction(mc, burst);
} }
else if (action instanceof BundleDupeV2Action bundleV2) { else if (action instanceof BundleDupeV2Action bundleV2) {
MacroExecutor.setCurrentStatus("Bundle Dupe V2"); MacroLifecycle.setCurrentStatus("Bundle Dupe V2");
bundleV2.execute(mc); bundleV2.execute(mc);
} }
else if (action instanceof RollbackAction rollback) { else if (action instanceof RollbackAction rollback) {
MacroExecutor.setCurrentStatus("Rollback"); MacroLifecycle.setCurrentStatus("Rollback");
try { try {
rollback.executeRollback(mc); rollback.executeRollback(mc);
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -1028,12 +1028,12 @@ final class MacroRunLoop {
postGuiFuture = null; postGuiFuture = null;
} else { } else {
if (placeTarget.hasIdentity() || placeTarget.hasSlot()) { if (placeTarget.hasIdentity() || placeTarget.hasSlot()) {
MacroExecutor.setCurrentStatus("Waiting for " + MacroWorldActions.describeItemTarget(placeTarget)); MacroLifecycle.setCurrentStatus("Waiting for " + MacroWorldActions.describeItemTarget(placeTarget));
try { try {
MacroWorldActions.waitForItemActionEntry(mc, placeTarget); MacroWorldActions.waitForItemActionEntry(mc, placeTarget);
} catch (java.util.concurrent.CancellationException e) { } } catch (java.util.concurrent.CancellationException e) { }
} }
if (MacroExecutor.isCurrentRunActive()) { if (MacroLifecycle.isCurrentRunActive()) {
final PlaceAction fPlace = place; final PlaceAction fPlace = place;
MacroClientThread.postOnClientThread(mc, () -> { MacroClientThread.postOnClientThread(mc, () -> {
if (PackHideState.isHardLocked()) return; if (PackHideState.isHardLocked()) return;
@ -1055,7 +1055,7 @@ final class MacroRunLoop {
java.util.concurrent.CountDownLatch latch = new java.util.concurrent.CountDownLatch(1); java.util.concurrent.CountDownLatch latch = new java.util.concurrent.CountDownLatch(1);
MacroExecutor.RunState scheduledRun = MacroExecutor.CURRENT_RUN.get(); MacroExecutor.RunState scheduledRun = MacroExecutor.CURRENT_RUN.get();
mc.execute(() -> MacroExecutor.withRunContext(scheduledRun, () -> { mc.execute(() -> MacroLifecycle.withRunContext(scheduledRun, () -> {
try { try {
if (PackHideState.isHardLocked()) return; if (PackHideState.isHardLocked()) return;
action.execute(mc); action.execute(mc);
@ -1078,18 +1078,18 @@ final class MacroRunLoop {
MacroPrearm.commitConditionOutput(action, mc); MacroPrearm.commitConditionOutput(action, mc);
if (postGuiFuture != null && MacroExecutor.isCurrentRunActive()) { if (postGuiFuture != null && MacroLifecycle.isCurrentRunActive()) {
try { try {
waitForCondition(postGuiFuture); waitForCondition(postGuiFuture);
} catch (java.util.concurrent.CancellationException e) { } } catch (java.util.concurrent.CancellationException e) { }
} }
if (MacroExecutor.isCurrentRunActive()) { if (MacroLifecycle.isCurrentRunActive()) {
MacroExecutor.markStepCompleted(i + 1); MacroLifecycle.markStepCompleted(i + 1);
MacroExecutor.broadcastStepProgress(runState, i + 1, macro.actions.size(), macro.name); MacroLifecycle.broadcastStepProgress(runState, i + 1, macro.actions.size(), macro.name);
} }
if (MacroExecutor.isCurrentRunActive() && !MacroActionRunner.isInstantInventoryAction(action)) { if (MacroLifecycle.isCurrentRunActive() && !MacroActionRunner.isInstantInventoryAction(action)) {
if (module != null && module.useInstantExecutionMode()) { if (module != null && module.useInstantExecutionMode()) {
int delayUs = module.getActionDelayUs(); int delayUs = module.getActionDelayUs();
if (delayUs > 0) { if (delayUs > 0) {
@ -1104,21 +1104,21 @@ final class MacroRunLoop {
} }
} finally { } finally {
MacroRaycastAim.release(); MacroRaycastAim.release();
MacroExecutor.releaseClientResources(heldResources); MacroLifecycle.releaseClientResources(heldResources);
} }
} }
if (macro.actions.isEmpty()) { if (macro.actions.isEmpty()) {
if (!runState.options.silentLifecycle()) AutismClientMessaging.sendPrefixed("\u00a7cMacro stopped: no actions left."); if (!runState.options.silentLifecycle()) AutismClientMessaging.sendPrefixed("\u00a7cMacro stopped: no actions left.");
MacroExecutor.stopCurrentRun(); MacroLifecycle.stopCurrentRun();
break; break;
} }
if (MacroExecutor.isCurrentRunActive()) { if (MacroLifecycle.isCurrentRunActive()) {
PacketGateManager.clearOwnerAndFlushConfigured(runState.id, mc == null ? null : mc.getConnection()); PacketGateManager.clearOwnerAndFlushConfigured(runState.id, mc == null ? null : mc.getConnection());
} }
if (macro.loop && loopCount < maxLoops - 1 && MacroExecutor.isCurrentRunActive()) { if (macro.loop && loopCount < maxLoops - 1 && MacroLifecycle.isCurrentRunActive()) {
if (module != null && module.useInstantExecutionMode()) { if (module != null && module.useInstantExecutionMode()) {
int delayUs = module.getActionDelayUs(); int delayUs = module.getActionDelayUs();
@ -1144,9 +1144,9 @@ final class MacroRunLoop {
loopCount++; loopCount++;
} }
MacroExecutor.awaitBackgroundTimedOverrides(runState); MacroLifecycle.awaitBackgroundTimedOverrides(runState);
if (MacroExecutor.isCurrentRunActive()) { if (MacroLifecycle.isCurrentRunActive()) {
if (!runState.options.silentLifecycle()) AutismClientMessaging.sendPrefixed("\u00a7aMacro finished: " + macro.name); if (!runState.options.silentLifecycle()) AutismClientMessaging.sendPrefixed("\u00a7aMacro finished: " + macro.name);
} }
@ -1158,11 +1158,11 @@ final class MacroRunLoop {
MacroRace.runFinallyActions(runState, mc); MacroRace.runFinallyActions(runState, mc);
} }
PacketGateManager.clearOwnerAndFlushConfigured(runState.id, mc == null ? null : mc.getConnection()); PacketGateManager.clearOwnerAndFlushConfigured(runState.id, mc == null ? null : mc.getConnection());
MacroExecutor.finishCurrentRun(); MacroLifecycle.finishCurrentRun();
MacroRender.cancelRotation(runState); MacroRender.cancelRotation(runState);
if (!MacroExecutor.isRunning.get()) MacroConditionRegistry.cancelAll(); if (!MacroExecutor.isRunning.get()) MacroConditionRegistry.cancelAll();
MacroExecutor.broadcastStepProgress(runState, -1, 0, ""); MacroLifecycle.broadcastStepProgress(runState, -1, 0, "");
} }
} }
@ -1170,12 +1170,12 @@ final class MacroRunLoop {
Thread t = Thread.currentThread(); Thread t = Thread.currentThread();
future.whenComplete((v, e) -> java.util.concurrent.locks.LockSupport.unpark(t)); future.whenComplete((v, e) -> java.util.concurrent.locks.LockSupport.unpark(t));
while (!future.isDone() && MacroExecutor.isCurrentRunActive()) { while (!future.isDone() && MacroLifecycle.isCurrentRunActive()) {
java.util.concurrent.locks.LockSupport.parkNanos(MacroExecutor.MACRO_WAIT_POLL_NANOS); java.util.concurrent.locks.LockSupport.parkNanos(MacroExecutor.MACRO_WAIT_POLL_NANOS);
if (Thread.interrupted()) break; if (Thread.interrupted()) break;
} }
if (!MacroExecutor.isCurrentRunActive()) { if (!MacroLifecycle.isCurrentRunActive()) {
future.cancel(true); future.cancel(true);
} }
} }
@ -1186,9 +1186,9 @@ final class MacroRunLoop {
autismclient.util.multi.PacketTeleportController.startMacro(action))); autismclient.util.multi.PacketTeleportController.startMacro(action)));
autismclient.util.multi.PacketTeleportController.MacroHandle handle = handleRef.get(); autismclient.util.multi.PacketTeleportController.MacroHandle handle = handleRef.get();
if (handle == null) return; if (handle == null) return;
MacroExecutor.setCurrentStatus("TP " + action.commandArguments()); MacroLifecycle.setCurrentStatus("TP " + action.commandArguments());
try { try {
while (MacroExecutor.isCurrentRunActive() && !handle.completion().isDone()) MacroExecutor.waitOneTick(); while (MacroLifecycle.isCurrentRunActive() && !handle.completion().isDone()) MacroExecutor.waitOneTick();
} finally { } finally {
if (!handle.completion().isDone()) { if (!handle.completion().isDone()) {
mc.execute(() -> autismclient.util.multi.PacketTeleportController.cancelMacro(handle, "macro stopped")); mc.execute(() -> autismclient.util.multi.PacketTeleportController.cancelMacro(handle, "macro stopped"));
@ -1207,7 +1207,7 @@ final class MacroRunLoop {
burst[0] = 0; burst[0] = 0;
CompletableFuture<Void> prev = MAIN_DRAIN_BARRIER.get(); CompletableFuture<Void> prev = MAIN_DRAIN_BARRIER.get();
if (prev != null && !prev.isDone()) waitForCondition(prev); if (prev != null && !prev.isDone()) waitForCondition(prev);
if (!MacroExecutor.isCurrentRunActive()) return; if (!MacroLifecycle.isCurrentRunActive()) return;
CompletableFuture<Void> next = new CompletableFuture<>(); CompletableFuture<Void> next = new CompletableFuture<>();
MAIN_DRAIN_BARRIER.set(next); MAIN_DRAIN_BARRIER.set(next);
try { try {
@ -1219,7 +1219,7 @@ final class MacroRunLoop {
public static void waitForPredicate(java.util.function.BooleanSupplier predicate, int timeoutMs) { public static void waitForPredicate(java.util.function.BooleanSupplier predicate, int timeoutMs) {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
while (MacroExecutor.isCurrentRunActive()) { while (MacroLifecycle.isCurrentRunActive()) {
try { try {
if (predicate.getAsBoolean()) return; if (predicate.getAsBoolean()) return;
} catch (Throwable ignored) { } } catch (Throwable ignored) { }

View file

@ -65,7 +65,7 @@ public final class MacroVariables {
} }
private static MacroVariableContext context() { private static MacroVariableContext context() {
MacroVariableContext active = MacroExecutor.currentVariableContext(); MacroVariableContext active = MacroLifecycle.currentVariableContext();
return active == null ? FALLBACK.get() : active; return active == null ? FALLBACK.get() : active;
} }
} }

View file

@ -26,7 +26,7 @@ final class MacroWorldActions {
ItemTarget target = action.resolvedItemTarget().resolveTemplate(mc); ItemTarget target = action.resolvedItemTarget().resolveTemplate(mc);
if (target == null) return; if (target == null) return;
if (action.waitForItem && target != null && (target.hasIdentity() || target.hasSlot())) { if (action.waitForItem && target != null && (target.hasIdentity() || target.hasSlot())) {
MacroExecutor.setCurrentStatus("Waiting for " + describeItemTarget(target)); MacroLifecycle.setCurrentStatus("Waiting for " + describeItemTarget(target));
waitForItemActionEntry(mc, target); waitForItemActionEntry(mc, target);
} }
@ -66,14 +66,14 @@ final class MacroWorldActions {
} }
private static void waitForItemInSpecificHandlerSlot(Minecraft mc, int slotId, ItemTarget target) throws InterruptedException { private static void waitForItemInSpecificHandlerSlot(Minecraft mc, int slotId, ItemTarget target) throws InterruptedException {
while (MacroExecutor.isCurrentRunActive()) { while (MacroLifecycle.isCurrentRunActive()) {
if (Boolean.TRUE.equals(MacroClientThread.callOnClientThread(mc, () -> handlerSlotMatchesItem(mc, slotId, target), Boolean.FALSE))) return; if (Boolean.TRUE.equals(MacroClientThread.callOnClientThread(mc, () -> handlerSlotMatchesItem(mc, slotId, target), Boolean.FALSE))) return;
MacroExecutor.waitOneTick(); MacroExecutor.waitOneTick();
} }
} }
private static void waitForAnyItemInSpecificHandlerSlot(Minecraft mc, int slotId) throws InterruptedException { private static void waitForAnyItemInSpecificHandlerSlot(Minecraft mc, int slotId) throws InterruptedException {
while (MacroExecutor.isCurrentRunActive()) { while (MacroLifecycle.isCurrentRunActive()) {
if (Boolean.TRUE.equals(MacroClientThread.callOnClientThread(mc, () -> handlerSlotHasAnyItem(mc, slotId), Boolean.FALSE))) return; if (Boolean.TRUE.equals(MacroClientThread.callOnClientThread(mc, () -> handlerSlotHasAnyItem(mc, slotId), Boolean.FALSE))) return;
MacroExecutor.waitOneTick(); MacroExecutor.waitOneTick();
} }
@ -110,7 +110,7 @@ final class MacroWorldActions {
} }
if (ia.useSlot && ia.targetSlot >= 0) { if (ia.useSlot && ia.targetSlot >= 0) {
MacroExecutor.setCurrentStatus("Waiting for slot " + ia.targetSlot); MacroLifecycle.setCurrentStatus("Waiting for slot " + ia.targetSlot);
waitForAnyItemInSpecificHandlerSlot(mc, ia.targetSlot); waitForAnyItemInSpecificHandlerSlot(mc, ia.targetSlot);
} }
} }
@ -122,19 +122,19 @@ final class MacroWorldActions {
int slot = resolvedTarget.hasSlot() ? resolvedTarget.slot : -1; int slot = resolvedTarget.hasSlot() ? resolvedTarget.slot : -1;
if (slot >= 0 && resolvedTarget.hasIdentity()) { if (slot >= 0 && resolvedTarget.hasIdentity()) {
MacroExecutor.setCurrentStatus("Waiting for " + itemLabel); MacroLifecycle.setCurrentStatus("Waiting for " + itemLabel);
waitForItemInSpecificHandlerSlot(mc, slot, resolvedTarget); waitForItemInSpecificHandlerSlot(mc, slot, resolvedTarget);
return; return;
} }
if (slot >= 0) { if (slot >= 0) {
MacroExecutor.setCurrentStatus("Waiting for slot " + slot); MacroLifecycle.setCurrentStatus("Waiting for slot " + slot);
waitForAnyItemInSpecificHandlerSlot(mc, slot); waitForAnyItemInSpecificHandlerSlot(mc, slot);
return; return;
} }
if (resolvedTarget.hasIdentity()) { if (resolvedTarget.hasIdentity()) {
MacroExecutor.setCurrentStatus("Waiting for item in GUI: " + itemLabel); MacroLifecycle.setCurrentStatus("Waiting for item in GUI: " + itemLabel);
CompletableFuture<Void> waitFuture = MacroConditionRegistry.waitForItemInHandler(resolvedTarget); CompletableFuture<Void> waitFuture = MacroConditionRegistry.waitForItemInHandler(resolvedTarget);
MacroRunLoop.waitForCondition(waitFuture); MacroRunLoop.waitForCondition(waitFuture);
} }
@ -174,7 +174,7 @@ final class MacroWorldActions {
public static void runCraftAction(Minecraft mc, CraftAction craftAction) throws InterruptedException { public static void runCraftAction(Minecraft mc, CraftAction craftAction) throws InterruptedException {
if (craftAction == null || !craftAction.hasEntries()) { if (craftAction == null || !craftAction.hasEntries()) {
MacroExecutor.setCurrentStatus("Crafting"); MacroLifecycle.setCurrentStatus("Crafting");
AutismClientMessaging.sendPrefixed("\u00a7cNo craft recipes selected."); AutismClientMessaging.sendPrefixed("\u00a7cNo craft recipes selected.");
return; return;
} }
@ -183,21 +183,21 @@ final class MacroWorldActions {
CraftAction.CraftEntry entry = craftAction.entries.get(index); CraftAction.CraftEntry entry = craftAction.entries.get(index);
if (entry == null || !entry.hasRecipe()) continue; if (entry == null || !entry.hasRecipe()) continue;
MacroExecutor.setCurrentStatus(entry.useMaxAmount MacroLifecycle.setCurrentStatus(entry.useMaxAmount
? "Crafting " + entry.resultName + " [Max] (" + (index + 1) + "/" + craftAction.entries.size() + ")" ? "Crafting " + entry.resultName + " [Max] (" + (index + 1) + "/" + craftAction.entries.size() + ")"
: "Crafting " + entry.resultName + " x" + Math.max(1, entry.amount) + " (" + (index + 1) + "/" + craftAction.entries.size() + ")"); : "Crafting " + entry.resultName + " x" + Math.max(1, entry.amount) + " (" + (index + 1) + "/" + craftAction.entries.size() + ")");
AutismCraftingHelper.CraftableRecipeOption option = AutismCraftingHelper.findCraftableRecipe(mc, entry.recipeKey); AutismCraftingHelper.CraftableRecipeOption option = AutismCraftingHelper.findCraftableRecipe(mc, entry.recipeKey);
if (option == null) option = AutismCraftingHelper.findCraftableRecipe(mc, entry.recipeId); if (option == null) option = AutismCraftingHelper.findCraftableRecipe(mc, entry.recipeId);
if (option == null) { if (option == null) {
MacroExecutor.setCurrentStatus("Recipe not found"); MacroLifecycle.setCurrentStatus("Recipe not found");
AutismClientMessaging.sendPrefixed("\u00a7cRecipe not found: " + (entry.resultName == null || entry.resultName.isBlank() ? "unknown" : entry.resultName)); AutismClientMessaging.sendPrefixed("\u00a7cRecipe not found: " + (entry.resultName == null || entry.resultName.isBlank() ? "unknown" : entry.resultName));
return; return;
} }
int desiredAmount = AutismCraftingHelper.getEffectiveRequestedOutput(option, entry.amount, entry.useMaxAmount); int desiredAmount = AutismCraftingHelper.getEffectiveRequestedOutput(option, entry.amount, entry.useMaxAmount);
if (desiredAmount <= 0) { if (desiredAmount <= 0) {
MacroExecutor.setCurrentStatus("No space or materials"); MacroLifecycle.setCurrentStatus("No space or materials");
AutismClientMessaging.sendPrefixed("\u00a7cNo space or materials for " + entry.resultName + "."); AutismClientMessaging.sendPrefixed("\u00a7cNo space or materials for " + entry.resultName + ".");
return; return;
} }
@ -209,12 +209,12 @@ final class MacroWorldActions {
desiredAmount desiredAmount
); );
MacroExecutor.setCurrentStatus(result.message); MacroLifecycle.setCurrentStatus(result.message);
if (!result.success) { if (!result.success) {
AutismClientMessaging.sendPrefixed("\u00a7c" + result.message); AutismClientMessaging.sendPrefixed("\u00a7c" + result.message);
return; return;
} }
if (MacroExecutor.isCurrentRunActive()) { if (MacroLifecycle.isCurrentRunActive()) {
CompletableFuture<Void> tickFuture = MacroConditionRegistry.waitForNextTick(); CompletableFuture<Void> tickFuture = MacroConditionRegistry.waitForNextTick();
MacroRunLoop.waitForCondition(tickFuture); MacroRunLoop.waitForCondition(tickFuture);
} }
@ -222,7 +222,7 @@ final class MacroWorldActions {
} }
public static void runGoToAction(Minecraft mc, GoToAction goToAction) throws InterruptedException { public static void runGoToAction(Minecraft mc, GoToAction goToAction) throws InterruptedException {
MacroExecutor.setCurrentStatus(String.format("Going to %.0f,%.0f,%.0f", goToAction.x, goToAction.y, goToAction.z)); MacroLifecycle.setCurrentStatus(String.format("Going to %.0f,%.0f,%.0f", goToAction.x, goToAction.y, goToAction.z));
if (!AutismCompatManager.isBaritoneAvailable()) { if (!AutismCompatManager.isBaritoneAvailable()) {
AutismClientMessaging.sendPrefixed("Baritone not installed; skipping goto action."); AutismClientMessaging.sendPrefixed("Baritone not installed; skipping goto action.");
@ -241,25 +241,25 @@ final class MacroWorldActions {
try { try {
if (!goToAction.waitForArrival) { if (!goToAction.waitForArrival) {
MacroExecutor.setCurrentStatus("Goto started"); MacroLifecycle.setCurrentStatus("Goto started");
return; return;
} }
long startMs = System.currentTimeMillis(); long startMs = System.currentTimeMillis();
boolean sawBaritoneActivity = false; boolean sawBaritoneActivity = false;
while (MacroExecutor.isCurrentRunActive()) { while (MacroLifecycle.isCurrentRunActive()) {
boolean goalActive = AutismCompatManager.isBaritoneGoalActive(); boolean goalActive = AutismCompatManager.isBaritoneGoalActive();
boolean baritoneBusy = AutismCompatManager.isBaritoneBusy(); boolean baritoneBusy = AutismCompatManager.isBaritoneBusy();
if (goalActive || baritoneBusy) sawBaritoneActivity = true; if (goalActive || baritoneBusy) sawBaritoneActivity = true;
if (sawBaritoneActivity && !goalActive && !baritoneBusy) { if (sawBaritoneActivity && !goalActive && !baritoneBusy) {
MacroExecutor.setCurrentStatus("Goto finished"); MacroLifecycle.setCurrentStatus("Goto finished");
return; return;
} }
if (!sawBaritoneActivity && System.currentTimeMillis() - startMs >= 1500 && !goalActive && !baritoneBusy) { if (!sawBaritoneActivity && System.currentTimeMillis() - startMs >= 1500 && !goalActive && !baritoneBusy) {
MacroExecutor.setCurrentStatus("Goto finished"); MacroLifecycle.setCurrentStatus("Goto finished");
return; return;
} }
@ -267,14 +267,14 @@ final class MacroWorldActions {
MacroRunLoop.waitForCondition(tickFuture); MacroRunLoop.waitForCondition(tickFuture);
} }
} finally { } finally {
if (!MacroExecutor.isCurrentRunActive()) requestOwnedBaritoneStop(run, mc); if (!MacroLifecycle.isCurrentRunActive()) requestOwnedBaritoneStop(run, mc);
else releaseBaritoneOwner(run); else releaseBaritoneOwner(run);
} }
} }
public static void runMineAction(Minecraft mc, MineAction mineAction) throws InterruptedException { public static void runMineAction(Minecraft mc, MineAction mineAction) throws InterruptedException {
String mineDesc = mineAction.targetBlocks.isEmpty() ? "none" : mineAction.targetBlocks.get(0); String mineDesc = mineAction.targetBlocks.isEmpty() ? "none" : mineAction.targetBlocks.get(0);
MacroExecutor.setCurrentStatus("Mining: " + mineDesc); MacroLifecycle.setCurrentStatus("Mining: " + mineDesc);
if (mineAction.targetBlocks.isEmpty()) return; if (mineAction.targetBlocks.isEmpty()) return;
if (!AutismCompatManager.isBaritoneAvailable()) { if (!AutismCompatManager.isBaritoneAvailable()) {
@ -305,7 +305,7 @@ final class MacroWorldActions {
long mineStartMs = System.currentTimeMillis(); long mineStartMs = System.currentTimeMillis();
boolean sawBaritoneActivity = false; boolean sawBaritoneActivity = false;
while (MacroExecutor.isCurrentRunActive()) { while (MacroLifecycle.isCurrentRunActive()) {
boolean mineActive = AutismCompatManager.isBaritoneMineActive(); boolean mineActive = AutismCompatManager.isBaritoneMineActive();
boolean baritoneBusy = AutismCompatManager.isBaritoneBusy(); boolean baritoneBusy = AutismCompatManager.isBaritoneBusy();
if (mineActive || baritoneBusy) sawBaritoneActivity = true; if (mineActive || baritoneBusy) sawBaritoneActivity = true;
@ -316,7 +316,7 @@ final class MacroWorldActions {
if (mineTracker != null) { if (mineTracker != null) {
mineTracker.poll(mc); mineTracker.poll(mc);
minedDelta = mineTracker.destroyedCount(); minedDelta = mineTracker.destroyedCount();
MacroExecutor.setCurrentStatus("Mining: " + mineDesc + " (" + minedDelta + "/" + mineAction.minedCountTarget + ")"); MacroLifecycle.setCurrentStatus("Mining: " + mineDesc + " (" + minedDelta + "/" + mineAction.minedCountTarget + ")");
if (minedDelta >= mineAction.minedCountTarget) { if (minedDelta >= mineAction.minedCountTarget) {
stopReason = "Mine target reached"; stopReason = "Mine target reached";
} }
@ -339,19 +339,19 @@ final class MacroWorldActions {
} }
if (stopReason != null) { if (stopReason != null) {
MacroExecutor.setCurrentStatus(stopReason); MacroLifecycle.setCurrentStatus(stopReason);
requestOwnedBaritoneStop(run, mc); requestOwnedBaritoneStop(run, mc);
waitForBaritoneIdle(); waitForBaritoneIdle();
return; return;
} }
if (sawBaritoneActivity && !mineActive && !baritoneBusy) { if (sawBaritoneActivity && !mineActive && !baritoneBusy) {
MacroExecutor.setCurrentStatus("Mine finished"); MacroLifecycle.setCurrentStatus("Mine finished");
return; return;
} }
if (!sawBaritoneActivity && System.currentTimeMillis() - mineStartMs >= 1500 && !mineActive && !baritoneBusy) { if (!sawBaritoneActivity && System.currentTimeMillis() - mineStartMs >= 1500 && !mineActive && !baritoneBusy) {
MacroExecutor.setCurrentStatus("Mine finished"); MacroLifecycle.setCurrentStatus("Mine finished");
return; return;
} }
@ -360,7 +360,7 @@ final class MacroWorldActions {
} }
} finally { } finally {
if (run != null && run.activeMineTracker == mineTracker) run.activeMineTracker = null; if (run != null && run.activeMineTracker == mineTracker) run.activeMineTracker = null;
if (!MacroExecutor.isCurrentRunActive()) requestOwnedBaritoneStop(run, mc); if (!MacroLifecycle.isCurrentRunActive()) requestOwnedBaritoneStop(run, mc);
else releaseBaritoneOwner(run); else releaseBaritoneOwner(run);
} }
} }
@ -407,7 +407,7 @@ final class MacroWorldActions {
private static void waitForBaritoneIdle() { private static void waitForBaritoneIdle() {
long waitStartMs = System.currentTimeMillis(); long waitStartMs = System.currentTimeMillis();
while (MacroExecutor.isCurrentRunActive() && AutismCompatManager.isBaritoneBusy() && System.currentTimeMillis() - waitStartMs < 3000L) { while (MacroLifecycle.isCurrentRunActive() && AutismCompatManager.isBaritoneBusy() && System.currentTimeMillis() - waitStartMs < 3000L) {
CompletableFuture<Void> tickFuture = MacroConditionRegistry.waitForNextTick(); CompletableFuture<Void> tickFuture = MacroConditionRegistry.waitForNextTick();
MacroRunLoop.waitForCondition(tickFuture); MacroRunLoop.waitForCondition(tickFuture);
} }
@ -566,7 +566,7 @@ final class MacroWorldActions {
int sent = 0; int sent = 0;
for (int i = 0; i < targets.size(); i++) { for (int i = 0; i < targets.size(); i++) {
if (!MacroExecutor.isCurrentRunActive()) break; if (!MacroLifecycle.isCurrentRunActive()) break;
String player = targets.get(i); String player = targets.get(i);
long perAmount = dividedAmounts != null ? dividedAmounts[i] : resolvedAmount; long perAmount = dividedAmounts != null ? dividedAmounts[i] : resolvedAmount;
@ -591,7 +591,7 @@ final class MacroWorldActions {
if (sent > 0 && payAction.delayEnabled && payAction.delayMs > 0) Thread.sleep(payAction.delayMs); if (sent > 0 && payAction.delayEnabled && payAction.delayMs > 0) Thread.sleep(payAction.delayMs);
MacroExecutor.setCurrentStatus("Paying " + player + " " + amountLabel + " (" + (sent + 1) + "/" + targets.size() + ")"); MacroLifecycle.setCurrentStatus("Paying " + player + " " + amountLabel + " (" + (sent + 1) + "/" + targets.size() + ")");
MacroClientThread.runOnClientThread(mc, () -> { MacroClientThread.runOnClientThread(mc, () -> {
try { try {
@ -609,8 +609,8 @@ final class MacroWorldActions {
sent++; sent++;
if (payAction.confirmMacro != null && !payAction.confirmMacro.isBlank()) { if (payAction.confirmMacro != null && !payAction.confirmMacro.isBlank()) {
MacroExecutor.setCurrentStatus("Confirming " + player); MacroLifecycle.setCurrentStatus("Confirming " + player);
PayAction.runConfirmMacro(payAction.confirmMacro, () -> !MacroExecutor.isCurrentRunActive()); PayAction.runConfirmMacro(payAction.confirmMacro, () -> !MacroLifecycle.isCurrentRunActive());
} }
} }
} }

View file

@ -20,7 +20,7 @@ final class MacroXCarry {
if (mc == null || mc.player == null || mc.gameMode == null) return; if (mc == null || mc.player == null || mc.gameMode == null) return;
if (xsa.requiresCursorStorage()) { if (xsa.requiresCursorStorage()) {
MacroExecutor.setCurrentStatus("XCarry Cursor"); MacroLifecycle.setCurrentStatus("XCarry Cursor");
MacroClientThread.runOnClientThread(mc, () -> xsa.execute(mc)); MacroClientThread.runOnClientThread(mc, () -> xsa.execute(mc));
return; return;
} }
@ -53,8 +53,8 @@ final class MacroXCarry {
if (usingContainer.get()) { if (usingContainer.get()) {
for (int slotId : containerSlotIdsRef.get()) { for (int slotId : containerSlotIdsRef.get()) {
if (!MacroExecutor.isCurrentRunActive()) return; if (!MacroLifecycle.isCurrentRunActive()) return;
MacroExecutor.setCurrentStatus("XCarry Click: collect"); MacroLifecycle.setCurrentStatus("XCarry Click: collect");
MacroClientThread.runOnClientThread(mc, () -> { MacroClientThread.runOnClientThread(mc, () -> {
if (mc.player == null || mc.gameMode == null) return; if (mc.player == null || mc.gameMode == null) return;
net.minecraft.world.inventory.AbstractContainerMenu handler = containerHandlerRef.get(); net.minecraft.world.inventory.AbstractContainerMenu handler = containerHandlerRef.get();
@ -85,14 +85,14 @@ final class MacroXCarry {
MacroClientThread.runOnClientThread(mc, xsa::preparePutInStorageGuard); MacroClientThread.runOnClientThread(mc, xsa::preparePutInStorageGuard);
int xCarryAttempts = 0; int xCarryAttempts = 0;
while (MacroExecutor.isCurrentRunActive() && xCarryAttempts++ < 512) { while (MacroLifecycle.isCurrentRunActive() && xCarryAttempts++ < 512) {
XCarryAction.PutInMove move = MacroClientThread.callOnClientThread(mc, () -> { XCarryAction.PutInMove move = MacroClientThread.callOnClientThread(mc, () -> {
if (mc.player == null) return null; if (mc.player == null) return null;
return xsa.findNextPutInMove(mc.player.inventoryMenu); return xsa.findNextPutInMove(mc.player.inventoryMenu);
}, null); }, null);
if (move == null) break; if (move == null) break;
MacroExecutor.setCurrentStatus("XCarry Click -> " + move.targetSlotId + " x" + move.count); MacroLifecycle.setCurrentStatus("XCarry Click -> " + move.targetSlotId + " x" + move.count);
int targetBefore = MacroClientThread.callOnClientThread(mc, () -> { int targetBefore = MacroClientThread.callOnClientThread(mc, () -> {
if (mc.player == null) return 0; if (mc.player == null) return 0;
net.minecraft.world.inventory.InventoryMenu handler = mc.player.inventoryMenu; net.minecraft.world.inventory.InventoryMenu handler = mc.player.inventoryMenu;
@ -158,7 +158,7 @@ final class MacroXCarry {
if (mc == null || mc.player == null || mc.gameMode == null) return; if (mc == null || mc.player == null || mc.gameMode == null) return;
if (xsa.requiresCursorStorage()) { if (xsa.requiresCursorStorage()) {
MacroExecutor.setCurrentStatus("XCarry Safe: Cursor"); MacroLifecycle.setCurrentStatus("XCarry Safe: Cursor");
MacroClientThread.runOnClientThread(mc, () -> xsa.execute(mc)); MacroClientThread.runOnClientThread(mc, () -> xsa.execute(mc));
return; return;
} }
@ -191,8 +191,8 @@ final class MacroXCarry {
if (usingContainer.get()) { if (usingContainer.get()) {
for (int slotId : containerSlotIdsRef.get()) { for (int slotId : containerSlotIdsRef.get()) {
if (!MacroExecutor.isCurrentRunActive()) return; if (!MacroLifecycle.isCurrentRunActive()) return;
MacroExecutor.setCurrentStatus("XCarry Safe: collect"); MacroLifecycle.setCurrentStatus("XCarry Safe: collect");
sendContainerClickThenTick(mc, containerHandlerRef.get(), slotId, 0, ContainerInput.QUICK_MOVE); sendContainerClickThenTick(mc, containerHandlerRef.get(), slotId, 0, ContainerInput.QUICK_MOVE);
} }
@ -218,14 +218,14 @@ final class MacroXCarry {
boolean delayAfterPickup = xsa.safeClickDelayAfterPickup; boolean delayAfterPickup = xsa.safeClickDelayAfterPickup;
boolean delayBeforeReturn = xsa.safeClickDelayBeforeReturn; boolean delayBeforeReturn = xsa.safeClickDelayBeforeReturn;
int attempts = 0; int attempts = 0;
while (MacroExecutor.isCurrentRunActive() && attempts++ < 512) { while (MacroLifecycle.isCurrentRunActive() && attempts++ < 512) {
List<XCarryAction.PutInMove> group = MacroClientThread.callOnClientThread(mc, () -> nextXCarrySafeGroup(mc, xsa), List.of()); List<XCarryAction.PutInMove> group = MacroClientThread.callOnClientThread(mc, () -> nextXCarrySafeGroup(mc, xsa), List.of());
if (group.isEmpty()) break; if (group.isEmpty()) break;
XCarryAction.PutInMove first = group.get(0); XCarryAction.PutInMove first = group.get(0);
int total = 0; int total = 0;
for (XCarryAction.PutInMove move : group) total += Math.max(0, move.count()); for (XCarryAction.PutInMove move : group) total += Math.max(0, move.count());
MacroExecutor.setCurrentStatus("XCarry Safe -> " + group.size() + " slots x" + total); MacroLifecycle.setCurrentStatus("XCarry Safe -> " + group.size() + " slots x" + total);
if (!executeXCarrySafeGroup(mc, group, safeDelayTicks, delayAfterPickup, delayBeforeReturn)) { if (!executeXCarrySafeGroup(mc, group, safeDelayTicks, delayAfterPickup, delayBeforeReturn)) {
rollbackXCarryCursorSafe(mc, first.sourceSlotId(), safeDelayTicks, delayBeforeReturn); rollbackXCarryCursorSafe(mc, first.sourceSlotId(), safeDelayTicks, delayBeforeReturn);
@ -321,7 +321,7 @@ final class MacroXCarry {
SafeGroupSnapshot expected = snapshot; SafeGroupSnapshot expected = snapshot;
if (quickCraftPlan.valid) { if (quickCraftPlan.valid) {
MacroExecutor.setCurrentStatus("XCarry Safe drag -> " + group.size() + " slots x" + quickCraftPlan.placeCount); MacroLifecycle.setCurrentStatus("XCarry Safe drag -> " + group.size() + " slots x" + quickCraftPlan.placeCount);
int start = net.minecraft.world.inventory.AbstractContainerMenu.getQuickcraftMask(0, quickCraftPlan.quickCraftType); int start = net.minecraft.world.inventory.AbstractContainerMenu.getQuickcraftMask(0, quickCraftPlan.quickCraftType);
int add = net.minecraft.world.inventory.AbstractContainerMenu.getQuickcraftMask(1, quickCraftPlan.quickCraftType); int add = net.minecraft.world.inventory.AbstractContainerMenu.getQuickcraftMask(1, quickCraftPlan.quickCraftType);
int end = net.minecraft.world.inventory.AbstractContainerMenu.getQuickcraftMask(2, quickCraftPlan.quickCraftType); int end = net.minecraft.world.inventory.AbstractContainerMenu.getQuickcraftMask(2, quickCraftPlan.quickCraftType);
@ -432,7 +432,7 @@ final class MacroXCarry {
private static boolean placeXCarrySafeDirectCount(Minecraft mc, int targetSlotId, int count, int delayTicks) throws InterruptedException { private static boolean placeXCarrySafeDirectCount(Minecraft mc, int targetSlotId, int count, int delayTicks) throws InterruptedException {
if (mc == null || count <= 0) return false; if (mc == null || count <= 0) return false;
int remaining = count; int remaining = count;
while (remaining > 0 && MacroExecutor.isCurrentRunActive()) { while (remaining > 0 && MacroLifecycle.isCurrentRunActive()) {
int carriedCount = MacroClientThread.callOnClientThread(mc, () -> { int carriedCount = MacroClientThread.callOnClientThread(mc, () -> {
InventoryMenu handler = mc.player == null ? null : mc.player.inventoryMenu; InventoryMenu handler = mc.player == null ? null : mc.player.inventoryMenu;
return handler == null ? 0 : handler.getCarried().getCount(); return handler == null ? 0 : handler.getCarried().getCount();
@ -627,7 +627,7 @@ final class MacroXCarry {
private static void waitXCarrySafeDelayTicks(int delayTicks) { private static void waitXCarrySafeDelayTicks(int delayTicks) {
int ticks = XCarryAction.clampSafeClickDelayTicks(delayTicks); int ticks = XCarryAction.clampSafeClickDelayTicks(delayTicks);
for (int i = 0; i < ticks && MacroExecutor.isCurrentRunActive(); i++) { for (int i = 0; i < ticks && MacroLifecycle.isCurrentRunActive(); i++) {
MacroExecutor.waitOneTick(); MacroExecutor.waitOneTick();
} }
} }
@ -670,7 +670,7 @@ final class MacroXCarry {
private static boolean waitForXCarrySafeLocal(Minecraft mc, int ticks, java.util.function.BooleanSupplier accepted) throws InterruptedException { private static boolean waitForXCarrySafeLocal(Minecraft mc, int ticks, java.util.function.BooleanSupplier accepted) throws InterruptedException {
int maxTicks = Math.max(1, ticks); int maxTicks = Math.max(1, ticks);
for (int i = 0; i < maxTicks && MacroExecutor.isCurrentRunActive(); i++) { for (int i = 0; i < maxTicks && MacroLifecycle.isCurrentRunActive(); i++) {
if (Boolean.TRUE.equals(MacroClientThread.callOnClientThread(mc, () -> accepted != null && accepted.getAsBoolean(), Boolean.FALSE))) return true; if (Boolean.TRUE.equals(MacroClientThread.callOnClientThread(mc, () -> accepted != null && accepted.getAsBoolean(), Boolean.FALSE))) return true;
MacroExecutor.waitOneTick(); MacroExecutor.waitOneTick();
} }
@ -680,8 +680,8 @@ final class MacroXCarry {
private static void waitForXCarrySafeSettle(Minecraft mc, long startRevision, int minTicks, long maxMs) throws InterruptedException { private static void waitForXCarrySafeSettle(Minecraft mc, long startRevision, int minTicks, long maxMs) throws InterruptedException {
long deadline = System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(Math.max(50L, maxMs)); long deadline = System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(Math.max(50L, maxMs));
int ticks = Math.max(1, minTicks); int ticks = Math.max(1, minTicks);
for (int i = 0; i < ticks && MacroExecutor.isCurrentRunActive(); i++) MacroExecutor.waitOneTick(); for (int i = 0; i < ticks && MacroLifecycle.isCurrentRunActive(); i++) MacroExecutor.waitOneTick();
while (MacroExecutor.isCurrentRunActive() && System.nanoTime() < deadline) { while (MacroLifecycle.isCurrentRunActive() && System.nanoTime() < deadline) {
long revision = MacroConditionRegistry.inventorySyncRevision(); long revision = MacroConditionRegistry.inventorySyncRevision();
if (revision != startRevision) { if (revision != startRevision) {
MacroExecutor.waitOneTick(); MacroExecutor.waitOneTick();
@ -848,7 +848,7 @@ final class MacroXCarry {
private static boolean waitForXCarryCondition(Minecraft mc, long timeoutMs, java.util.function.Supplier<Boolean> condition) throws InterruptedException { private static boolean waitForXCarryCondition(Minecraft mc, long timeoutMs, java.util.function.Supplier<Boolean> condition) throws InterruptedException {
long deadline = System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(timeoutMs); long deadline = System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(timeoutMs);
while (MacroExecutor.isCurrentRunActive()) { while (MacroLifecycle.isCurrentRunActive()) {
if (Boolean.TRUE.equals(MacroClientThread.callOnClientThread(mc, condition, Boolean.FALSE))) { if (Boolean.TRUE.equals(MacroClientThread.callOnClientThread(mc, condition, Boolean.FALSE))) {
return true; return true;
} }