mirror of
https://github.com/AutismDevelopment/Autism-Client.git
synced 2026-10-28 19:39:48 +00:00
Refactor: extract MacroBreak from MacroExecutor (upstream #4)
Move 26 insta-break/break-engine methods verbatim into MacroBreak. Shared members referenced as MacroExecutor.xxx (mechanical qualification only); dispatch call sites of runInstaBreakAction, runBreakAction and sendBlockInteract re-pointed. All bodies verified identical against HEAD modulo that qualification.
This commit is contained in:
parent
c78be74b37
commit
79c1e81cc6
2 changed files with 559 additions and 536 deletions
548
src/main/java/autismclient/util/macro/MacroBreak.java
Normal file
548
src/main/java/autismclient/util/macro/MacroBreak.java
Normal file
|
|
@ -0,0 +1,548 @@
|
|||
package autismclient.util.macro;
|
||||
|
||||
import autismclient.mixin.accessor.AutismMultiPlayerGameModeAccessor;
|
||||
import autismclient.modules.AutismModule;
|
||||
import autismclient.util.AutismAutoTool;
|
||||
import autismclient.util.AutismClientMessaging;
|
||||
import autismclient.util.AutismInstaBreakRenderer;
|
||||
import autismclient.util.AutismInventoryHelper;
|
||||
import autismclient.util.AutismSharedState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket;
|
||||
import net.minecraft.tags.ItemTags;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
final class MacroBreak {
|
||||
private MacroBreak() {
|
||||
}
|
||||
public static void runInstaBreakAction(Minecraft mc, InstaBreakAction action) throws InterruptedException {
|
||||
if (mc == null || mc.player == null || mc.level == null || mc.getConnection() == null || mc.gameMode == null) {
|
||||
AutismClientMessaging.sendPrefixed("\u00a7cInstaBreak: missing world or connection");
|
||||
return;
|
||||
}
|
||||
|
||||
BlockPos target = action.blockPos == null ? BlockPos.ZERO : action.blockPos;
|
||||
Direction direction = action.direction == null ? Direction.UP : action.direction;
|
||||
int delayTicks = Math.max(0, action.delayTicks);
|
||||
int targetTimes = Math.max(0, action.times);
|
||||
int completed = 0;
|
||||
boolean wasSolid = !isInstaBreakAir(mc, target);
|
||||
|
||||
if (!ensureInstaBreakPickaxe(mc, action)) return;
|
||||
|
||||
AutismInstaBreakRenderer.setTarget(target);
|
||||
try {
|
||||
long lastAttemptTick = AutismSharedState.get().getClientTickCounter() - (delayTicks + 1L);
|
||||
long lastSneakTick = Long.MIN_VALUE;
|
||||
while (MacroExecutor.isCurrentRunActive() && isActionStillInCurrentMacro(action)) {
|
||||
|
||||
if (action.sneak) {
|
||||
long sneakTick = AutismSharedState.get().getClientTickCounter();
|
||||
if (sneakTick != lastSneakTick) {
|
||||
lastSneakTick = sneakTick;
|
||||
final String sneakMode = action.sneakMode;
|
||||
MacroExecutor.runOnClientThread(mc, () -> holdMacroSneak(mc, sneakMode), action.isTickAligned());
|
||||
}
|
||||
}
|
||||
|
||||
boolean isAir = isInstaBreakAir(mc, target);
|
||||
if (wasSolid && isAir) {
|
||||
completed++;
|
||||
MacroExecutor.setCurrentStatus("InstaBreak " + completed + "/" + (targetTimes == 0 ? "\u221e" : targetTimes));
|
||||
if (targetTimes > 0 && completed >= targetTimes) return;
|
||||
wasSolid = false;
|
||||
} else if (!isAir) {
|
||||
wasSolid = true;
|
||||
}
|
||||
|
||||
if (!isAir) {
|
||||
long currentTick = AutismSharedState.get().getClientTickCounter();
|
||||
if (currentTick != lastAttemptTick && (currentTick - lastAttemptTick) >= delayTicks) {
|
||||
lastAttemptTick = currentTick;
|
||||
if (!ensureInstaBreakPickaxe(mc, action)) return;
|
||||
if (action.interact) {
|
||||
|
||||
InteractTiming t = action.interactTiming;
|
||||
boolean interactFirst = t == InteractTiming.BEFORE || t == InteractTiming.WITH
|
||||
|| (t == InteractTiming.CUSTOM && action.interactCustomMs < 0);
|
||||
long ns = t == InteractTiming.CUSTOM
|
||||
? Math.abs((long) action.interactCustomMs) * 1_000_000L : 0L;
|
||||
if (interactFirst) {
|
||||
MacroExecutor.runOnClientThread(mc, () -> sendBlockInteract(mc, target, direction), action.isTickAligned());
|
||||
if (ns > 0) java.util.concurrent.locks.LockSupport.parkNanos(ns);
|
||||
sendInstaBreakAttempt(mc, target, direction, action.isTickAligned());
|
||||
} else if (t == InteractTiming.AFTER_PLUS) {
|
||||
sendInstaBreakAttempt(mc, target, direction, action.isTickAligned());
|
||||
MacroExecutor.waitOneTick();
|
||||
MacroExecutor.runOnClientThread(mc, () -> sendBlockInteract(mc, target, direction), action.isTickAligned());
|
||||
} else {
|
||||
sendInstaBreakAttempt(mc, target, direction, action.isTickAligned());
|
||||
if (ns > 0) java.util.concurrent.locks.LockSupport.parkNanos(ns);
|
||||
MacroExecutor.runOnClientThread(mc, () -> sendBlockInteract(mc, target, direction), action.isTickAligned());
|
||||
}
|
||||
} else {
|
||||
sendInstaBreakAttempt(mc, target, direction, action.isTickAligned());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MacroExecutor.setCurrentStatus("InstaBreak " + target.getX() + "," + target.getY() + "," + target.getZ()
|
||||
+ " " + completed + "/" + (targetTimes == 0 ? "\u221e" : targetTimes));
|
||||
|
||||
Thread.sleep(1);
|
||||
}
|
||||
} finally {
|
||||
if (action.sneak) {
|
||||
final String sneakMode = action.sneakMode;
|
||||
try {
|
||||
MacroExecutor.runOnClientThread(mc, () -> releaseMacroSneak(mc, sneakMode));
|
||||
} catch (InterruptedException interrupted) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
AutismInstaBreakRenderer.clearTarget(target);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isInstaBreakAir(Minecraft mc, BlockPos pos) {
|
||||
|
||||
return mc.level == null || mc.level.isOutsideBuildHeight(pos) || mc.level.getBlockState(pos).isAir();
|
||||
}
|
||||
|
||||
private static boolean isActionStillInCurrentMacro(MacroAction action) {
|
||||
MacroExecutor.RunState run = MacroExecutor.CURRENT_RUN.get();
|
||||
if (run == null || run.macro == null || run.macro.actions == null) return true;
|
||||
return run.macro.actions.contains(action);
|
||||
}
|
||||
|
||||
private static boolean ensureInstaBreakPickaxe(Minecraft mc, InstaBreakAction action) throws InterruptedException {
|
||||
|
||||
return MacroExecutor.callOnClientThread(mc, () -> {
|
||||
if (mc.player == null) return false;
|
||||
if (mc.player.getMainHandItem().is(ItemTags.PICKAXES)) return true;
|
||||
if (!action.autoPickaxe) return false;
|
||||
|
||||
int preferred = Math.max(0, Math.min(8, mc.player.getInventory().getSelectedSlot()));
|
||||
for (int slot = 0; slot < 9; slot++) {
|
||||
if (mc.player.getInventory().getItem(slot).is(ItemTags.PICKAXES)) {
|
||||
AutismInventoryHelper.selectHotbarSlot(mc, slot);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (int slot = 9; slot < 36; slot++) {
|
||||
if (mc.player.getInventory().getItem(slot).is(ItemTags.PICKAXES)) {
|
||||
if (!AutismInventoryHelper.swapInventorySlots(mc, slot, preferred)) return false;
|
||||
AutismInventoryHelper.selectHotbarSlot(mc, preferred);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}, false, action.isTickAligned());
|
||||
}
|
||||
|
||||
private static void sendInstaBreakAttempt(Minecraft mc, BlockPos pos, Direction direction, boolean tickAligned) throws InterruptedException {
|
||||
MacroExecutor.runOnClientThread(mc, () -> {
|
||||
if (mc.player == null || mc.level == null || mc.gameMode == null || mc.getConnection() == null) return;
|
||||
BlockPos blockPos = pos.immutable();
|
||||
Direction dir = direction == null ? Direction.UP : direction;
|
||||
|
||||
if (mc.gameMode instanceof AutismMultiPlayerGameModeAccessor accessor) {
|
||||
accessor.autism$startPrediction(mc.level, sequence -> new ServerboundPlayerActionPacket(
|
||||
ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK, blockPos, dir, sequence));
|
||||
accessor.autism$startPrediction(mc.level, sequence -> new ServerboundPlayerActionPacket(
|
||||
ServerboundPlayerActionPacket.Action.STOP_DESTROY_BLOCK, blockPos, dir, sequence));
|
||||
} else {
|
||||
|
||||
mc.getConnection().send(new ServerboundPlayerActionPacket(
|
||||
ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK, blockPos, dir));
|
||||
mc.getConnection().send(new ServerboundPlayerActionPacket(
|
||||
ServerboundPlayerActionPacket.Action.STOP_DESTROY_BLOCK, blockPos, dir));
|
||||
}
|
||||
|
||||
mc.player.swing(InteractionHand.MAIN_HAND);
|
||||
}, tickAligned);
|
||||
}
|
||||
|
||||
public static void runBreakAction(Minecraft mc, BreakAction action) throws InterruptedException {
|
||||
if (mc == null || mc.player == null || mc.level == null || mc.getConnection() == null || mc.gameMode == null) {
|
||||
AutismClientMessaging.sendPrefixed("\u00a7cBreak: missing world or connection");
|
||||
return;
|
||||
}
|
||||
|
||||
final BlockPos target = action.blockPos == null ? BlockPos.ZERO : action.blockPos;
|
||||
final Direction direction = action.direction == null ? Direction.UP : action.direction;
|
||||
int startDelay = Math.max(0, action.delayTicks);
|
||||
int targetTimes = Math.max(0, action.times);
|
||||
int completed = 0;
|
||||
|
||||
if (startDelay > 0) waitBreakClientTicks(startDelay);
|
||||
|
||||
final boolean[] started = { false };
|
||||
final boolean useNextSteps = action.interact && action.runNextSteps;
|
||||
final boolean[] nextStepsFired = { false };
|
||||
final boolean[] missingNextStepsWarned = { false };
|
||||
AutismInstaBreakRenderer.setTarget(target);
|
||||
long lastTick = -1L;
|
||||
try {
|
||||
while (MacroExecutor.isCurrentRunActive() && isActionStillInCurrentMacro(action)) {
|
||||
long now = AutismSharedState.get().getClientTickCounter();
|
||||
if (now == lastTick) {
|
||||
Thread.sleep(1);
|
||||
continue;
|
||||
}
|
||||
lastTick = now;
|
||||
|
||||
int result;
|
||||
if (!started[0]) {
|
||||
result = useNextSteps
|
||||
? startBreakWithNextSteps(mc, action, target, direction, started, nextStepsFired, missingNextStepsWarned)
|
||||
: MacroExecutor.callOnClientThread(mc, () -> startBreakOnClient(mc, action, target, direction, started), -1, action.isTickAligned());
|
||||
} else if (action.interact && action.interactTiming == InteractTiming.CUSTOM) {
|
||||
result = useNextSteps
|
||||
? breakCustomTickWithNextSteps(mc, action, target, direction, nextStepsFired, missingNextStepsWarned)
|
||||
: breakCustomTick(mc, action, target, direction);
|
||||
} else {
|
||||
result = useNextSteps
|
||||
? breakContinueWithNextSteps(mc, action, target, direction, nextStepsFired, missingNextStepsWarned)
|
||||
: MacroExecutor.callOnClientThread(mc, () -> breakContinueOnClient(mc, action, target, direction), -1, action.isTickAligned());
|
||||
}
|
||||
|
||||
if (result < 0) {
|
||||
return;
|
||||
} else if (result == 1) {
|
||||
boolean completedStartedBreak = started[0];
|
||||
if (useNextSteps && completedStartedBreak) {
|
||||
runBreakNextStepsAfterCompletion(mc, action, nextStepsFired, missingNextStepsWarned);
|
||||
} else if (action.interact && action.interactTiming == InteractTiming.AFTER_PLUS) {
|
||||
MacroExecutor.waitOneTick();
|
||||
MacroExecutor.runOnClientThread(mc, () -> sendBlockInteract(mc, target, direction), action.isTickAligned());
|
||||
}
|
||||
completed++;
|
||||
MacroExecutor.setCurrentStatus("Break " + completed + "/" + (targetTimes == 0 ? "\u221e" : targetTimes));
|
||||
if (targetTimes > 0 && completed >= targetTimes) return;
|
||||
started[0] = false;
|
||||
nextStepsFired[0] = false;
|
||||
waitForBreakSolid(mc, target);
|
||||
} else {
|
||||
MacroExecutor.setCurrentStatus("Break " + target.getX() + "," + target.getY() + "," + target.getZ()
|
||||
+ " " + completed + "/" + (targetTimes == 0 ? "\u221e" : targetTimes));
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
final boolean wasMining = started[0];
|
||||
MacroExecutor.runOnClientThread(mc, () -> {
|
||||
if (wasMining && mc.gameMode != null && mc.gameMode.isDestroying()) mc.gameMode.stopDestroyBlock();
|
||||
if (action.sneak) releaseMacroSneak(mc, action.sneakMode);
|
||||
}, action.isTickAligned());
|
||||
AutismInstaBreakRenderer.clearTarget(target);
|
||||
}
|
||||
}
|
||||
|
||||
private static int startBreakWithNextSteps(Minecraft mc, BreakAction action, BlockPos pos, Direction dir,
|
||||
boolean[] started, boolean[] nextStepsFired,
|
||||
boolean[] missingNextStepsWarned) throws InterruptedException {
|
||||
MacroExecutor.BreakStartPlan plan = MacroExecutor.callOnClientThread(mc, () -> prepareBreakStartOnClient(mc, action, pos), new MacroExecutor.BreakStartPlan(-1, false, false));
|
||||
if (plan.result() != 0) return plan.result();
|
||||
|
||||
if (plan.instant() && plan.interactFirst()) {
|
||||
runBreakNextStepsOnce(mc, action, nextStepsFired, missingNextStepsWarned);
|
||||
if (!MacroExecutor.isCurrentRunActive()) return -1;
|
||||
}
|
||||
|
||||
int result = MacroExecutor.callOnClientThread(mc, () -> startPreparedBreakOnClient(mc, action, pos, dir, started), -1, action.isTickAligned());
|
||||
return result;
|
||||
}
|
||||
|
||||
private static MacroExecutor.BreakStartPlan prepareBreakStartOnClient(Minecraft mc, BreakAction action, BlockPos pos) {
|
||||
if (mc.level == null || mc.gameMode == null || mc.player == null || mc.getConnection() == null) {
|
||||
return new MacroExecutor.BreakStartPlan(-1, false, false);
|
||||
}
|
||||
if (mc.level.isOutsideBuildHeight(pos)) return new MacroExecutor.BreakStartPlan(1, false, false);
|
||||
BlockState state = mc.level.getBlockState(pos);
|
||||
if (state.isAir()) return new MacroExecutor.BreakStartPlan(1, false, false);
|
||||
|
||||
if (action.sneak) holdMacroSneak(mc, action.sneakMode);
|
||||
if (action.autoTool) {
|
||||
AutismAutoTool.equipBestTool(mc, state, action.considerInventory, true);
|
||||
state = mc.level.getBlockState(pos);
|
||||
if (state.isAir()) return new MacroExecutor.BreakStartPlan(1, false, false);
|
||||
}
|
||||
|
||||
float startDelta = state.getDestroyProgress(mc.player, mc.player.level(), pos);
|
||||
boolean instant = startDelta >= 1.0f;
|
||||
boolean interactFirst = action.interact && (action.interactTiming == InteractTiming.BEFORE
|
||||
|| action.interactTiming == InteractTiming.WITH
|
||||
|| (action.interactTiming == InteractTiming.CUSTOM && action.interactCustomMs < 0));
|
||||
return new MacroExecutor.BreakStartPlan(0, instant, interactFirst);
|
||||
}
|
||||
|
||||
private static int startPreparedBreakOnClient(Minecraft mc, BreakAction action, BlockPos pos, Direction dir, boolean[] started) {
|
||||
if (mc.level == null || mc.gameMode == null || mc.player == null || mc.getConnection() == null) return -1;
|
||||
if (mc.level.isOutsideBuildHeight(pos) || mc.level.getBlockState(pos).isAir()) return 1;
|
||||
if (action.sneak) holdMacroSneak(mc, action.sneakMode);
|
||||
mc.gameMode.startDestroyBlock(pos, dir);
|
||||
mc.player.swing(InteractionHand.MAIN_HAND);
|
||||
started[0] = true;
|
||||
return mc.level.getBlockState(pos).isAir() ? 1 : 0;
|
||||
}
|
||||
|
||||
private static int startBreakOnClient(Minecraft mc, BreakAction action, BlockPos pos, Direction dir, boolean[] started) {
|
||||
if (mc.level == null || mc.gameMode == null || mc.player == null || mc.getConnection() == null) return -1;
|
||||
BlockState state = mc.level.getBlockState(pos);
|
||||
if (state.isAir() || mc.level.isOutsideBuildHeight(pos)) return 1;
|
||||
|
||||
if (action.sneak) holdMacroSneak(mc, action.sneakMode);
|
||||
if (action.autoTool) {
|
||||
AutismAutoTool.equipBestTool(mc, state, action.considerInventory, true);
|
||||
state = mc.level.getBlockState(pos);
|
||||
}
|
||||
|
||||
float startDelta = state.getDestroyProgress(mc.player, mc.player.level(), pos);
|
||||
boolean instant = startDelta >= 1.0f;
|
||||
boolean interactFirst = action.interact && (action.interactTiming == InteractTiming.BEFORE
|
||||
|| action.interactTiming == InteractTiming.WITH
|
||||
|| (action.interactTiming == InteractTiming.CUSTOM && action.interactCustomMs < 0));
|
||||
if (instant && interactFirst) sendBlockInteract(mc, pos, dir);
|
||||
mc.gameMode.startDestroyBlock(pos, dir);
|
||||
mc.player.swing(InteractionHand.MAIN_HAND);
|
||||
started[0] = true;
|
||||
if (instant && action.interact && !interactFirst && action.interactTiming != InteractTiming.AFTER_PLUS) sendBlockInteract(mc, pos, dir);
|
||||
return mc.level.getBlockState(pos).isAir() ? 1 : 0;
|
||||
}
|
||||
|
||||
private static int breakContinueWithNextSteps(Minecraft mc, BreakAction action, BlockPos pos, Direction dir,
|
||||
boolean[] nextStepsFired,
|
||||
boolean[] missingNextStepsWarned) throws InterruptedException {
|
||||
MacroExecutor.BreakContinuePlan plan = MacroExecutor.callOnClientThread(mc, () -> inspectBreakContinueOnClient(mc, action, pos), new MacroExecutor.BreakContinuePlan(-1, false, false));
|
||||
if (plan.result() != 0) return plan.result();
|
||||
|
||||
InteractTiming timing = action.interactTiming;
|
||||
if (timing == InteractTiming.BEFORE && plan.breaksNextTick()) {
|
||||
runBreakNextStepsOnce(mc, action, nextStepsFired, missingNextStepsWarned);
|
||||
if (!MacroExecutor.isCurrentRunActive()) return -1;
|
||||
}
|
||||
if (timing == InteractTiming.WITH && plan.breaksThisTick()) {
|
||||
runBreakNextStepsOnce(mc, action, nextStepsFired, missingNextStepsWarned);
|
||||
if (!MacroExecutor.isCurrentRunActive()) return -1;
|
||||
}
|
||||
|
||||
int result = MacroExecutor.callOnClientThread(mc, () -> continueBreakOnClient(mc, action, pos, dir), -1, action.isTickAligned());
|
||||
return result;
|
||||
}
|
||||
|
||||
private static MacroExecutor.BreakContinuePlan inspectBreakContinueOnClient(Minecraft mc, BreakAction action, BlockPos pos) {
|
||||
if (mc.level == null || mc.gameMode == null || mc.player == null || mc.getConnection() == null) {
|
||||
return new MacroExecutor.BreakContinuePlan(-1, false, false);
|
||||
}
|
||||
BlockState state = mc.level.getBlockState(pos);
|
||||
if (state.isAir()) return new MacroExecutor.BreakContinuePlan(1, false, false);
|
||||
if (action.sneak) holdMacroSneak(mc, action.sneakMode);
|
||||
|
||||
boolean breaksThisTick = willBreakThisTick(mc, pos, state);
|
||||
boolean breaksNextTick = !breaksThisTick && willBreakNextTick(mc, pos, state);
|
||||
return new MacroExecutor.BreakContinuePlan(0, breaksThisTick, breaksNextTick);
|
||||
}
|
||||
|
||||
private static int continueBreakOnClient(Minecraft mc, BreakAction action, BlockPos pos, Direction dir) {
|
||||
if (mc.level == null || mc.gameMode == null || mc.player == null || mc.getConnection() == null) return -1;
|
||||
if (mc.level.getBlockState(pos).isAir()) return 1;
|
||||
if (action.sneak) holdMacroSneak(mc, action.sneakMode);
|
||||
mc.gameMode.continueDestroyBlock(pos, dir);
|
||||
mc.player.swing(InteractionHand.MAIN_HAND);
|
||||
return mc.level.getBlockState(pos).isAir() ? 1 : 0;
|
||||
}
|
||||
|
||||
private static int breakContinueOnClient(Minecraft mc, BreakAction action, BlockPos pos, Direction dir) {
|
||||
if (mc.level == null || mc.gameMode == null || mc.player == null || mc.getConnection() == null) return -1;
|
||||
BlockState state = mc.level.getBlockState(pos);
|
||||
if (state.isAir()) return 1;
|
||||
if (action.sneak) holdMacroSneak(mc, action.sneakMode);
|
||||
|
||||
boolean breaksThisTick = willBreakThisTick(mc, pos, state);
|
||||
boolean breaksNextTick = !breaksThisTick && willBreakNextTick(mc, pos, state);
|
||||
InteractTiming t = action.interactTiming;
|
||||
if (action.interact && t == InteractTiming.BEFORE && breaksNextTick) sendBlockInteract(mc, pos, dir);
|
||||
if (action.interact && t == InteractTiming.WITH && breaksThisTick) sendBlockInteract(mc, pos, dir);
|
||||
|
||||
mc.gameMode.continueDestroyBlock(pos, dir);
|
||||
mc.player.swing(InteractionHand.MAIN_HAND);
|
||||
|
||||
if (action.interact && t == InteractTiming.AFTER && breaksThisTick) sendBlockInteract(mc, pos, dir);
|
||||
return mc.level.getBlockState(pos).isAir() ? 1 : 0;
|
||||
}
|
||||
|
||||
private static int breakCustomTickWithNextSteps(Minecraft mc, BreakAction action, BlockPos pos, Direction dir,
|
||||
boolean[] nextStepsFired,
|
||||
boolean[] missingNextStepsWarned) throws InterruptedException {
|
||||
boolean willBreak = Boolean.TRUE.equals(MacroExecutor.callOnClientThread(mc, () -> {
|
||||
if (mc.level == null || mc.player == null) return Boolean.FALSE;
|
||||
BlockState state = mc.level.getBlockState(pos);
|
||||
if (state.isAir()) return Boolean.FALSE;
|
||||
return willBreakThisTick(mc, pos, state);
|
||||
}, Boolean.FALSE));
|
||||
|
||||
if (!willBreak) {
|
||||
return MacroExecutor.callOnClientThread(mc, () -> continueBreakOnClient(mc, action, pos, dir), -1, action.isTickAligned());
|
||||
}
|
||||
|
||||
long ns = Math.abs((long) action.interactCustomMs) * 1_000_000L;
|
||||
int broke;
|
||||
if (action.interactCustomMs < 0) {
|
||||
runBreakNextStepsOnce(mc, action, nextStepsFired, missingNextStepsWarned);
|
||||
if (!MacroExecutor.isCurrentRunActive()) return -1;
|
||||
if (ns > 0) java.util.concurrent.locks.LockSupport.parkNanos(ns);
|
||||
broke = MacroExecutor.callOnClientThread(mc, () -> breakAndDetectOnClient(mc, pos, dir), -1, action.isTickAligned());
|
||||
} else {
|
||||
broke = MacroExecutor.callOnClientThread(mc, () -> breakAndDetectOnClient(mc, pos, dir), -1, action.isTickAligned());
|
||||
}
|
||||
return broke;
|
||||
}
|
||||
|
||||
private static int breakCustomTick(Minecraft mc, BreakAction action, BlockPos pos, Direction dir) throws InterruptedException {
|
||||
boolean willBreak = Boolean.TRUE.equals(MacroExecutor.callOnClientThread(mc, () -> {
|
||||
if (mc.level == null || mc.player == null) return Boolean.FALSE;
|
||||
BlockState s = mc.level.getBlockState(pos);
|
||||
if (s.isAir()) return Boolean.FALSE;
|
||||
return willBreakThisTick(mc, pos, s);
|
||||
}, Boolean.FALSE));
|
||||
|
||||
if (!willBreak) {
|
||||
|
||||
return MacroExecutor.callOnClientThread(mc, () -> {
|
||||
if (mc.level == null || mc.gameMode == null || mc.player == null) return -1;
|
||||
if (mc.level.getBlockState(pos).isAir()) return 1;
|
||||
if (action.sneak) holdMacroSneak(mc, action.sneakMode);
|
||||
mc.gameMode.continueDestroyBlock(pos, dir);
|
||||
mc.player.swing(InteractionHand.MAIN_HAND);
|
||||
return mc.level.getBlockState(pos).isAir() ? 1 : 0;
|
||||
}, -1, action.isTickAligned());
|
||||
}
|
||||
|
||||
long ns = Math.abs((long) action.interactCustomMs) * 1_000_000L;
|
||||
int broke;
|
||||
if (action.interactCustomMs < 0) {
|
||||
|
||||
MacroExecutor.runOnClientThread(mc, () -> sendBlockInteract(mc, pos, dir), action.isTickAligned());
|
||||
if (ns > 0) java.util.concurrent.locks.LockSupport.parkNanos(ns);
|
||||
broke = MacroExecutor.callOnClientThread(mc, () -> breakAndDetectOnClient(mc, pos, dir), -1, action.isTickAligned());
|
||||
} else {
|
||||
|
||||
broke = MacroExecutor.callOnClientThread(mc, () -> breakAndDetectOnClient(mc, pos, dir), -1, action.isTickAligned());
|
||||
if (ns > 0) java.util.concurrent.locks.LockSupport.parkNanos(ns);
|
||||
MacroExecutor.runOnClientThread(mc, () -> sendBlockInteract(mc, pos, dir), action.isTickAligned());
|
||||
}
|
||||
return broke;
|
||||
}
|
||||
|
||||
private static int breakAndDetectOnClient(Minecraft mc, BlockPos pos, Direction dir) {
|
||||
if (mc.level == null || mc.gameMode == null || mc.player == null) return -1;
|
||||
if (mc.level.getBlockState(pos).isAir()) return 1;
|
||||
mc.gameMode.continueDestroyBlock(pos, dir);
|
||||
mc.player.swing(InteractionHand.MAIN_HAND);
|
||||
return mc.level.getBlockState(pos).isAir() ? 1 : 0;
|
||||
}
|
||||
|
||||
private static boolean willBreakThisTick(Minecraft mc, BlockPos pos, BlockState state) {
|
||||
float progress = (mc.gameMode instanceof AutismMultiPlayerGameModeAccessor acc) ? acc.autism$getDestroyProgress() : 0f;
|
||||
float delta = state.getDestroyProgress(mc.player, mc.player.level(), pos);
|
||||
return progress > 0f && (progress + delta) >= 1.0f;
|
||||
}
|
||||
|
||||
private static boolean willBreakNextTick(Minecraft mc, BlockPos pos, BlockState state) {
|
||||
float progress = (mc.gameMode instanceof AutismMultiPlayerGameModeAccessor acc) ? acc.autism$getDestroyProgress() : 0f;
|
||||
float delta = state.getDestroyProgress(mc.player, mc.player.level(), pos);
|
||||
return progress > 0f && (progress + 2f * delta) >= 1.0f;
|
||||
}
|
||||
|
||||
private static void runBreakNextStepsOnce(Minecraft mc, BreakAction action, boolean[] fired, boolean[] missingWarned) throws InterruptedException {
|
||||
if (fired != null && fired[0]) return;
|
||||
java.util.List<MacroAction> actions = action.getNextActions();
|
||||
if (actions == null || actions.isEmpty()) {
|
||||
if (missingWarned != null && !missingWarned[0]) {
|
||||
missingWarned[0] = true;
|
||||
AutismClientMessaging.sendPrefixed("\u00a7cBreak: no next steps found. Add action(s) after this Break step.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (fired != null) fired[0] = true;
|
||||
action.markNextActionsRan();
|
||||
String names = actions.size() == 1 ? actions.get(0).getDisplayName() : actions.size() + " steps";
|
||||
MacroExecutor.setCurrentStatus("Break: next " + names);
|
||||
AutismModule module = AutismModule.get();
|
||||
boolean previousSuppressPostGui = Boolean.TRUE.equals(MacroExecutor.SUPPRESS_POST_GUI_AFTER.get());
|
||||
try {
|
||||
MacroExecutor.SUPPRESS_POST_GUI_AFTER.set(true);
|
||||
for (MacroAction next : actions) {
|
||||
if (next == null || !next.isEnabled() || !MacroExecutor.isCurrentRunActive()) continue;
|
||||
try {
|
||||
MacroExecutor.executeSingleActionWithWaits(mc, next, module);
|
||||
} catch (InterruptedException e) {
|
||||
throw e;
|
||||
} catch (Throwable t) {
|
||||
AutismClientMessaging.sendPrefixed("\u00a7cBreak next step failed (" + next.getDisplayName() + "): " + MacroRace.safeThrowableMessage(t));
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
MacroExecutor.SUPPRESS_POST_GUI_AFTER.set(previousSuppressPostGui);
|
||||
}
|
||||
}
|
||||
|
||||
private static void runBreakNextStepsAfterCompletion(Minecraft mc, BreakAction action, boolean[] fired,
|
||||
boolean[] missingWarned) throws InterruptedException {
|
||||
if (!action.interact || !action.runNextSteps || action.interactTiming == null) return;
|
||||
switch (action.interactTiming) {
|
||||
case AFTER -> runBreakNextStepsOnce(mc, action, fired, missingWarned);
|
||||
case AFTER_PLUS -> {
|
||||
MacroExecutor.waitOneTick();
|
||||
runBreakNextStepsOnce(mc, action, fired, missingWarned);
|
||||
}
|
||||
case CUSTOM -> {
|
||||
if (action.interactCustomMs >= 0) {
|
||||
long ns = Math.abs((long) action.interactCustomMs) * 1_000_000L;
|
||||
if (ns > 0) java.util.concurrent.locks.LockSupport.parkNanos(ns);
|
||||
runBreakNextStepsOnce(mc, action, fired, missingWarned);
|
||||
}
|
||||
}
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void sendBlockInteract(Minecraft mc, BlockPos pos, Direction dir) {
|
||||
if (mc.gameMode == null || mc.player == null) return;
|
||||
Vec3 hit = Vec3.atCenterOf(pos).add(dir.getStepX() * 0.5, dir.getStepY() * 0.5, dir.getStepZ() * 0.5);
|
||||
BlockHitResult blockHit = new BlockHitResult(hit, dir, pos, false);
|
||||
mc.gameMode.useItemOn(mc.player, InteractionHand.MAIN_HAND, blockHit);
|
||||
}
|
||||
|
||||
private static void waitForBreakSolid(Minecraft mc, BlockPos pos) throws InterruptedException {
|
||||
while (MacroExecutor.isCurrentRunActive()) {
|
||||
if (!isInstaBreakAir(mc, pos)) return;
|
||||
Thread.sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
private static void waitBreakClientTicks(int ticks) throws InterruptedException {
|
||||
long start = AutismSharedState.get().getClientTickCounter();
|
||||
while (MacroExecutor.isCurrentRunActive() && (AutismSharedState.get().getClientTickCounter() - start) < ticks) {
|
||||
Thread.sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
private static void holdMacroSneak(Minecraft mc, String mode) {
|
||||
autismclient.util.AutismMacroSneak.hold(mc, mode);
|
||||
}
|
||||
|
||||
private static void releaseMacroSneak(Minecraft mc, String mode) {
|
||||
autismclient.util.AutismMacroSneak.release(mc, mode);
|
||||
if (!autismclient.util.AutismMacroSneak.isPacket(mode)) MacroExecutor.applyAggregateSneakState(mc);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue