mirror of
https://github.com/AutismDevelopment/Autism-Client.git
synced 2026-10-28 17:29:46 +00:00
Refactor: extract MacroActionRunner from MacroExecutor (upstream #4)
Move 28 single-action execution methods plus ApiExecutionContext verbatim into MacroActionRunner: raycast/target interaction, GUI gating, client-thread dispatch, paced item/use/click/store/container actions and packet-burst helpers. Shared members referenced as MacroExecutor.xxx (mechanical qualification only); self-calls to the context interface methods left bare. All bodies verified identical against HEAD modulo that qualification.
This commit is contained in:
parent
57ca197042
commit
4c036f9c54
3 changed files with 582 additions and 564 deletions
521
src/main/java/autismclient/util/macro/MacroActionRunner.java
Normal file
521
src/main/java/autismclient/util/macro/MacroActionRunner.java
Normal file
|
|
@ -0,0 +1,521 @@
|
||||||
|
package autismclient.util.macro;
|
||||||
|
|
||||||
|
import autismclient.modules.PackHideState;
|
||||||
|
import autismclient.util.AutismClientMessaging;
|
||||||
|
import autismclient.util.AutismGuiActions;
|
||||||
|
import autismclient.util.AutismInventoryClickHelper;
|
||||||
|
import autismclient.util.AutismSharedState;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
final class MacroActionRunner {
|
||||||
|
private MacroActionRunner() {
|
||||||
|
}
|
||||||
|
public static void beginRaycastAim(Minecraft mc, MacroAction action) {
|
||||||
|
if (!(action instanceof RaycastAim aim) || !aim.isRaycast()) return;
|
||||||
|
autismclient.util.AutismRotationUtil.Rotation rotation;
|
||||||
|
try {
|
||||||
|
rotation = MacroExecutor.callOnClientThread(mc, () -> MacroRaycastAim.aimFor(mc, aim.raycastTarget(mc)), null);
|
||||||
|
} catch (InterruptedException interrupted) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (rotation == null) return;
|
||||||
|
MacroRaycastAim.hold(rotation);
|
||||||
|
MacroExecutor.waitOneTick();
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean dynamicTextInputsAvailable(MacroAction action, Minecraft mc) {
|
||||||
|
if (action instanceof WaitForChatAction chat && chat.effectiveMatchMode() == MacroCapturePattern.Mode.MATCH) {
|
||||||
|
return MacroVariables.resolve(chat.pattern, mc).success();
|
||||||
|
}
|
||||||
|
if (action instanceof WaitForGuiAction gui && gui.matchMode == MacroCapturePattern.Mode.MATCH) {
|
||||||
|
return MacroVariables.resolve(gui.guiTitle, mc).success();
|
||||||
|
}
|
||||||
|
if (action instanceof WaitGuiTypeAction gui && gui.matchMode == MacroCapturePattern.Mode.MATCH) {
|
||||||
|
return MacroVariables.resolve(gui.title, mc).success();
|
||||||
|
}
|
||||||
|
if (action instanceof WaitInventoryPredicateAction inventory) {
|
||||||
|
return MacroVariables.resolve(inventory.itemName, mc).success();
|
||||||
|
}
|
||||||
|
if (action instanceof WaitDurabilityAction durability && durability.targetMode == WaitDurabilityAction.TargetMode.ITEM) {
|
||||||
|
return MacroVariables.resolve(durability.itemName, mc).success();
|
||||||
|
}
|
||||||
|
if (action instanceof WaitEntityTargetAction entity) {
|
||||||
|
return MacroVariables.resolve(entity.entityId, mc).success();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static java.util.List<net.minecraft.network.protocol.Packet<?>> preGeneratePacketsForRepeat(
|
||||||
|
int count, Minecraft mc) {
|
||||||
|
MacroExecutor.RepeatPacketContext context = MacroExecutor.REPEAT_PACKET_CONTEXT.get();
|
||||||
|
if (context == null || context.macro() == null) return new java.util.ArrayList<>();
|
||||||
|
return MacroExecutor.preGeneratePackets(context.macro(), context.startIdx(), count, context.endIdx());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isTargetWaitInteractionAction(MacroAction action) {
|
||||||
|
return action instanceof OpenContainerAction || action instanceof InteractEntityAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CompletableFuture<Void> runTargetWaitInteractionAction(Minecraft mc, MacroAction action) throws InterruptedException {
|
||||||
|
boolean waitForTarget = switch (action) {
|
||||||
|
case OpenContainerAction open -> open.waitForTarget;
|
||||||
|
case InteractEntityAction interact -> interact.waitForTarget;
|
||||||
|
default -> false;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!waitForTarget) {
|
||||||
|
CompletableFuture<Void> postGuiFuture = createPostGuiFuture(mc, action);
|
||||||
|
runTargetInteractionAttempt(mc, action);
|
||||||
|
return postGuiFuture;
|
||||||
|
}
|
||||||
|
|
||||||
|
MacroExecutor.setCurrentStatus("Waiting target: " + action.getDisplayName());
|
||||||
|
while (MacroExecutor.isCurrentRunActive()) {
|
||||||
|
if (!canRunTargetInteractionNow(mc, action)) {
|
||||||
|
java.util.concurrent.locks.LockSupport.parkNanos(MacroExecutor.MACRO_WAIT_POLL_NANOS);
|
||||||
|
if (Thread.interrupted()) throw new InterruptedException();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CompletableFuture<Void> postGuiFuture = createPostGuiFuture(mc, action);
|
||||||
|
if (runTargetInteractionAttempt(mc, action)) {
|
||||||
|
return postGuiFuture;
|
||||||
|
}
|
||||||
|
if (postGuiFuture != null) postGuiFuture.cancel(true);
|
||||||
|
java.util.concurrent.locks.LockSupport.parkNanos(MacroExecutor.MACRO_WAIT_POLL_NANOS);
|
||||||
|
if (Thread.interrupted()) throw new InterruptedException();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean canRunTargetInteractionNow(Minecraft mc, MacroAction action) throws InterruptedException {
|
||||||
|
return MacroExecutor.callOnClientThread(mc, () -> {
|
||||||
|
if (action instanceof OpenContainerAction open) return open.canExecuteNow(mc);
|
||||||
|
if (action instanceof InteractEntityAction interact) return interact.canExecuteNow(mc);
|
||||||
|
return true;
|
||||||
|
}, Boolean.FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean runTargetInteractionAttempt(Minecraft mc, MacroAction action) throws InterruptedException {
|
||||||
|
return MacroExecutor.callOnClientThread(mc, () -> {
|
||||||
|
try {
|
||||||
|
if (action instanceof OpenContainerAction open) return open.tryExecute(mc);
|
||||||
|
if (action instanceof InteractEntityAction interact) return interact.tryExecute(mc);
|
||||||
|
action.execute(mc);
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
AutismClientMessaging.sendPrefixed("\u00a7cError in " + action.getDisplayName() + ": " + e.getMessage());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}, Boolean.FALSE, usesTickAlignedDispatch(action));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CompletableFuture<Void> createPostGuiFuture(Minecraft mc, MacroAction action) {
|
||||||
|
if (Boolean.TRUE.equals(MacroExecutor.SUPPRESS_POST_GUI_AFTER.get())) return null;
|
||||||
|
if (!(action instanceof WaitsForGui wfg) || !wfg.isWaitForGuiAfter()) return null;
|
||||||
|
return createWaitsForGuiFuture(mc, wfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CompletableFuture<Void> createWaitsForGuiFuture(Minecraft mc, WaitsForGui wfg) {
|
||||||
|
MacroTemplate.Resolution guiName = MacroVariables.resolve(wfg.getWaitGuiName(), mc);
|
||||||
|
if (!guiName.success()) return CompletableFuture.completedFuture(null);
|
||||||
|
return wfg.isWaitForGuiChange()
|
||||||
|
? MacroConditionRegistry.waitForGuiChange(mc.gui.screen())
|
||||||
|
: MacroConditionRegistry.waitForGui(guiName.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean waitForGuiBeforeAction(Minecraft mc, MacroAction action) throws InterruptedException {
|
||||||
|
if (!(action instanceof WaitsForGui wfg)) return true;
|
||||||
|
return waitForGuiBeforeAction(mc, wfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean waitForGuiBeforeAction(Minecraft mc, WaitsForGui action) throws InterruptedException {
|
||||||
|
if (mc == null || action == null || !action.isWaitForGuiBefore()) return true;
|
||||||
|
MacroTemplate.Resolution guiName = MacroVariables.resolve(action.getWaitGuiName(), mc);
|
||||||
|
if (!guiName.success()) return false;
|
||||||
|
if (isWaitGuiPresent(mc, guiName.value())) {
|
||||||
|
waitForCurrentGuiReady(mc);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
CompletableFuture<Void> future = MacroConditionRegistry.waitForGui(guiName.value());
|
||||||
|
MacroExecutor.waitForCondition(future);
|
||||||
|
waitForCurrentGuiReady(mc);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isWaitGuiPresent(Minecraft mc, String guiName) {
|
||||||
|
if (mc == null || mc.gui.screen() == null) return false;
|
||||||
|
if (MacroGuiMatcher.isOwnScreen(mc.gui.screen())) return false;
|
||||||
|
String expected = guiName == null ? "" : guiName.trim();
|
||||||
|
if (expected.isEmpty()) return true;
|
||||||
|
String actual = mc.gui.screen().getTitle() == null ? "" : mc.gui.screen().getTitle().getString();
|
||||||
|
return matchesWaitGuiTitle(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean matchesWaitGuiTitle(String expected, String actual) {
|
||||||
|
if (expected == null || expected.isBlank() || actual == null || actual.isBlank()) return false;
|
||||||
|
String expectedLower = expected.toLowerCase(Locale.ROOT);
|
||||||
|
String actualLower = actual.toLowerCase(Locale.ROOT);
|
||||||
|
if (expectedLower.equals(actualLower) || actualLower.contains(expectedLower)) return true;
|
||||||
|
for (String word : expectedLower.split("\\s+")) {
|
||||||
|
if (!word.isBlank() && !actualLower.contains(word)) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void waitForCurrentGuiReady(Minecraft mc) throws InterruptedException {
|
||||||
|
|
||||||
|
long deadline = System.nanoTime() + 500_000_000L;
|
||||||
|
while (MacroExecutor.isCurrentRunActive()) {
|
||||||
|
Boolean ready = MacroExecutor.callOnClientThread(mc, () -> {
|
||||||
|
if (mc.player == null || mc.gui.screen() == null) return false;
|
||||||
|
if (mc.player.containerMenu != null && mc.player.containerMenu != mc.player.inventoryMenu) {
|
||||||
|
return mc.player.containerMenu.getStateId() > 0;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}, Boolean.FALSE);
|
||||||
|
if (Boolean.TRUE.equals(ready)) return;
|
||||||
|
if (System.nanoTime() >= deadline) return;
|
||||||
|
java.util.concurrent.locks.LockSupport.parkNanos(MacroExecutor.MACRO_WAIT_POLL_NANOS);
|
||||||
|
if (Thread.interrupted()) return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void runMacroActionOnClientThread(Minecraft mc, MacroAction action, String label) throws InterruptedException {
|
||||||
|
Runnable body = () -> {
|
||||||
|
try {
|
||||||
|
action.execute(mc);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
recordAddonActionError(action, "Action threw " + t.getClass().getSimpleName());
|
||||||
|
AutismClientMessaging.sendPrefixed("\u00a7cError in " + label + ": "
|
||||||
|
+ (t.getMessage() == null ? t.getClass().getSimpleName() : t.getMessage()));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (usesTickAlignedDispatch(action)) MacroExecutor.runOnClientTick(mc, body);
|
||||||
|
else MacroExecutor.runOnClientThread(mc, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean usesTickAlignedDispatch(MacroAction action) {
|
||||||
|
return action instanceof PacketOrdered ordered && ordered.isTickAligned();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void runItemActionPaced(Minecraft mc, ItemAction ia) throws InterruptedException {
|
||||||
|
MacroExecutor.setCurrentStatus(ia.getDisplayName());
|
||||||
|
java.util.List<Runnable> plan = MacroExecutor.callOnClientThread(mc, () -> ia.buildClickPlan(mc), java.util.Collections.<Runnable>emptyList());
|
||||||
|
if (plan == null || plan.isEmpty()) return;
|
||||||
|
long delayMs = Math.max(0, ia.clickDelayMs);
|
||||||
|
MacroExecutor.RunState scheduledRun = MacroExecutor.CURRENT_RUN.get();
|
||||||
|
boolean first = true;
|
||||||
|
for (Runnable op : plan) {
|
||||||
|
if (!MacroExecutor.isCurrentRunActive()) break;
|
||||||
|
if (!first && delayMs > 0) Thread.sleep(delayMs);
|
||||||
|
first = false;
|
||||||
|
mc.execute(() -> MacroExecutor.withRunContext(scheduledRun, () -> {
|
||||||
|
if (PackHideState.isHardLocked()) return;
|
||||||
|
try {
|
||||||
|
op.run();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
AutismClientMessaging.sendPrefixed("\u00a7cError in ItemAction: "
|
||||||
|
+ (t.getMessage() == null ? t.getClass().getSimpleName() : t.getMessage()));
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void runContextMacroAction(autismclient.api.macro.ContextMacroAction action) {
|
||||||
|
if (PackHideState.isHardLocked()) return;
|
||||||
|
if (action == null) return;
|
||||||
|
try {
|
||||||
|
action.run(new ApiExecutionContext(MacroExecutor.CURRENT_RUN.get()));
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
recordAddonActionError(action, "Context action threw " + t.getClass().getSimpleName());
|
||||||
|
AutismClientMessaging.sendPrefixed("\u00a7cAddon action error: "
|
||||||
|
+ (t.getMessage() == null ? t.getClass().getSimpleName() : t.getMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void recordAddonActionError(MacroAction action, String detail) {
|
||||||
|
if (action == null) return;
|
||||||
|
String owner = autismclient.api.macro.MacroActionRegistry.ownerOf(action.getTypeId());
|
||||||
|
if (owner != null && !owner.isBlank()) autismclient.addons.AddonManager.recordRuntimeError(owner, detail);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class ApiExecutionContext implements autismclient.api.macro.MacroExecutionContext {
|
||||||
|
private final MacroExecutor.RunState run;
|
||||||
|
|
||||||
|
private ApiExecutionContext(MacroExecutor.RunState run) {
|
||||||
|
this.run = run;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public Minecraft mc() { return Minecraft.getInstance(); }
|
||||||
|
|
||||||
|
@Override public void runOnClientThread(Runnable r) {
|
||||||
|
if (r == null) return;
|
||||||
|
|
||||||
|
Runnable safe = () -> MacroExecutor.withRunContext(run, () -> {
|
||||||
|
try { r.run(); }
|
||||||
|
catch (Throwable t) { AutismClientMessaging.sendPrefixed("\u00a7cAddon action (client task) error: " + (t.getMessage() == null ? t.getClass().getSimpleName() : t.getMessage())); }
|
||||||
|
});
|
||||||
|
try { MacroExecutor.runOnClientThread(Minecraft.getInstance(), safe); }
|
||||||
|
catch (InterruptedException e) { Thread.currentThread().interrupt(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public <T> T callOnClientThread(java.util.function.Supplier<T> s) {
|
||||||
|
if (s == null) return null;
|
||||||
|
java.util.function.Supplier<T> safe = () -> {
|
||||||
|
AtomicReference<T> value = new AtomicReference<>();
|
||||||
|
MacroExecutor.withRunContext(run, () -> {
|
||||||
|
try { value.set(s.get()); }
|
||||||
|
catch (Throwable t) { AutismClientMessaging.sendPrefixed("\u00a7cAddon action (client task) error: " + (t.getMessage() == null ? t.getClass().getSimpleName() : t.getMessage())); }
|
||||||
|
});
|
||||||
|
return value.get();
|
||||||
|
};
|
||||||
|
try { return MacroExecutor.callOnClientThread(Minecraft.getInstance(), safe, null); }
|
||||||
|
catch (InterruptedException e) { Thread.currentThread().interrupt(); return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void waitTicks(int ticks) {
|
||||||
|
MacroExecutor.withRunContext(run, () -> {
|
||||||
|
for (int i = 0; i < ticks && MacroExecutor.isCurrentRunActive(); i++) {
|
||||||
|
MacroExecutor.waitForCondition(MacroConditionRegistry.waitForNextTick());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void awaitCondition(CompletableFuture<Void> future) {
|
||||||
|
if (future != null) MacroExecutor.withRunContext(run, () -> MacroExecutor.waitForCondition(future));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void awaitCondition(autismclient.api.macro.AddonCondition condition) {
|
||||||
|
if (condition != null) MacroExecutor.withRunContext(run, () -> MacroExecutor.waitForCondition(MacroConditionRegistry.await(condition)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 sendPacket(net.minecraft.network.protocol.Packet<?> packet) {
|
||||||
|
if (packet == null) return;
|
||||||
|
runOnClientThread(() -> {
|
||||||
|
Minecraft mc = Minecraft.getInstance();
|
||||||
|
if (mc.getConnection() != null) mc.getConnection().send(packet);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public java.util.Optional<MacroValue> variable(String name) {
|
||||||
|
return run == null ? java.util.Optional.empty() : run.variables.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void setVariable(String name, MacroValue value) {
|
||||||
|
if (run != null) run.variables.set(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void removeVariable(String name) {
|
||||||
|
if (run != null) run.variables.remove(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public java.util.Map<String, MacroValue> variables() {
|
||||||
|
return run == null ? java.util.Map.of() : run.variables.snapshot();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public MacroTemplate.Resolution resolveTemplate(String template) {
|
||||||
|
return MacroTemplate.resolve(template, run == null ? null : run.variables, Minecraft.getInstance());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void runUseItemPhaseAction(Minecraft mc, UseItemPhaseAction action) throws InterruptedException {
|
||||||
|
int times = action.repeatTimes();
|
||||||
|
for (int i = 0; i < times && MacroExecutor.isCurrentRunActive(); i++) {
|
||||||
|
|
||||||
|
MacroExecutor.runOnClientThread(mc, () -> {
|
||||||
|
try { action.sendUsePacket(mc); }
|
||||||
|
catch (Exception e) { AutismClientMessaging.sendPrefixed("\u00a7cError in Use phase: " + e.getMessage()); }
|
||||||
|
});
|
||||||
|
|
||||||
|
final boolean[] gateInstalled = { false };
|
||||||
|
if (action.shouldGate()) {
|
||||||
|
MacroExecutor.runOnClientThread(mc, () -> {
|
||||||
|
try { gateInstalled[0] = action.installGate(mc); }
|
||||||
|
catch (Exception e) { AutismClientMessaging.sendPrefixed("\u00a7cError in Use gate: " + e.getMessage()); }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
|
||||||
|
for (int t = 0; t < action.holdTicks && MacroExecutor.isCurrentRunActive(); t++) {
|
||||||
|
CompletableFuture<Void> tf = MacroConditionRegistry.waitForNextTick();
|
||||||
|
MacroExecutor.waitForCondition(tf);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (gateInstalled[0]) {
|
||||||
|
final boolean wasOnThread = mc.isSameThread();
|
||||||
|
if (wasOnThread) {
|
||||||
|
action.removeGate();
|
||||||
|
} else {
|
||||||
|
MacroExecutor.runOnClientThread(mc, action::removeGate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!MacroExecutor.isCurrentRunActive()) break;
|
||||||
|
|
||||||
|
MacroExecutor.runOnClientThread(mc, () -> {
|
||||||
|
try { action.finishRelease(mc); }
|
||||||
|
catch (Exception e) { AutismClientMessaging.sendPrefixed("\u00a7cError in Use release: " + e.getMessage()); }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void runClickActionBurst(Minecraft mc, ClickAction action) throws InterruptedException {
|
||||||
|
int times = Math.max(1, action.clickCount);
|
||||||
|
|
||||||
|
MacroExecutor.runOnClientThread(mc, () -> {
|
||||||
|
for (int c = 0; c < times && MacroExecutor.isCurrentRunActive(); c++) {
|
||||||
|
try {
|
||||||
|
action.execute(mc);
|
||||||
|
} catch (Exception e) {
|
||||||
|
AutismClientMessaging.sendPrefixed("\u00a7cError in Click: " + e.getMessage());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, action.isTickAligned());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isInstantInventoryAction(MacroAction action) {
|
||||||
|
if (action instanceof ItemAction
|
||||||
|
|| action instanceof DropAction
|
||||||
|
|| action instanceof SwapSlotsAction
|
||||||
|
|| action instanceof ClickAction
|
||||||
|
|| action instanceof XCarryAction) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return action instanceof StoreItemAction storeItemAction && !storeItemAction.persistent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void runStoreItemAction(Minecraft mc, StoreItemAction action) throws InterruptedException {
|
||||||
|
if (action == null) return;
|
||||||
|
int delayTicks = StoreItemAction.clampDelayTicks(action.delayTicks);
|
||||||
|
if (delayTicks <= 0) {
|
||||||
|
MacroExecutor.runOnClientThread(mc, () -> action.doTransfer(mc));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Integer> slots = MacroExecutor.callOnClientThread(mc, () -> action.collectTransferSlots(mc), List.of());
|
||||||
|
for (int i = 0; i < slots.size() && MacroExecutor.isCurrentRunActive(); i++) {
|
||||||
|
AutismInventoryClickHelper.click(mc, slots.get(i), 0, net.minecraft.world.inventory.ContainerInput.QUICK_MOVE);
|
||||||
|
if (i + 1 < slots.size()) waitTicks(delayTicks);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action.closeAfter && !action.persistent) {
|
||||||
|
MacroExecutor.runOnClientThread(mc, () -> AutismGuiActions.closeCurrentScreen(mc, action.closeSendPkt, false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void waitTicks(int ticks) {
|
||||||
|
for (int i = 0; i < ticks && MacroExecutor.isCurrentRunActive(); i++) {
|
||||||
|
CompletableFuture<Void> tickFuture = MacroConditionRegistry.waitForNextTick();
|
||||||
|
MacroExecutor.waitForCondition(tickFuture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void runUseItemAction(Minecraft mc, UseItemAction action) throws InterruptedException {
|
||||||
|
if (action == null) return;
|
||||||
|
|
||||||
|
boolean sneaking = action.sneak;
|
||||||
|
try {
|
||||||
|
if (action.useMode == UseItemAction.UseMode.CUSTOM_HOLD) {
|
||||||
|
MacroExecutor.runOnClientThread(mc, () -> {
|
||||||
|
try {
|
||||||
|
if (sneaking) autismclient.util.AutismMacroSneak.forceSneak(mc, true);
|
||||||
|
action.execute(mc);
|
||||||
|
}
|
||||||
|
catch (Exception e) { AutismClientMessaging.sendPrefixed("\u00a7cError in UseItem: " + e.getMessage()); }
|
||||||
|
}, action.isTickAligned());
|
||||||
|
if (action.holdTicks > 0) {
|
||||||
|
waitTicks(action.holdTicks);
|
||||||
|
if (!MacroExecutor.isCurrentRunActive()) return;
|
||||||
|
MacroExecutor.runOnClientThread(mc, () -> {
|
||||||
|
try { action.sendRelease(mc); }
|
||||||
|
catch (Exception e) { AutismClientMessaging.sendPrefixed("\u00a7cError in UseItem release: " + e.getMessage()); }
|
||||||
|
}, action.isTickAligned());
|
||||||
|
if (action.waitForFinish) waitForUseItemFinish(mc, action.holdTicks + 8);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int times = Math.max(1, action.useCount);
|
||||||
|
for (int i = 0; i < times && MacroExecutor.isCurrentRunActive(); i++) {
|
||||||
|
MacroExecutor.runOnClientThread(mc, () -> {
|
||||||
|
try {
|
||||||
|
if (sneaking) autismclient.util.AutismMacroSneak.forceSneak(mc, true);
|
||||||
|
action.execute(mc);
|
||||||
|
}
|
||||||
|
catch (Exception e) { AutismClientMessaging.sendPrefixed("\u00a7cError in UseItem: " + e.getMessage()); }
|
||||||
|
}, action.isTickAligned());
|
||||||
|
if (action.waitForFinish) waitForUseItemFinish(mc, 0);
|
||||||
|
if (i + 1 < times && MacroExecutor.isCurrentRunActive()) MacroExecutor.waitOneTick();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (sneaking) mc.execute(() -> autismclient.util.AutismMacroSneak.forceSneak(mc, false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void runContainerClickSequenceAction(Minecraft mc, ContainerClickSequenceAction action) throws InterruptedException {
|
||||||
|
if (action == null) return;
|
||||||
|
List<Integer> slots = action.resolvedSlots();
|
||||||
|
int repeats = Math.max(1, action.repeatCount);
|
||||||
|
int delay = Math.max(0, action.delayTicks);
|
||||||
|
int total = repeats * slots.size();
|
||||||
|
int sent = 0;
|
||||||
|
for (int repeat = 0; repeat < repeats && MacroExecutor.isCurrentRunActive(); repeat++) {
|
||||||
|
for (int slot : slots) {
|
||||||
|
if (!MacroExecutor.isCurrentRunActive()) return;
|
||||||
|
MacroExecutor.runOnClientThread(mc, () -> action.executeClick(mc, slot));
|
||||||
|
sent++;
|
||||||
|
if (delay > 0 && sent < total) waitTicks(delay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void runPacketBurstAction(Minecraft mc, PacketBurstAction action) {
|
||||||
|
if (action == null || mc == null || mc.getConnection() == null) return;
|
||||||
|
if (action.flushBefore) AutismSharedState.get().flushDelayedPackets(mc.getConnection());
|
||||||
|
int total = action.effectiveCount();
|
||||||
|
int delay = Math.max(0, action.delayTicks);
|
||||||
|
for (int i = 0; i < total && MacroExecutor.isCurrentRunActive(); i++) {
|
||||||
|
action.sendOne(mc);
|
||||||
|
if (delay > 0 && i + 1 < total) waitTicks(delay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void waitForUseItemFinish(Minecraft mc, int fallbackTicks) throws InterruptedException {
|
||||||
|
if (mc == null || !MacroExecutor.isCurrentRunActive()) return;
|
||||||
|
|
||||||
|
if (!Boolean.TRUE.equals(MacroExecutor.callOnClientThread(mc,
|
||||||
|
() -> mc.player != null && mc.player.isUsingItem(),
|
||||||
|
Boolean.FALSE))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int remaining = MacroExecutor.callOnClientThread(mc,
|
||||||
|
() -> mc.player == null ? 0 : Math.max(0, mc.player.getUseItemRemainingTicks()),
|
||||||
|
0);
|
||||||
|
int maxTicks = Math.max(8, remaining > 0 ? remaining + 8 : fallbackTicks + 8);
|
||||||
|
maxTicks = Math.min(maxTicks, 72000);
|
||||||
|
for (int i = 0; i < maxTicks && MacroExecutor.isCurrentRunActive(); i++) {
|
||||||
|
if (!Boolean.TRUE.equals(MacroExecutor.callOnClientThread(mc,
|
||||||
|
() -> mc.player != null && mc.player.isUsingItem(),
|
||||||
|
Boolean.FALSE))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CompletableFuture<Void> tickFuture = MacroConditionRegistry.waitForNextTick();
|
||||||
|
MacroExecutor.waitForCondition(tickFuture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -98,7 +98,7 @@ public class MacroExecutor {
|
||||||
private static final java.util.concurrent.ConcurrentHashMap<Long, RunState> RUNS_BY_ID = new java.util.concurrent.ConcurrentHashMap<>();
|
private 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();
|
private static final AtomicLong RUN_STATE_REVISION = new AtomicLong();
|
||||||
static final ThreadLocal<RunState> CURRENT_RUN = new ThreadLocal<>();
|
static final ThreadLocal<RunState> CURRENT_RUN = new ThreadLocal<>();
|
||||||
private 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;
|
private static volatile RunState primaryRun = null;
|
||||||
private static volatile boolean visibleRunActive;
|
private static volatile boolean visibleRunActive;
|
||||||
private static AutismMacro currentMacro = null;
|
private static AutismMacro currentMacro = null;
|
||||||
|
|
@ -147,7 +147,7 @@ public class MacroExecutor {
|
||||||
|
|
||||||
private static final java.util.concurrent.ConcurrentHashMap<MoveAction, int[]> backgroundMoves =
|
private static final java.util.concurrent.ConcurrentHashMap<MoveAction, int[]> backgroundMoves =
|
||||||
new java.util.concurrent.ConcurrentHashMap<>();
|
new java.util.concurrent.ConcurrentHashMap<>();
|
||||||
private static final ThreadLocal<RepeatPacketContext> REPEAT_PACKET_CONTEXT = new ThreadLocal<>();
|
static final ThreadLocal<RepeatPacketContext> REPEAT_PACKET_CONTEXT = new ThreadLocal<>();
|
||||||
private static final ThreadLocal<Integer> REPEAT_PACKET_SKIP = ThreadLocal.withInitial(() -> 0);
|
private static final ThreadLocal<Integer> REPEAT_PACKET_SKIP = ThreadLocal.withInitial(() -> 0);
|
||||||
|
|
||||||
static final class RunState {
|
static final class RunState {
|
||||||
|
|
@ -237,7 +237,7 @@ public class MacroExecutor {
|
||||||
}
|
}
|
||||||
|
|
||||||
record ChatCapture(String sender, String message, String displayText, Component displayComponent, ChatSource source) {}
|
record ChatCapture(String sender, String message, String displayText, Component displayComponent, ChatSource source) {}
|
||||||
private record RepeatPacketContext(AutismMacro macro, int startIdx, int endIdx) {}
|
record RepeatPacketContext(AutismMacro macro, int startIdx, int endIdx) {}
|
||||||
private record InlineNextActions(java.util.List<MacroAction> actions, int lastIndex) {
|
private record InlineNextActions(java.util.List<MacroAction> actions, int lastIndex) {
|
||||||
static InlineNextActions empty() {
|
static InlineNextActions empty() {
|
||||||
return new InlineNextActions(java.util.List.of(), -1);
|
return new InlineNextActions(java.util.List.of(), -1);
|
||||||
|
|
@ -985,7 +985,7 @@ public class MacroExecutor {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!MacroDynamicBindings.apply(action, mc)) continue;
|
if (!MacroDynamicBindings.apply(action, mc)) continue;
|
||||||
if (!dynamicTextInputsAvailable(action, mc)) continue;
|
if (!MacroActionRunner.dynamicTextInputsAvailable(action, mc)) continue;
|
||||||
if (!MacroPrearm.hasPrearmedWait(action)) MacroPrearm.clearOwnCaptureOutput(action);
|
if (!MacroPrearm.hasPrearmedWait(action)) MacroPrearm.clearOwnCaptureOutput(action);
|
||||||
|
|
||||||
if (action instanceof BranchAction branch) {
|
if (action instanceof BranchAction branch) {
|
||||||
|
|
@ -1044,10 +1044,10 @@ public class MacroExecutor {
|
||||||
EnumSet<SharedClientResource> heldResources = acquireClientResources(action);
|
EnumSet<SharedClientResource> heldResources = acquireClientResources(action);
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if (!waitForGuiBeforeAction(mc, action)) continue;
|
if (!MacroActionRunner.waitForGuiBeforeAction(mc, action)) continue;
|
||||||
beginRaycastAim(mc, action);
|
MacroActionRunner.beginRaycastAim(mc, action);
|
||||||
java.util.concurrent.CompletableFuture<Void> postGuiFuture =
|
java.util.concurrent.CompletableFuture<Void> postGuiFuture =
|
||||||
(action instanceof ItemAction || action instanceof DropAction || isTargetWaitInteractionAction(action)) ? null : createPostGuiFuture(mc, action);
|
(action instanceof ItemAction || action instanceof DropAction || MacroActionRunner.isTargetWaitInteractionAction(action)) ? null : MacroActionRunner.createPostGuiFuture(mc, action);
|
||||||
|
|
||||||
if (burstMode && action instanceof SendPacketAction) {
|
if (burstMode && action instanceof SendPacketAction) {
|
||||||
|
|
||||||
|
|
@ -1719,7 +1719,7 @@ public class MacroExecutor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (action instanceof UseItemAction) {
|
else if (action instanceof UseItemAction) {
|
||||||
runUseItemAction(mc, (UseItemAction) action);
|
MacroActionRunner.runUseItemAction(mc, (UseItemAction) action);
|
||||||
}
|
}
|
||||||
else if (action instanceof ItemAction) {
|
else if (action instanceof ItemAction) {
|
||||||
ItemAction ia = (ItemAction) action;
|
ItemAction ia = (ItemAction) action;
|
||||||
|
|
@ -1728,18 +1728,18 @@ public class MacroExecutor {
|
||||||
waitForItemActionTargets(mc, ia);
|
waitForItemActionTargets(mc, ia);
|
||||||
} catch (java.util.concurrent.CancellationException e) { }
|
} catch (java.util.concurrent.CancellationException e) { }
|
||||||
}
|
}
|
||||||
postGuiFuture = createPostGuiFuture(mc, ia);
|
postGuiFuture = MacroActionRunner.createPostGuiFuture(mc, ia);
|
||||||
if (ia.useClickDelay && ia.clickDelayMs > 0) {
|
if (ia.useClickDelay && ia.clickDelayMs > 0) {
|
||||||
runItemActionPaced(mc, ia);
|
MacroActionRunner.runItemActionPaced(mc, ia);
|
||||||
} else {
|
} else {
|
||||||
runMacroActionOnClientThread(mc, action, "ItemAction");
|
MacroActionRunner.runMacroActionOnClientThread(mc, action, "ItemAction");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (action instanceof DropAction || action instanceof SwapSlotsAction) {
|
else if (action instanceof DropAction || action instanceof SwapSlotsAction) {
|
||||||
if (action instanceof DropAction dropAction) {
|
if (action instanceof DropAction dropAction) {
|
||||||
postGuiFuture = createPostGuiFuture(mc, dropAction);
|
postGuiFuture = MacroActionRunner.createPostGuiFuture(mc, dropAction);
|
||||||
}
|
}
|
||||||
runMacroActionOnClientThread(mc, action, action.getDisplayName());
|
MacroActionRunner.runMacroActionOnClientThread(mc, action, action.getDisplayName());
|
||||||
}
|
}
|
||||||
else if (action instanceof CraftAction craftAction) {
|
else if (action instanceof CraftAction craftAction) {
|
||||||
runCraftAction(mc, craftAction);
|
runCraftAction(mc, craftAction);
|
||||||
|
|
@ -1770,7 +1770,7 @@ public class MacroExecutor {
|
||||||
if (sia.persistent) {
|
if (sia.persistent) {
|
||||||
|
|
||||||
while (isCurrentRunActive()) {
|
while (isCurrentRunActive()) {
|
||||||
try { 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()); }
|
||||||
|
|
||||||
|
|
@ -1778,14 +1778,14 @@ public class MacroExecutor {
|
||||||
waitForCondition(siTick);
|
waitForCondition(siTick);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try { runStoreItemAction(mc, sia); }
|
try { MacroActionRunner.runStoreItemAction(mc, sia); }
|
||||||
catch (InterruptedException e) { Thread.currentThread().interrupt(); }
|
catch (InterruptedException e) { Thread.currentThread().interrupt(); }
|
||||||
catch (Exception e) { AutismClientMessaging.sendPrefixed("Store error: " + e.getMessage()); }
|
catch (Exception e) { AutismClientMessaging.sendPrefixed("Store error: " + e.getMessage()); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (action instanceof ClickAction) {
|
else if (action instanceof ClickAction) {
|
||||||
ClickAction ca = (ClickAction) action;
|
ClickAction ca = (ClickAction) action;
|
||||||
runClickActionBurst(mc, ca);
|
MacroActionRunner.runClickActionBurst(mc, ca);
|
||||||
}
|
}
|
||||||
else if (action instanceof PayAction) {
|
else if (action instanceof PayAction) {
|
||||||
runPayAction(mc, (PayAction) action);
|
runPayAction(mc, (PayAction) action);
|
||||||
|
|
@ -1829,10 +1829,10 @@ public class MacroExecutor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (action instanceof ContainerClickSequenceAction sequence) {
|
else if (action instanceof ContainerClickSequenceAction sequence) {
|
||||||
runContainerClickSequenceAction(mc, sequence);
|
MacroActionRunner.runContainerClickSequenceAction(mc, sequence);
|
||||||
}
|
}
|
||||||
else if (action instanceof PacketBurstAction burst) {
|
else if (action instanceof PacketBurstAction burst) {
|
||||||
runPacketBurstAction(mc, burst);
|
MacroActionRunner.runPacketBurstAction(mc, burst);
|
||||||
}
|
}
|
||||||
else if (action instanceof BundleDupeV2Action bundleV2) {
|
else if (action instanceof BundleDupeV2Action bundleV2) {
|
||||||
setCurrentStatus("Bundle Dupe V2");
|
setCurrentStatus("Bundle Dupe V2");
|
||||||
|
|
@ -1851,17 +1851,17 @@ public class MacroExecutor {
|
||||||
else if (action instanceof PacketGateAction pga) {
|
else if (action instanceof PacketGateAction pga) {
|
||||||
MacroRace.runPacketGateAction(mc, pga);
|
MacroRace.runPacketGateAction(mc, pga);
|
||||||
}
|
}
|
||||||
else if (isTargetWaitInteractionAction(action)) {
|
else if (MacroActionRunner.isTargetWaitInteractionAction(action)) {
|
||||||
postGuiFuture = runTargetWaitInteractionAction(mc, action);
|
postGuiFuture = MacroActionRunner.runTargetWaitInteractionAction(mc, action);
|
||||||
}
|
}
|
||||||
else if (action instanceof MacroVariablesAction || action instanceof AssertAction) {
|
else if (action instanceof MacroVariablesAction || action instanceof AssertAction) {
|
||||||
action.execute(mc);
|
action.execute(mc);
|
||||||
}
|
}
|
||||||
else if (action instanceof UseItemPhaseAction phaseAction) {
|
else if (action instanceof UseItemPhaseAction phaseAction) {
|
||||||
runUseItemPhaseAction(mc, phaseAction);
|
MacroActionRunner.runUseItemPhaseAction(mc, phaseAction);
|
||||||
}
|
}
|
||||||
else if (action instanceof autismclient.api.macro.ContextMacroAction contextAction) {
|
else if (action instanceof autismclient.api.macro.ContextMacroAction contextAction) {
|
||||||
runContextMacroAction(contextAction);
|
MacroActionRunner.runContextMacroAction(contextAction);
|
||||||
}
|
}
|
||||||
else if (action instanceof PlaceAction placeInteract && placeInteract.interact) {
|
else if (action instanceof PlaceAction placeInteract && placeInteract.interact) {
|
||||||
|
|
||||||
|
|
@ -1894,9 +1894,9 @@ public class MacroExecutor {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
if (usesTickAlignedDispatch(action)) {
|
if (MacroActionRunner.usesTickAlignedDispatch(action)) {
|
||||||
|
|
||||||
runMacroActionOnClientThread(mc, action, action.getDisplayName());
|
MacroActionRunner.runMacroActionOnClientThread(mc, action, action.getDisplayName());
|
||||||
} 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);
|
||||||
|
|
@ -1918,7 +1918,7 @@ public class MacroExecutor {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
runMacroActionOnClientThread(mc, action, action.getDisplayName());
|
MacroActionRunner.runMacroActionOnClientThread(mc, action, action.getDisplayName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1935,7 +1935,7 @@ public class MacroExecutor {
|
||||||
broadcastStepProgress(runState, i + 1, macro.actions.size(), macro.name);
|
broadcastStepProgress(runState, i + 1, macro.actions.size(), macro.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isCurrentRunActive() && !isInstantInventoryAction(action)) {
|
if (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) {
|
||||||
|
|
@ -2122,15 +2122,15 @@ public class MacroExecutor {
|
||||||
|
|
||||||
static void executeSingleActionWithWaits(Minecraft mc, MacroAction action, AutismModule module) throws InterruptedException {
|
static void executeSingleActionWithWaits(Minecraft mc, MacroAction action, AutismModule module) throws InterruptedException {
|
||||||
if (!MacroDynamicBindings.apply(action, mc)) return;
|
if (!MacroDynamicBindings.apply(action, mc)) return;
|
||||||
if (!dynamicTextInputsAvailable(action, mc)) return;
|
if (!MacroActionRunner.dynamicTextInputsAvailable(action, mc)) return;
|
||||||
MacroPrearm.clearOwnCaptureOutput(action);
|
MacroPrearm.clearOwnCaptureOutput(action);
|
||||||
EnumSet<SharedClientResource> heldResources = acquireClientResources(action);
|
EnumSet<SharedClientResource> heldResources = acquireClientResources(action);
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if (!waitForGuiBeforeAction(mc, action)) return;
|
if (!MacroActionRunner.waitForGuiBeforeAction(mc, action)) return;
|
||||||
beginRaycastAim(mc, action);
|
MacroActionRunner.beginRaycastAim(mc, action);
|
||||||
java.util.concurrent.CompletableFuture<Void> postGuiFuture =
|
java.util.concurrent.CompletableFuture<Void> postGuiFuture =
|
||||||
(action instanceof ItemAction || action instanceof DropAction || isTargetWaitInteractionAction(action)) ? null : createPostGuiFuture(mc, action);
|
(action instanceof ItemAction || action instanceof DropAction || MacroActionRunner.isTargetWaitInteractionAction(action)) ? null : MacroActionRunner.createPostGuiFuture(mc, action);
|
||||||
|
|
||||||
if (action instanceof DelayAction) {
|
if (action instanceof DelayAction) {
|
||||||
DelayAction da = (DelayAction) action;
|
DelayAction da = (DelayAction) action;
|
||||||
|
|
@ -2191,8 +2191,8 @@ public class MacroExecutor {
|
||||||
MacroPrearm.commitStagedCapture(wgta);
|
MacroPrearm.commitStagedCapture(wgta);
|
||||||
} else if (action instanceof PacketGateAction pga) {
|
} else if (action instanceof PacketGateAction pga) {
|
||||||
MacroRace.runPacketGateAction(mc, pga);
|
MacroRace.runPacketGateAction(mc, pga);
|
||||||
} else if (isTargetWaitInteractionAction(action)) {
|
} else if (MacroActionRunner.isTargetWaitInteractionAction(action)) {
|
||||||
postGuiFuture = 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;
|
||||||
setCurrentStatus(wh.waitingStatusText());
|
setCurrentStatus(wh.waitingStatusText());
|
||||||
|
|
@ -2364,7 +2364,7 @@ public class MacroExecutor {
|
||||||
} else if (action instanceof PlaceAction) {
|
} else if (action instanceof PlaceAction) {
|
||||||
runPlaceAction(mc, (PlaceAction) action);
|
runPlaceAction(mc, (PlaceAction) action);
|
||||||
} else if (action instanceof UseItemAction) {
|
} else if (action instanceof UseItemAction) {
|
||||||
runUseItemAction(mc, (UseItemAction) action);
|
MacroActionRunner.runUseItemAction(mc, (UseItemAction) action);
|
||||||
} else if (action instanceof JumpAction) {
|
} else if (action instanceof JumpAction) {
|
||||||
JumpAction ja = (JumpAction) action;
|
JumpAction ja = (JumpAction) action;
|
||||||
mc.execute(() -> ja.execute(mc));
|
mc.execute(() -> ja.execute(mc));
|
||||||
|
|
@ -2428,13 +2428,13 @@ public class MacroExecutor {
|
||||||
waitForItemActionTargets(mc, ia);
|
waitForItemActionTargets(mc, ia);
|
||||||
} catch (java.util.concurrent.CancellationException e) { }
|
} catch (java.util.concurrent.CancellationException e) { }
|
||||||
}
|
}
|
||||||
postGuiFuture = createPostGuiFuture(mc, ia);
|
postGuiFuture = MacroActionRunner.createPostGuiFuture(mc, ia);
|
||||||
runMacroActionOnClientThread(mc, action, "ItemAction");
|
MacroActionRunner.runMacroActionOnClientThread(mc, action, "ItemAction");
|
||||||
} else if (action instanceof DropAction || action instanceof SwapSlotsAction) {
|
} else if (action instanceof DropAction || action instanceof SwapSlotsAction) {
|
||||||
if (action instanceof DropAction dropAction) {
|
if (action instanceof DropAction dropAction) {
|
||||||
postGuiFuture = createPostGuiFuture(mc, dropAction);
|
postGuiFuture = MacroActionRunner.createPostGuiFuture(mc, dropAction);
|
||||||
}
|
}
|
||||||
runMacroActionOnClientThread(mc, action, action.getDisplayName());
|
MacroActionRunner.runMacroActionOnClientThread(mc, action, action.getDisplayName());
|
||||||
} else if (action instanceof SendPacketAction) {
|
} else if (action instanceof SendPacketAction) {
|
||||||
if (module != null && module.useInstantExecutionMode()) {
|
if (module != null && module.useInstantExecutionMode()) {
|
||||||
try {
|
try {
|
||||||
|
|
@ -2453,7 +2453,7 @@ public class MacroExecutor {
|
||||||
}
|
}
|
||||||
} else if (action instanceof ClickAction) {
|
} else if (action instanceof ClickAction) {
|
||||||
ClickAction ca = (ClickAction) action;
|
ClickAction ca = (ClickAction) action;
|
||||||
runClickActionBurst(mc, ca);
|
MacroActionRunner.runClickActionBurst(mc, ca);
|
||||||
} else if (action instanceof PayAction) {
|
} else if (action instanceof PayAction) {
|
||||||
runPayAction(mc, (PayAction) action);
|
runPayAction(mc, (PayAction) action);
|
||||||
} else if (action instanceof XCarryAction xsa) {
|
} else if (action instanceof XCarryAction xsa) {
|
||||||
|
|
@ -2489,14 +2489,14 @@ public class MacroExecutor {
|
||||||
+ (sia.persistent ? " \u221e" : ""));
|
+ (sia.persistent ? " \u221e" : ""));
|
||||||
if (sia.persistent) {
|
if (sia.persistent) {
|
||||||
while (isCurrentRunActive()) {
|
while (isCurrentRunActive()) {
|
||||||
try { 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()); }
|
||||||
CompletableFuture<Void> siTick = MacroConditionRegistry.waitForNextTick();
|
CompletableFuture<Void> siTick = MacroConditionRegistry.waitForNextTick();
|
||||||
waitForCondition(siTick);
|
waitForCondition(siTick);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try { runStoreItemAction(mc, sia); }
|
try { MacroActionRunner.runStoreItemAction(mc, sia); }
|
||||||
catch (InterruptedException e) { Thread.currentThread().interrupt(); }
|
catch (InterruptedException e) { Thread.currentThread().interrupt(); }
|
||||||
catch (Exception e) { AutismClientMessaging.sendPrefixed("Store error: " + e.getMessage()); }
|
catch (Exception e) { AutismClientMessaging.sendPrefixed("Store error: " + e.getMessage()); }
|
||||||
}
|
}
|
||||||
|
|
@ -2513,13 +2513,13 @@ public class MacroExecutor {
|
||||||
+ (t.getMessage() == null ? t.getClass().getSimpleName() : t.getMessage()));
|
+ (t.getMessage() == null ? t.getClass().getSimpleName() : t.getMessage()));
|
||||||
}
|
}
|
||||||
} else if (action instanceof ContainerClickSequenceAction sequence) {
|
} else if (action instanceof ContainerClickSequenceAction sequence) {
|
||||||
runContainerClickSequenceAction(mc, sequence);
|
MacroActionRunner.runContainerClickSequenceAction(mc, sequence);
|
||||||
} else if (action instanceof PacketBurstAction burst) {
|
} else if (action instanceof PacketBurstAction burst) {
|
||||||
runPacketBurstAction(mc, burst);
|
MacroActionRunner.runPacketBurstAction(mc, burst);
|
||||||
} else if (action instanceof TickSyncAction tsa) {
|
} else if (action instanceof TickSyncAction tsa) {
|
||||||
if (mc.level == null) return;
|
if (mc.level == null) return;
|
||||||
java.util.List<net.minecraft.network.protocol.Packet<?>> preGenerated =
|
java.util.List<net.minecraft.network.protocol.Packet<?>> preGenerated =
|
||||||
preGeneratePacketsForRepeat(tsa.preGenCount, mc);
|
MacroActionRunner.preGeneratePacketsForRepeat(tsa.preGenCount, mc);
|
||||||
long targetTick = mc.level.getGameTime() + tsa.tickOffset;
|
long targetTick = mc.level.getGameTime() + tsa.tickOffset;
|
||||||
setCurrentStatus("Tick Sync -> " + targetTick + " (" + preGenerated.size() + " pkts)");
|
setCurrentStatus("Tick Sync -> " + targetTick + " (" + preGenerated.size() + " pkts)");
|
||||||
while (isCurrentRunActive() && mc.level.getGameTime() < targetTick) {
|
while (isCurrentRunActive() && mc.level.getGameTime() < targetTick) {
|
||||||
|
|
@ -2534,7 +2534,7 @@ public class MacroExecutor {
|
||||||
} else if (action instanceof RevisionSyncAction rsa) {
|
} else if (action instanceof RevisionSyncAction rsa) {
|
||||||
if (mc.player == null || mc.player.containerMenu == null) return;
|
if (mc.player == null || mc.player.containerMenu == null) return;
|
||||||
java.util.List<net.minecraft.network.protocol.Packet<?>> preGenerated =
|
java.util.List<net.minecraft.network.protocol.Packet<?>> preGenerated =
|
||||||
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;
|
||||||
setCurrentStatus("Rev Sync -> " + targetRevision + " (" + preGenerated.size() + " pkts)");
|
setCurrentStatus("Rev Sync -> " + targetRevision + " (" + preGenerated.size() + " pkts)");
|
||||||
|
|
@ -2552,7 +2552,7 @@ public class MacroExecutor {
|
||||||
} else if (action instanceof ServerTickSyncAction stsa) {
|
} else if (action instanceof ServerTickSyncAction stsa) {
|
||||||
if (mc.getConnection() == null) return;
|
if (mc.getConnection() == null) return;
|
||||||
java.util.List<net.minecraft.network.protocol.Packet<?>> preGenerated =
|
java.util.List<net.minecraft.network.protocol.Packet<?>> preGenerated =
|
||||||
preGeneratePacketsForRepeat(stsa.preGenCount, mc);
|
MacroActionRunner.preGeneratePacketsForRepeat(stsa.preGenCount, mc);
|
||||||
int sampleWaitMs = 0;
|
int sampleWaitMs = 0;
|
||||||
while (isCurrentRunActive() && !ServerTickTracker.isReady() && sampleWaitMs < stsa.maxWaitMs) {
|
while (isCurrentRunActive() && !ServerTickTracker.isReady() && sampleWaitMs < stsa.maxWaitMs) {
|
||||||
float progress = ServerTickTracker.getWarmupProgress();
|
float progress = ServerTickTracker.getWarmupProgress();
|
||||||
|
|
@ -2604,14 +2604,14 @@ public class MacroExecutor {
|
||||||
if (stopAction.target == StopMacroAction.StopTarget.SELF) stopCurrentRun();
|
if (stopAction.target == StopMacroAction.StopTarget.SELF) stopCurrentRun();
|
||||||
else stopAction.execute(mc);
|
else stopAction.execute(mc);
|
||||||
} else if (action instanceof UseItemPhaseAction phaseAction) {
|
} else if (action instanceof UseItemPhaseAction phaseAction) {
|
||||||
runUseItemPhaseAction(mc, phaseAction);
|
MacroActionRunner.runUseItemPhaseAction(mc, phaseAction);
|
||||||
} else if (action instanceof autismclient.api.macro.ContextMacroAction contextAction) {
|
} else if (action instanceof autismclient.api.macro.ContextMacroAction contextAction) {
|
||||||
runContextMacroAction(contextAction);
|
MacroActionRunner.runContextMacroAction(contextAction);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (usesTickAlignedDispatch(action)) {
|
if (MacroActionRunner.usesTickAlignedDispatch(action)) {
|
||||||
|
|
||||||
runMacroActionOnClientThread(mc, action, action.getDisplayName());
|
MacroActionRunner.runMacroActionOnClientThread(mc, action, action.getDisplayName());
|
||||||
} 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);
|
||||||
RunState scheduledRun = CURRENT_RUN.get();
|
RunState scheduledRun = CURRENT_RUN.get();
|
||||||
|
|
@ -2630,7 +2630,7 @@ public class MacroExecutor {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
runMacroActionOnClientThread(mc, action, action.getDisplayName());
|
MacroActionRunner.runMacroActionOnClientThread(mc, action, action.getDisplayName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2642,7 +2642,7 @@ public class MacroExecutor {
|
||||||
} catch (java.util.concurrent.CancellationException e) { }
|
} catch (java.util.concurrent.CancellationException e) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isCurrentRunActive() && !isInstantInventoryAction(action) && module != null && module.useInstantExecutionMode()) {
|
if (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();
|
||||||
|
|
@ -2653,509 +2653,6 @@ public class MacroExecutor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void beginRaycastAim(Minecraft mc, MacroAction action) {
|
|
||||||
if (!(action instanceof RaycastAim aim) || !aim.isRaycast()) return;
|
|
||||||
autismclient.util.AutismRotationUtil.Rotation rotation;
|
|
||||||
try {
|
|
||||||
rotation = callOnClientThread(mc, () -> MacroRaycastAim.aimFor(mc, aim.raycastTarget(mc)), null);
|
|
||||||
} catch (InterruptedException interrupted) {
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (rotation == null) return;
|
|
||||||
MacroRaycastAim.hold(rotation);
|
|
||||||
waitOneTick();
|
|
||||||
}
|
|
||||||
|
|
||||||
static boolean dynamicTextInputsAvailable(MacroAction action, Minecraft mc) {
|
|
||||||
if (action instanceof WaitForChatAction chat && chat.effectiveMatchMode() == MacroCapturePattern.Mode.MATCH) {
|
|
||||||
return MacroVariables.resolve(chat.pattern, mc).success();
|
|
||||||
}
|
|
||||||
if (action instanceof WaitForGuiAction gui && gui.matchMode == MacroCapturePattern.Mode.MATCH) {
|
|
||||||
return MacroVariables.resolve(gui.guiTitle, mc).success();
|
|
||||||
}
|
|
||||||
if (action instanceof WaitGuiTypeAction gui && gui.matchMode == MacroCapturePattern.Mode.MATCH) {
|
|
||||||
return MacroVariables.resolve(gui.title, mc).success();
|
|
||||||
}
|
|
||||||
if (action instanceof WaitInventoryPredicateAction inventory) {
|
|
||||||
return MacroVariables.resolve(inventory.itemName, mc).success();
|
|
||||||
}
|
|
||||||
if (action instanceof WaitDurabilityAction durability && durability.targetMode == WaitDurabilityAction.TargetMode.ITEM) {
|
|
||||||
return MacroVariables.resolve(durability.itemName, mc).success();
|
|
||||||
}
|
|
||||||
if (action instanceof WaitEntityTargetAction entity) {
|
|
||||||
return MacroVariables.resolve(entity.entityId, mc).success();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static java.util.List<net.minecraft.network.protocol.Packet<?>> preGeneratePacketsForRepeat(
|
|
||||||
int count, Minecraft mc) {
|
|
||||||
RepeatPacketContext context = REPEAT_PACKET_CONTEXT.get();
|
|
||||||
if (context == null || context.macro() == null) return new java.util.ArrayList<>();
|
|
||||||
return preGeneratePackets(context.macro(), context.startIdx(), count, context.endIdx());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isTargetWaitInteractionAction(MacroAction action) {
|
|
||||||
return action instanceof OpenContainerAction || action instanceof InteractEntityAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static CompletableFuture<Void> runTargetWaitInteractionAction(Minecraft mc, MacroAction action) throws InterruptedException {
|
|
||||||
boolean waitForTarget = switch (action) {
|
|
||||||
case OpenContainerAction open -> open.waitForTarget;
|
|
||||||
case InteractEntityAction interact -> interact.waitForTarget;
|
|
||||||
default -> false;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!waitForTarget) {
|
|
||||||
CompletableFuture<Void> postGuiFuture = createPostGuiFuture(mc, action);
|
|
||||||
runTargetInteractionAttempt(mc, action);
|
|
||||||
return postGuiFuture;
|
|
||||||
}
|
|
||||||
|
|
||||||
setCurrentStatus("Waiting target: " + action.getDisplayName());
|
|
||||||
while (isCurrentRunActive()) {
|
|
||||||
if (!canRunTargetInteractionNow(mc, action)) {
|
|
||||||
java.util.concurrent.locks.LockSupport.parkNanos(MACRO_WAIT_POLL_NANOS);
|
|
||||||
if (Thread.interrupted()) throw new InterruptedException();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
CompletableFuture<Void> postGuiFuture = createPostGuiFuture(mc, action);
|
|
||||||
if (runTargetInteractionAttempt(mc, action)) {
|
|
||||||
return postGuiFuture;
|
|
||||||
}
|
|
||||||
if (postGuiFuture != null) postGuiFuture.cancel(true);
|
|
||||||
java.util.concurrent.locks.LockSupport.parkNanos(MACRO_WAIT_POLL_NANOS);
|
|
||||||
if (Thread.interrupted()) throw new InterruptedException();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean canRunTargetInteractionNow(Minecraft mc, MacroAction action) throws InterruptedException {
|
|
||||||
return callOnClientThread(mc, () -> {
|
|
||||||
if (action instanceof OpenContainerAction open) return open.canExecuteNow(mc);
|
|
||||||
if (action instanceof InteractEntityAction interact) return interact.canExecuteNow(mc);
|
|
||||||
return true;
|
|
||||||
}, Boolean.FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean runTargetInteractionAttempt(Minecraft mc, MacroAction action) throws InterruptedException {
|
|
||||||
return callOnClientThread(mc, () -> {
|
|
||||||
try {
|
|
||||||
if (action instanceof OpenContainerAction open) return open.tryExecute(mc);
|
|
||||||
if (action instanceof InteractEntityAction interact) return interact.tryExecute(mc);
|
|
||||||
action.execute(mc);
|
|
||||||
return true;
|
|
||||||
} catch (Exception e) {
|
|
||||||
AutismClientMessaging.sendPrefixed("\u00a7cError in " + action.getDisplayName() + ": " + e.getMessage());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}, Boolean.FALSE, usesTickAlignedDispatch(action));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static CompletableFuture<Void> createPostGuiFuture(Minecraft mc, MacroAction action) {
|
|
||||||
if (Boolean.TRUE.equals(SUPPRESS_POST_GUI_AFTER.get())) return null;
|
|
||||||
if (!(action instanceof WaitsForGui wfg) || !wfg.isWaitForGuiAfter()) return null;
|
|
||||||
return createWaitsForGuiFuture(mc, wfg);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static CompletableFuture<Void> createWaitsForGuiFuture(Minecraft mc, WaitsForGui wfg) {
|
|
||||||
MacroTemplate.Resolution guiName = MacroVariables.resolve(wfg.getWaitGuiName(), mc);
|
|
||||||
if (!guiName.success()) return CompletableFuture.completedFuture(null);
|
|
||||||
return wfg.isWaitForGuiChange()
|
|
||||||
? MacroConditionRegistry.waitForGuiChange(mc.gui.screen())
|
|
||||||
: MacroConditionRegistry.waitForGui(guiName.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean waitForGuiBeforeAction(Minecraft mc, MacroAction action) throws InterruptedException {
|
|
||||||
if (!(action instanceof WaitsForGui wfg)) return true;
|
|
||||||
return waitForGuiBeforeAction(mc, wfg);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean waitForGuiBeforeAction(Minecraft mc, WaitsForGui action) throws InterruptedException {
|
|
||||||
if (mc == null || action == null || !action.isWaitForGuiBefore()) return true;
|
|
||||||
MacroTemplate.Resolution guiName = MacroVariables.resolve(action.getWaitGuiName(), mc);
|
|
||||||
if (!guiName.success()) return false;
|
|
||||||
if (isWaitGuiPresent(mc, guiName.value())) {
|
|
||||||
waitForCurrentGuiReady(mc);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
CompletableFuture<Void> future = MacroConditionRegistry.waitForGui(guiName.value());
|
|
||||||
waitForCondition(future);
|
|
||||||
waitForCurrentGuiReady(mc);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isWaitGuiPresent(Minecraft mc, String guiName) {
|
|
||||||
if (mc == null || mc.gui.screen() == null) return false;
|
|
||||||
if (MacroGuiMatcher.isOwnScreen(mc.gui.screen())) return false;
|
|
||||||
String expected = guiName == null ? "" : guiName.trim();
|
|
||||||
if (expected.isEmpty()) return true;
|
|
||||||
String actual = mc.gui.screen().getTitle() == null ? "" : mc.gui.screen().getTitle().getString();
|
|
||||||
return matchesWaitGuiTitle(expected, actual);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean matchesWaitGuiTitle(String expected, String actual) {
|
|
||||||
if (expected == null || expected.isBlank() || actual == null || actual.isBlank()) return false;
|
|
||||||
String expectedLower = expected.toLowerCase(Locale.ROOT);
|
|
||||||
String actualLower = actual.toLowerCase(Locale.ROOT);
|
|
||||||
if (expectedLower.equals(actualLower) || actualLower.contains(expectedLower)) return true;
|
|
||||||
for (String word : expectedLower.split("\\s+")) {
|
|
||||||
if (!word.isBlank() && !actualLower.contains(word)) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void waitForCurrentGuiReady(Minecraft mc) throws InterruptedException {
|
|
||||||
|
|
||||||
long deadline = System.nanoTime() + 500_000_000L;
|
|
||||||
while (isCurrentRunActive()) {
|
|
||||||
Boolean ready = callOnClientThread(mc, () -> {
|
|
||||||
if (mc.player == null || mc.gui.screen() == null) return false;
|
|
||||||
if (mc.player.containerMenu != null && mc.player.containerMenu != mc.player.inventoryMenu) {
|
|
||||||
return mc.player.containerMenu.getStateId() > 0;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}, Boolean.FALSE);
|
|
||||||
if (Boolean.TRUE.equals(ready)) return;
|
|
||||||
if (System.nanoTime() >= deadline) return;
|
|
||||||
java.util.concurrent.locks.LockSupport.parkNanos(MACRO_WAIT_POLL_NANOS);
|
|
||||||
if (Thread.interrupted()) return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void runMacroActionOnClientThread(Minecraft mc, MacroAction action, String label) throws InterruptedException {
|
|
||||||
Runnable body = () -> {
|
|
||||||
try {
|
|
||||||
action.execute(mc);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
recordAddonActionError(action, "Action threw " + t.getClass().getSimpleName());
|
|
||||||
AutismClientMessaging.sendPrefixed("\u00a7cError in " + label + ": "
|
|
||||||
+ (t.getMessage() == null ? t.getClass().getSimpleName() : t.getMessage()));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (usesTickAlignedDispatch(action)) runOnClientTick(mc, body);
|
|
||||||
else runOnClientThread(mc, body);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean usesTickAlignedDispatch(MacroAction action) {
|
|
||||||
return action instanceof PacketOrdered ordered && ordered.isTickAligned();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void runItemActionPaced(Minecraft mc, ItemAction ia) throws InterruptedException {
|
|
||||||
setCurrentStatus(ia.getDisplayName());
|
|
||||||
java.util.List<Runnable> plan = callOnClientThread(mc, () -> ia.buildClickPlan(mc), java.util.Collections.<Runnable>emptyList());
|
|
||||||
if (plan == null || plan.isEmpty()) return;
|
|
||||||
long delayMs = Math.max(0, ia.clickDelayMs);
|
|
||||||
RunState scheduledRun = CURRENT_RUN.get();
|
|
||||||
boolean first = true;
|
|
||||||
for (Runnable op : plan) {
|
|
||||||
if (!isCurrentRunActive()) break;
|
|
||||||
if (!first && delayMs > 0) Thread.sleep(delayMs);
|
|
||||||
first = false;
|
|
||||||
mc.execute(() -> withRunContext(scheduledRun, () -> {
|
|
||||||
if (PackHideState.isHardLocked()) return;
|
|
||||||
try {
|
|
||||||
op.run();
|
|
||||||
} catch (Throwable t) {
|
|
||||||
AutismClientMessaging.sendPrefixed("\u00a7cError in ItemAction: "
|
|
||||||
+ (t.getMessage() == null ? t.getClass().getSimpleName() : t.getMessage()));
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void runContextMacroAction(autismclient.api.macro.ContextMacroAction action) {
|
|
||||||
if (PackHideState.isHardLocked()) return;
|
|
||||||
if (action == null) return;
|
|
||||||
try {
|
|
||||||
action.run(new ApiExecutionContext(CURRENT_RUN.get()));
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
} catch (Throwable t) {
|
|
||||||
recordAddonActionError(action, "Context action threw " + t.getClass().getSimpleName());
|
|
||||||
AutismClientMessaging.sendPrefixed("\u00a7cAddon action error: "
|
|
||||||
+ (t.getMessage() == null ? t.getClass().getSimpleName() : t.getMessage()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void recordAddonActionError(MacroAction action, String detail) {
|
|
||||||
if (action == null) return;
|
|
||||||
String owner = autismclient.api.macro.MacroActionRegistry.ownerOf(action.getTypeId());
|
|
||||||
if (owner != null && !owner.isBlank()) autismclient.addons.AddonManager.recordRuntimeError(owner, detail);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class ApiExecutionContext implements autismclient.api.macro.MacroExecutionContext {
|
|
||||||
private final RunState run;
|
|
||||||
|
|
||||||
private ApiExecutionContext(RunState run) {
|
|
||||||
this.run = run;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public Minecraft mc() { return Minecraft.getInstance(); }
|
|
||||||
|
|
||||||
@Override public void runOnClientThread(Runnable r) {
|
|
||||||
if (r == null) return;
|
|
||||||
|
|
||||||
Runnable safe = () -> withRunContext(run, () -> {
|
|
||||||
try { r.run(); }
|
|
||||||
catch (Throwable t) { AutismClientMessaging.sendPrefixed("\u00a7cAddon action (client task) error: " + (t.getMessage() == null ? t.getClass().getSimpleName() : t.getMessage())); }
|
|
||||||
});
|
|
||||||
try { MacroExecutor.runOnClientThread(Minecraft.getInstance(), safe); }
|
|
||||||
catch (InterruptedException e) { Thread.currentThread().interrupt(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public <T> T callOnClientThread(java.util.function.Supplier<T> s) {
|
|
||||||
if (s == null) return null;
|
|
||||||
java.util.function.Supplier<T> safe = () -> {
|
|
||||||
AtomicReference<T> value = new AtomicReference<>();
|
|
||||||
withRunContext(run, () -> {
|
|
||||||
try { value.set(s.get()); }
|
|
||||||
catch (Throwable t) { AutismClientMessaging.sendPrefixed("\u00a7cAddon action (client task) error: " + (t.getMessage() == null ? t.getClass().getSimpleName() : t.getMessage())); }
|
|
||||||
});
|
|
||||||
return value.get();
|
|
||||||
};
|
|
||||||
try { return MacroExecutor.callOnClientThread(Minecraft.getInstance(), safe, null); }
|
|
||||||
catch (InterruptedException e) { Thread.currentThread().interrupt(); return null; }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void waitTicks(int ticks) {
|
|
||||||
withRunContext(run, () -> {
|
|
||||||
for (int i = 0; i < ticks && isCurrentRunActive(); i++) {
|
|
||||||
waitForCondition(MacroConditionRegistry.waitForNextTick());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void awaitCondition(CompletableFuture<Void> future) {
|
|
||||||
if (future != null) withRunContext(run, () -> waitForCondition(future));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void awaitCondition(autismclient.api.macro.AddonCondition condition) {
|
|
||||||
if (condition != null) withRunContext(run, () -> waitForCondition(MacroConditionRegistry.await(condition)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public boolean isActive() { return run != null && run.running.get() && !PackHideState.isHardLocked(); }
|
|
||||||
|
|
||||||
@Override public void setStatus(String status) { withRunContext(run, () -> setCurrentStatus(status)); }
|
|
||||||
|
|
||||||
@Override public void sendPacket(net.minecraft.network.protocol.Packet<?> packet) {
|
|
||||||
if (packet == null) return;
|
|
||||||
runOnClientThread(() -> {
|
|
||||||
Minecraft mc = Minecraft.getInstance();
|
|
||||||
if (mc.getConnection() != null) mc.getConnection().send(packet);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public java.util.Optional<MacroValue> variable(String name) {
|
|
||||||
return run == null ? java.util.Optional.empty() : run.variables.get(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void setVariable(String name, MacroValue value) {
|
|
||||||
if (run != null) run.variables.set(name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void removeVariable(String name) {
|
|
||||||
if (run != null) run.variables.remove(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public java.util.Map<String, MacroValue> variables() {
|
|
||||||
return run == null ? java.util.Map.of() : run.variables.snapshot();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public MacroTemplate.Resolution resolveTemplate(String template) {
|
|
||||||
return MacroTemplate.resolve(template, run == null ? null : run.variables, Minecraft.getInstance());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void runUseItemPhaseAction(Minecraft mc, UseItemPhaseAction action) throws InterruptedException {
|
|
||||||
int times = action.repeatTimes();
|
|
||||||
for (int i = 0; i < times && isCurrentRunActive(); i++) {
|
|
||||||
|
|
||||||
runOnClientThread(mc, () -> {
|
|
||||||
try { action.sendUsePacket(mc); }
|
|
||||||
catch (Exception e) { AutismClientMessaging.sendPrefixed("\u00a7cError in Use phase: " + e.getMessage()); }
|
|
||||||
});
|
|
||||||
|
|
||||||
final boolean[] gateInstalled = { false };
|
|
||||||
if (action.shouldGate()) {
|
|
||||||
runOnClientThread(mc, () -> {
|
|
||||||
try { gateInstalled[0] = action.installGate(mc); }
|
|
||||||
catch (Exception e) { AutismClientMessaging.sendPrefixed("\u00a7cError in Use gate: " + e.getMessage()); }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
|
|
||||||
for (int t = 0; t < action.holdTicks && isCurrentRunActive(); t++) {
|
|
||||||
CompletableFuture<Void> tf = MacroConditionRegistry.waitForNextTick();
|
|
||||||
waitForCondition(tf);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (gateInstalled[0]) {
|
|
||||||
final boolean wasOnThread = mc.isSameThread();
|
|
||||||
if (wasOnThread) {
|
|
||||||
action.removeGate();
|
|
||||||
} else {
|
|
||||||
runOnClientThread(mc, action::removeGate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!isCurrentRunActive()) break;
|
|
||||||
|
|
||||||
runOnClientThread(mc, () -> {
|
|
||||||
try { action.finishRelease(mc); }
|
|
||||||
catch (Exception e) { AutismClientMessaging.sendPrefixed("\u00a7cError in Use release: " + e.getMessage()); }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void runClickActionBurst(Minecraft mc, ClickAction action) throws InterruptedException {
|
|
||||||
int times = Math.max(1, action.clickCount);
|
|
||||||
|
|
||||||
runOnClientThread(mc, () -> {
|
|
||||||
for (int c = 0; c < times && isCurrentRunActive(); c++) {
|
|
||||||
try {
|
|
||||||
action.execute(mc);
|
|
||||||
} catch (Exception e) {
|
|
||||||
AutismClientMessaging.sendPrefixed("\u00a7cError in Click: " + e.getMessage());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, action.isTickAligned());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isInstantInventoryAction(MacroAction action) {
|
|
||||||
if (action instanceof ItemAction
|
|
||||||
|| action instanceof DropAction
|
|
||||||
|| action instanceof SwapSlotsAction
|
|
||||||
|| action instanceof ClickAction
|
|
||||||
|| action instanceof XCarryAction) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return action instanceof StoreItemAction storeItemAction && !storeItemAction.persistent;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void runStoreItemAction(Minecraft mc, StoreItemAction action) throws InterruptedException {
|
|
||||||
if (action == null) return;
|
|
||||||
int delayTicks = StoreItemAction.clampDelayTicks(action.delayTicks);
|
|
||||||
if (delayTicks <= 0) {
|
|
||||||
runOnClientThread(mc, () -> action.doTransfer(mc));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Integer> slots = callOnClientThread(mc, () -> action.collectTransferSlots(mc), List.of());
|
|
||||||
for (int i = 0; i < slots.size() && isCurrentRunActive(); i++) {
|
|
||||||
AutismInventoryClickHelper.click(mc, slots.get(i), 0, net.minecraft.world.inventory.ContainerInput.QUICK_MOVE);
|
|
||||||
if (i + 1 < slots.size()) waitTicks(delayTicks);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (action.closeAfter && !action.persistent) {
|
|
||||||
runOnClientThread(mc, () -> AutismGuiActions.closeCurrentScreen(mc, action.closeSendPkt, false));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void waitTicks(int ticks) {
|
|
||||||
for (int i = 0; i < ticks && isCurrentRunActive(); i++) {
|
|
||||||
CompletableFuture<Void> tickFuture = MacroConditionRegistry.waitForNextTick();
|
|
||||||
waitForCondition(tickFuture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void runUseItemAction(Minecraft mc, UseItemAction action) throws InterruptedException {
|
|
||||||
if (action == null) return;
|
|
||||||
|
|
||||||
boolean sneaking = action.sneak;
|
|
||||||
try {
|
|
||||||
if (action.useMode == UseItemAction.UseMode.CUSTOM_HOLD) {
|
|
||||||
runOnClientThread(mc, () -> {
|
|
||||||
try {
|
|
||||||
if (sneaking) autismclient.util.AutismMacroSneak.forceSneak(mc, true);
|
|
||||||
action.execute(mc);
|
|
||||||
}
|
|
||||||
catch (Exception e) { AutismClientMessaging.sendPrefixed("\u00a7cError in UseItem: " + e.getMessage()); }
|
|
||||||
}, action.isTickAligned());
|
|
||||||
if (action.holdTicks > 0) {
|
|
||||||
waitTicks(action.holdTicks);
|
|
||||||
if (!isCurrentRunActive()) return;
|
|
||||||
runOnClientThread(mc, () -> {
|
|
||||||
try { action.sendRelease(mc); }
|
|
||||||
catch (Exception e) { AutismClientMessaging.sendPrefixed("\u00a7cError in UseItem release: " + e.getMessage()); }
|
|
||||||
}, action.isTickAligned());
|
|
||||||
if (action.waitForFinish) waitForUseItemFinish(mc, action.holdTicks + 8);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int times = Math.max(1, action.useCount);
|
|
||||||
for (int i = 0; i < times && isCurrentRunActive(); i++) {
|
|
||||||
runOnClientThread(mc, () -> {
|
|
||||||
try {
|
|
||||||
if (sneaking) autismclient.util.AutismMacroSneak.forceSneak(mc, true);
|
|
||||||
action.execute(mc);
|
|
||||||
}
|
|
||||||
catch (Exception e) { AutismClientMessaging.sendPrefixed("\u00a7cError in UseItem: " + e.getMessage()); }
|
|
||||||
}, action.isTickAligned());
|
|
||||||
if (action.waitForFinish) waitForUseItemFinish(mc, 0);
|
|
||||||
if (i + 1 < times && isCurrentRunActive()) waitOneTick();
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (sneaking) mc.execute(() -> autismclient.util.AutismMacroSneak.forceSneak(mc, false));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void runContainerClickSequenceAction(Minecraft mc, ContainerClickSequenceAction action) throws InterruptedException {
|
|
||||||
if (action == null) return;
|
|
||||||
List<Integer> slots = action.resolvedSlots();
|
|
||||||
int repeats = Math.max(1, action.repeatCount);
|
|
||||||
int delay = Math.max(0, action.delayTicks);
|
|
||||||
int total = repeats * slots.size();
|
|
||||||
int sent = 0;
|
|
||||||
for (int repeat = 0; repeat < repeats && isCurrentRunActive(); repeat++) {
|
|
||||||
for (int slot : slots) {
|
|
||||||
if (!isCurrentRunActive()) return;
|
|
||||||
runOnClientThread(mc, () -> action.executeClick(mc, slot));
|
|
||||||
sent++;
|
|
||||||
if (delay > 0 && sent < total) waitTicks(delay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void runPacketBurstAction(Minecraft mc, PacketBurstAction action) {
|
|
||||||
if (action == null || mc == null || mc.getConnection() == null) return;
|
|
||||||
if (action.flushBefore) AutismSharedState.get().flushDelayedPackets(mc.getConnection());
|
|
||||||
int total = action.effectiveCount();
|
|
||||||
int delay = Math.max(0, action.delayTicks);
|
|
||||||
for (int i = 0; i < total && isCurrentRunActive(); i++) {
|
|
||||||
action.sendOne(mc);
|
|
||||||
if (delay > 0 && i + 1 < total) waitTicks(delay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void waitForUseItemFinish(Minecraft mc, int fallbackTicks) throws InterruptedException {
|
|
||||||
if (mc == null || !isCurrentRunActive()) return;
|
|
||||||
|
|
||||||
if (!Boolean.TRUE.equals(callOnClientThread(mc,
|
|
||||||
() -> mc.player != null && mc.player.isUsingItem(),
|
|
||||||
Boolean.FALSE))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int remaining = callOnClientThread(mc,
|
|
||||||
() -> mc.player == null ? 0 : Math.max(0, mc.player.getUseItemRemainingTicks()),
|
|
||||||
0);
|
|
||||||
int maxTicks = Math.max(8, remaining > 0 ? remaining + 8 : fallbackTicks + 8);
|
|
||||||
maxTicks = Math.min(maxTicks, 72000);
|
|
||||||
for (int i = 0; i < maxTicks && isCurrentRunActive(); i++) {
|
|
||||||
if (!Boolean.TRUE.equals(callOnClientThread(mc,
|
|
||||||
() -> mc.player != null && mc.player.isUsingItem(),
|
|
||||||
Boolean.FALSE))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
CompletableFuture<Void> tickFuture = MacroConditionRegistry.waitForNextTick();
|
|
||||||
waitForCondition(tickFuture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void runXCarryClickPutIn(Minecraft mc, XCarryAction xsa) throws InterruptedException {
|
private static void runXCarryClickPutIn(Minecraft mc, XCarryAction xsa) throws InterruptedException {
|
||||||
if (mc == null || mc.player == null || mc.gameMode == null) return;
|
if (mc == null || mc.player == null || mc.gameMode == null) return;
|
||||||
|
|
@ -4530,7 +4027,7 @@ public class MacroExecutor {
|
||||||
if (!autismclient.util.AutismMacroSneak.isPacket(mode)) applyAggregateSneakState(mc);
|
if (!autismclient.util.AutismMacroSneak.isPacket(mode)) applyAggregateSneakState(mc);
|
||||||
}
|
}
|
||||||
|
|
||||||
private 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;
|
||||||
RunState scheduledRun = CURRENT_RUN.get();
|
RunState scheduledRun = CURRENT_RUN.get();
|
||||||
Runnable contextual = () -> withRunContext(scheduledRun, runnable);
|
Runnable contextual = () -> withRunContext(scheduledRun, runnable);
|
||||||
|
|
@ -4553,7 +4050,7 @@ public class MacroExecutor {
|
||||||
if (!latch.await(2000, TimeUnit.MILLISECONDS)) pending.set(false);
|
if (!latch.await(2000, TimeUnit.MILLISECONDS)) pending.set(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void runOnClientThread(Minecraft mc, Runnable runnable, boolean tickAligned) throws InterruptedException {
|
static void runOnClientThread(Minecraft mc, Runnable runnable, boolean tickAligned) throws InterruptedException {
|
||||||
if (tickAligned) runOnClientTick(mc, runnable);
|
if (tickAligned) runOnClientTick(mc, runnable);
|
||||||
else runOnClientThread(mc, runnable);
|
else runOnClientThread(mc, runnable);
|
||||||
}
|
}
|
||||||
|
|
@ -4571,7 +4068,7 @@ public class MacroExecutor {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private 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;
|
||||||
RunState scheduledRun = CURRENT_RUN.get();
|
RunState scheduledRun = CURRENT_RUN.get();
|
||||||
Runnable contextual = () -> withRunContext(scheduledRun, runnable);
|
Runnable contextual = () -> withRunContext(scheduledRun, runnable);
|
||||||
|
|
@ -4684,7 +4181,7 @@ public class MacroExecutor {
|
||||||
|
|
||||||
if (!action.interact) {
|
if (!action.interact) {
|
||||||
|
|
||||||
runMacroActionOnClientThread(mc, action, "Place");
|
MacroActionRunner.runMacroActionOnClientThread(mc, action, "Place");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4698,7 +4195,7 @@ public class MacroExecutor {
|
||||||
|
|
||||||
runOnClientThread(mc, () -> sendBlockInteract(mc, placePos, face), action.isTickAligned());
|
runOnClientThread(mc, () -> sendBlockInteract(mc, placePos, face), action.isTickAligned());
|
||||||
if (ns > 0) java.util.concurrent.locks.LockSupport.parkNanos(ns);
|
if (ns > 0) java.util.concurrent.locks.LockSupport.parkNanos(ns);
|
||||||
runMacroActionOnClientThread(mc, action, "Place");
|
MacroActionRunner.runMacroActionOnClientThread(mc, action, "Place");
|
||||||
} else if (t == InteractTiming.WITH) {
|
} else if (t == InteractTiming.WITH) {
|
||||||
|
|
||||||
runOnClientThread(mc, () -> {
|
runOnClientThread(mc, () -> {
|
||||||
|
|
@ -4706,12 +4203,12 @@ public class MacroExecutor {
|
||||||
sendBlockInteract(mc, placePos, face);
|
sendBlockInteract(mc, placePos, face);
|
||||||
}, action.isTickAligned());
|
}, action.isTickAligned());
|
||||||
} else if (t == InteractTiming.AFTER_PLUS) {
|
} else if (t == InteractTiming.AFTER_PLUS) {
|
||||||
runMacroActionOnClientThread(mc, action, "Place");
|
MacroActionRunner.runMacroActionOnClientThread(mc, action, "Place");
|
||||||
waitOneTick();
|
waitOneTick();
|
||||||
runOnClientThread(mc, () -> sendBlockInteract(mc, placePos, face), action.isTickAligned());
|
runOnClientThread(mc, () -> sendBlockInteract(mc, placePos, face), action.isTickAligned());
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
runMacroActionOnClientThread(mc, action, "Place");
|
MacroActionRunner.runMacroActionOnClientThread(mc, action, "Place");
|
||||||
if (ns > 0) java.util.concurrent.locks.LockSupport.parkNanos(ns);
|
if (ns > 0) java.util.concurrent.locks.LockSupport.parkNanos(ns);
|
||||||
runOnClientThread(mc, () -> sendBlockInteract(mc, placePos, face), action.isTickAligned());
|
runOnClientThread(mc, () -> sendBlockInteract(mc, placePos, face), action.isTickAligned());
|
||||||
}
|
}
|
||||||
|
|
@ -5935,13 +5432,13 @@ public class MacroExecutor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static java.util.List<Packet<?>> preGeneratePackets(AutismMacro macro, int startIdx, int count) {
|
static java.util.List<Packet<?>> preGeneratePackets(AutismMacro macro, int startIdx, int count) {
|
||||||
java.util.List<Packet<?>> result = new java.util.ArrayList<>();
|
java.util.List<Packet<?>> result = new java.util.ArrayList<>();
|
||||||
int maxIdx = count < 0 ? macro.actions.size() : Math.min(startIdx + count, macro.actions.size());
|
int maxIdx = count < 0 ? macro.actions.size() : Math.min(startIdx + count, macro.actions.size());
|
||||||
return preGeneratePackets(macro, startIdx, count, maxIdx);
|
return preGeneratePackets(macro, startIdx, count, maxIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static java.util.List<Packet<?>> preGeneratePackets(AutismMacro macro, int startIdx, int count, int endIdx) {
|
static java.util.List<Packet<?>> preGeneratePackets(AutismMacro macro, int startIdx, int count, int endIdx) {
|
||||||
java.util.List<Packet<?>> result = new java.util.ArrayList<>();
|
java.util.List<Packet<?>> result = new java.util.ArrayList<>();
|
||||||
int maxIdx = Math.min(endIdx, count < 0 ? macro.actions.size() : Math.min(startIdx + count, macro.actions.size()));
|
int maxIdx = Math.min(endIdx, count < 0 ? macro.actions.size() : Math.min(startIdx + count, macro.actions.size()));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ final class MacroPrearm {
|
||||||
MacroAction next = actions.get(nextIndex);
|
MacroAction next = actions.get(nextIndex);
|
||||||
if (next == null || !next.isEnabled() || !next.listensDuringPreviousAction()) return;
|
if (next == null || !next.isEnabled() || !next.listensDuringPreviousAction()) return;
|
||||||
if (!MacroDynamicBindings.apply(next, mc)) return;
|
if (!MacroDynamicBindings.apply(next, mc)) return;
|
||||||
if (!MacroExecutor.dynamicTextInputsAvailable(next, mc)) return;
|
if (!MacroActionRunner.dynamicTextInputsAvailable(next, mc)) return;
|
||||||
if (!isWaitConditionAction(next)) return;
|
if (!isWaitConditionAction(next)) return;
|
||||||
synchronized (run.prearmedWaits) {
|
synchronized (run.prearmedWaits) {
|
||||||
if (run.prearmedWaits.containsKey(next)) return;
|
if (run.prearmedWaits.containsKey(next)) return;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue