From 8ec1ccd45d8680df7effcbd655423940d2221caf Mon Sep 17 00:00:00 2001 From: BruceChen Date: Sat, 25 Apr 2026 18:08:08 +0000 Subject: [PATCH] pathing: 0-replan on long Descend->Traverse + cold-start 5 c2c Two complementary fixes for live-server "stuck on a step then replan" on the 252.5,138,220.5 -> 244.5,122,188.5 route. Search layer (ParkourFeasibility.HasRunUp): a long flat sprint parkour (5 c2c, horiz~5) cannot launch from a cold start. Vanilla physics show that gap=4 dy=0 reaches 5.1075m only with 12 momentum ticks of straight sprint windup; a 0t standing jump tops out at gap=3 (=4 c2c). When the previous move type is not Parkour/Descend (i.e. no carried airborne momentum) we now require two aligned back-runway blocks instead of one so the executor actually has room to spin sprint up. Execution layer (GroundedSegmentController.ShouldComplete): the LandingRecovery early-out used to live below the MinExitSpeed gate. A Descend that landed inside the destination block but naturally settled to zero speed (e.g. when the next segment is a fresh Traverse rather than a chained Parkour) would fail the 0.03 MinExitSpeed check and idle inside the target block until the per-segment timeout fired, triggering an unnecessary replan. Move the LandingRecovery footprint check above the speed gate so a fully-decelerated handoff is accepted. Verified live on 1.21.11-Vanilla: - 252.5,138,220.5 -> 244.5,122,188.5: 24 segments, 0 replans (was: 1) - 244.5,122,188.5 -> 252.5,138,220.5: 48 segments, 0 replans - 251.5,141,210.5 -> 252.5,138,220.5: 34 segments, 0 replans - 252.5,138,220.5 -> 251.5,141,210.5: 24 segments, 0 replans Test suite: 297 passed / 22 known pre-existing failures, no new regressions vs 5de169db. Made-with: Cursor --- .../Templates/GroundedSegmentController.cs | 20 +++++++++---- .../Pathing/Moves/ParkourFeasibility.cs | 30 +++++++++++++++---- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/MinecraftClient/Pathing/Execution/Templates/GroundedSegmentController.cs b/MinecraftClient/Pathing/Execution/Templates/GroundedSegmentController.cs index 13e67da4..87c03403 100644 --- a/MinecraftClient/Pathing/Execution/Templates/GroundedSegmentController.cs +++ b/MinecraftClient/Pathing/Execution/Templates/GroundedSegmentController.cs @@ -123,12 +123,14 @@ namespace MinecraftClient.Pathing.Execution.Templates return TemplateHelper.RemainingDistanceAlongSegment(pos, segment) <= handoffDistance; } - if (exitSpeed < segment.ExitHints.MinExitSpeed) - return false; - - if (exitSpeed > segment.ExitHints.MaxExitSpeed) - return false; - + // LandingRecovery accepts a fully-decelerated handoff: once the bot + // has reached the target block on the ground, the segment has done + // its job. Apply this before the MinExitSpeed gate so a Descend + // that lands and naturally settles to zero speed (e.g. when the + // following segment is a fresh Traverse rather than a chained + // Parkour) can hand off cleanly. Without this early-out the bot + // would idle inside the destination block until the segment timed + // out, triggering an unnecessary replan. if (segment.ExitTransition == PathTransitionType.LandingRecovery && physics.OnGround && !segment.ExitHints.RequireStableFooting @@ -137,6 +139,12 @@ namespace MinecraftClient.Pathing.Execution.Templates return true; } + if (exitSpeed < segment.ExitHints.MinExitSpeed) + return false; + + if (exitSpeed > segment.ExitHints.MaxExitSpeed) + return false; + if (segment.ExitHints.RequireStableFooting) { return physics.OnGround diff --git a/MinecraftClient/Pathing/Moves/ParkourFeasibility.cs b/MinecraftClient/Pathing/Moves/ParkourFeasibility.cs index a1ef655f..480a92fd 100644 --- a/MinecraftClient/Pathing/Moves/ParkourFeasibility.cs +++ b/MinecraftClient/Pathing/Moves/ParkourFeasibility.cs @@ -62,11 +62,31 @@ internal static class ParkourFeasibility if (carriedEntry && yDelta < 0) return true; - int backX = x - Math.Sign(xOffset); - int backZ = z - Math.Sign(zOffset); - if (!ctx.CanWalkOn(backX, y - 1, backZ)) - return false; - return IsColumnPassable(ctx, backX, y, backZ); + int xSign = Math.Sign(xOffset); + int zSign = Math.Sign(zOffset); + + // Long flat sprint parkour (5 c2c, horiz~5) requires the player to be + // launched at full vanilla sprint velocity (~12 momentum ticks). A + // standing-jump cold start only reaches gap=3 (=4 c2c). When the + // previous move is not a momentum-carrying Parkour/Descend, one back + // block of runway is not enough to spin sprint up; demand at least + // two aligned back blocks so the executor has a real run-up window. + // tools/sim_jump_reach.py "Standing sprint jump (0t momentum)" matrix + // shows gap=4 dy=0 is unreachable, while 12t-momentum gap=4 reaches + // 5.1075 m. + int requiredBackBlocks = (yDelta == 0 && !carriedEntry && horiz >= 4.5) ? 2 : 1; + + for (int i = 1; i <= requiredBackBlocks; i++) + { + int backX = x - xSign * i; + int backZ = z - zSign * i; + if (!ctx.CanWalkOn(backX, y - 1, backZ)) + return false; + if (!IsColumnPassable(ctx, backX, y, backZ)) + return false; + } + + return true; } public static bool TryGetRequiredStaticEntryRunupSteps(