mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2026-08-15 13:04:36 +00:00
pathing: stabilize 0-replan round-trip on ledge/descend runs
Fix a cluster of execution-layer issues that caused replans and void falls when traversing narrow ledges and multi-block descents between (251.5,141,210.5) and (252.5,138,220.5): - WalkTemplate / GroundedSegmentController: suppress the pre-rotation bias toward the next segment's exit heading on stable-footing Turn exits where the next segment is not a jump. The next template snaps yaw on its first tick anyway, and pre-rotating mid-stride on a 1-block walkway pushes sprint drift perpendicular to the path and walks the bot off the edge. Turn exits into a jump still get the bias so the takeoff direction stays aligned. - GroundedSegmentController.ShouldComplete: relax the headingReady gate for Turn exits with stable footing so the segment can complete once yaw is aligned with either the current or the next segment heading (within 25/15 deg). Without this the removed bias would leave the bot stuck at the end of a walkway waiting for a rotation that never happens. - DescendTemplate: restrict the airborne exit-heading bias so it only kicks in when the footprint is inside the landing block, or on single-step drops where the fall is too short for lateral drift to miss the landing column. On 2+ block drops the bot now keeps yaw pointed at the landing center for the whole fall. - DescendTemplate: add a multi-block overshoot guard on PrepareJump exits. Once airborne and past the landing end-plane on a 2+ Y drop, release forward/sprint and press back briefly so air drag pulls the bot back into the 1x1 landing column instead of sailing one block past it into the neighbouring void. Live round-trip between the two goal coordinates now completes with zero replans in three consecutive runs in each direction. Full unit test suite is unchanged from the pre-existing baseline (22 failing tests, all orthogonal to this change). Made-with: Cursor
This commit is contained in:
parent
d002930a6a
commit
5de169db64
19 changed files with 1418 additions and 171 deletions
|
|
@ -1724,58 +1724,33 @@ namespace MinecraftClient
|
|||
|
||||
/// <summary>
|
||||
/// Navigate to a goal using the new A* pathfinder and template-based execution.
|
||||
/// Accepts any IGoal for flexible target specification.
|
||||
/// Returns a description of the result for UI feedback.
|
||||
/// The A* search runs on a background task so the 20 TPS tick loop is
|
||||
/// never blocked; the caller sees a "planning started" acknowledgement
|
||||
/// and the real result is logged when
|
||||
/// <see cref="Pathing.Execution.PathSegmentManager"/> installs the plan
|
||||
/// on a subsequent tick.
|
||||
/// </summary>
|
||||
public (bool success, string message) NavigateToGoal(Pathing.Goals.IGoal goal, long timeoutMs = 5000)
|
||||
{
|
||||
Location startPos;
|
||||
lock (locationLock)
|
||||
{
|
||||
var ctx = new Pathing.Core.CalculationContext(world,
|
||||
allowParkour: true, allowParkourAscend: true);
|
||||
var finder = new Pathing.Core.AStarPathFinder();
|
||||
finder.DebugLog = msg => Log.Debug(msg);
|
||||
|
||||
int sx = (int)Math.Floor(location.X);
|
||||
int sy = (int)Math.Floor(location.Y);
|
||||
int sz = (int)Math.Floor(location.Z);
|
||||
|
||||
if (!ctx.CanWalkThrough(sx, sy, sz) && ctx.CanWalkThrough(sx, sy + 1, sz))
|
||||
sy++;
|
||||
|
||||
Log.Info($"[Navigate] A* search from ({sx},{sy},{sz}) to {goal}");
|
||||
|
||||
using var cts = new CancellationTokenSource();
|
||||
var result = finder.Calculate(ctx, sx, sy, sz, goal, cts.Token, timeoutMs);
|
||||
|
||||
Log.Info($"[Navigate] A* result: {result.Status}, nodes={result.NodesExplored}, " +
|
||||
$"time={result.ElapsedMs}ms, path length={result.Path.Count}");
|
||||
|
||||
if (result.Status == Pathing.Core.PathStatus.Failed || result.Path.Count < 2)
|
||||
{
|
||||
return (false, string.Format(Translations.cmd_goto_failed,
|
||||
result.NodesExplored, result.ElapsedMs));
|
||||
}
|
||||
|
||||
for (int i = 1; i < result.Path.Count; i++)
|
||||
{
|
||||
var node = result.Path[i];
|
||||
Log.Debug($"[Navigate] seg[{i - 1}] = {node.MoveUsed}: ({node.X},{node.Y},{node.Z})");
|
||||
}
|
||||
|
||||
pathTarget = null;
|
||||
path = null;
|
||||
|
||||
pathSegmentManager = new Pathing.Execution.PathSegmentManager(
|
||||
debugLog: msg => Log.Debug(msg),
|
||||
infoLog: msg => Log.Info(msg),
|
||||
observer: new Pathing.Execution.Telemetry.PathExecutionLogObserver(msg => Log.Debug(msg)));
|
||||
pathSegmentManager.StartNavigation(goal, result);
|
||||
|
||||
string statusStr = result.Status == Pathing.Core.PathStatus.Partial ? " (partial)" : "";
|
||||
return (true, string.Format(Translations.cmd_goto_success,
|
||||
result.Path.Count - 1, result.NodesExplored, result.ElapsedMs, statusStr));
|
||||
startPos = location;
|
||||
}
|
||||
|
||||
Log.Info($"[Navigate] A* search from ({(int)Math.Floor(startPos.X)},{(int)Math.Floor(startPos.Y)},{(int)Math.Floor(startPos.Z)}) to {goal}");
|
||||
|
||||
pathTarget = null;
|
||||
path = null;
|
||||
|
||||
pathSegmentManager?.Cancel();
|
||||
pathSegmentManager = new Pathing.Execution.PathSegmentManager(
|
||||
debugLog: msg => Log.Debug(msg),
|
||||
infoLog: msg => Log.Info(msg),
|
||||
observer: new Pathing.Execution.Telemetry.PathExecutionLogObserver(msg => Log.Debug(msg)));
|
||||
pathSegmentManager.StartNavigationAsync(goal, startPos, world, timeoutMs);
|
||||
|
||||
return (true, string.Format(Translations.cmd_goto_planning, timeoutMs));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue