Fix bot wedging on a wall corner when detouring#10
Conversation
When walking along a wall (e.g. detouring around it) the bot could wedge its hitbox against the wall's corner block: it kept pressing forward along the path (into the wall) and stopped moving, oscillating in place forever. The forward executor's stall safety net was commented out and recovery is disabled, so the move never ended and goto() never returned. NewForwardExecutor now tracks XZ progress per move. After 12 ticks of no progress it enters an unstick: stop sprinting and steer at the target block's centre, which adds the sideways push needed to slide off the corner instead of ramming the wall. If that still makes no progress after 40 ticks it throws CancelError so the path executor can give up cleanly. The detector sits after the mining/placing early-returns, so it never fires while interacting, and it keys on real position progress (not a tick count), so slow legit moves are fine. Verified in-game on a real offline 1.20.4 server: - wall-detour now completes; full movement suite 5/5 (flat, diagonal, staircase, drop, wall) on two runs, no regression. - wall stress 10/10 across 5 geometries x 2 rounds (standard, long, north-side detour, 5-tall, L-shaped corner). - build + ts-standard clean, 31/31 unit tests pass. Pre-existing bug (reproduces on 2026-rewrite before this change). Touches only the forward executor; recovery and cost subsystems are untouched.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4bbdb5cafd
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (this.stuckTicks >= NewForwardExecutor.STUCK_TICK_LIMIT) { | ||
| this.stuckTicks = 0 | ||
| this.stuckLastPos = null | ||
| throw new CancelError(`ForwardMove: stuck (no progress) near ${thisMove.exitPos}`) |
There was a problem hiding this comment.
Don't treat long block breaking as a movement stall
When a Forward/Diagonal move starts a dig that takes more than 40 ticks, this.cI remains set while the block is still being broken, and BreakHandler.performInfo returns finite ticks: 0 for any reachable block, so the allowExternalInfluence check at the top falls through into this stall guard instead of returning. The bot is commonly pressed against the still-solid target block during that dig, so XZ progress stays below the threshold and this throws CancelError before slow-but-valid mining, such as stone by hand or obsidian with a pickaxe, can finish.
Useful? React with 👍 / 👎.
Review catch (chatgpt-codex): `allowExternalInfluence` returns true for a reachable block mid-dig, so a Forward/Diagonal move that breaks a slow block (stone by hand, obsidian, ...) falls through to the stall guard. The bot stands still against the still-solid block during the dig, so XZ progress stays under the threshold and the guard CancelError'd valid mining after 40 ticks. Now the no-progress counter is skipped whenever an interaction is in progress (this.cI != null): mining/placing is not a movement stall. The corner-unstick behaviour for real travel is unchanged.
Separate executor fix, as suggested in #8 (the wall-detour issue I flagged from in-game testing).
The bug
When the bot walks along a wall to get around it, it can wedge its hitbox against the wall's corner block: it keeps pressing forward along the path (which points mostly into the wall) and stops moving, oscillating in place forever.
goto()never returns.Root cause, from per-tick in-game tracing: the forward executor advances onto the next move while the bot is at the edge of the previous node (off-centre, hugging the wall). The next move's steering aims mostly along the path (into the wall), so the bot pins on the corner and the small perpendicular component never slides it clear. The executor's stall safety net (
tickCount > 160) is commented out and recovery is disabled (MAX_RECOVERY_DEPTH = 0), so nothing ends the move.The fix (forward executor only)
NewForwardExecutortracks XZ progress per move:CancelErrorso the path executor gives up cleanly instead of hanging.It is keyed on real position progress (not a tick count) and sits after the mining/placing early-returns, so it never fires while interacting and won't false-positive on slow legitimate moves. Recovery and cost subsystems are untouched.
Verification (real offline 1.20.4 server)
wall-detournow completes. Full movement suite 5/5 on two runs (flat, diagonal, staircase-up, drop-down, wall-detour) — no regression.npm run build+npx ts-standard -yclean,npm test31/31.Pre-existing bug: it reproduces identically on
2026-rewritebefore this change.