mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2026-08-15 13:04:36 +00:00
Replace seven hand-written IMove classes (MoveTraverse, MoveDiagonal, MoveAscend, MoveDiagonalAscend, MoveDiagonalDescend, MoveParkour, MoveSidewallParkour) with a single MoveJump driven by a JumpDescriptor (XOffset, ZOffset, YDelta, JumpFlavor). JumpFeasibility is the single source of truth for the physics/cost rules of every jump-family move. A* no longer iterates a flat IMove[]. The Calculate loop now drives an IMoveExpander[] that writes into a stackalloc Span<MoveNeighbor>, eliminating per-iteration heap traffic. JumpExpander enumerates every jump-family descriptor dynamically; LegacyMoveExpander wraps the remaining dynamic-landing moves (MoveDescend, MoveSprintDescend, MoveClimb, MoveFall) so callers that still pass a custom IMove[] keep working. Add two O(1) short-circuits at the top of JumpExpander.Expand: - Hoist the per-node parkour preconditions (AllowParkour + CanSprint, standing block climbability, feet-liquid, head clearance at y+2) so ~170 SprintJump + Sidewall descriptors never call JumpFeasibility when the node cannot take off at all. - Precompute an 8-way "first step has no floor" table indexed by (sign(dx), sign(dz)) so SprintJump descriptors in a direction that has a walkable floor underneath are dropped without Evaluate. - Add a conservative "any cardinal wall at y or y+1" probe that skips all 112 Sidewall descriptors when no wall exists adjacent to the takeoff. Move tests switch to the new MoveJump.* factory methods. Behavior is verified by the existing test suite: the 21 pre-existing baseline failures are preserved exactly, 0 regressions introduced. Made-with: Cursor
56 lines
1.8 KiB
C#
56 lines
1.8 KiB
C#
namespace MinecraftClient.Pathing.Moves;
|
|
|
|
/// <summary>
|
|
/// Kind of jump-family move. Each flavor selects a different evaluator path
|
|
/// inside <see cref="JumpFeasibility"/> while sharing low-level primitives
|
|
/// (head clearance, destination clearance, flight-path sweep, cost model).
|
|
/// </summary>
|
|
public enum JumpFlavor
|
|
{
|
|
/// <summary>
|
|
/// Single-block cardinal or diagonal walk at the same Y. No jump input.
|
|
/// Covers the old <c>MoveTraverse</c> and <c>MoveDiagonal</c>.
|
|
/// </summary>
|
|
Walk,
|
|
|
|
/// <summary>
|
|
/// Single-block vertical step (dy = +1 up or dy = -1 down), cardinal or
|
|
/// diagonal. Covers <c>MoveAscend</c>, <c>MoveDiagonalAscend</c>, and
|
|
/// <c>MoveDiagonalDescend</c>.
|
|
/// </summary>
|
|
Step,
|
|
|
|
/// <summary>
|
|
/// Multi-block sprint jump, cardinal or diagonal. Covers <c>MoveParkour</c>.
|
|
/// </summary>
|
|
SprintJump,
|
|
|
|
/// <summary>
|
|
/// Dominant-axis sprint jump that uses an inner wall for support. Covers
|
|
/// <c>MoveSidewallParkour</c>.
|
|
/// </summary>
|
|
Sidewall,
|
|
}
|
|
|
|
/// <summary>
|
|
/// Fully describes a single jump-family move (Walk / Step / SprintJump /
|
|
/// Sidewall). All geometry that downstream planners or templates need can be
|
|
/// derived from this value, so A* only needs to enumerate descriptors rather
|
|
/// than hard-coded IMove subclasses.
|
|
/// </summary>
|
|
public readonly record struct JumpDescriptor(
|
|
int XOffset,
|
|
int ZOffset,
|
|
int YDelta,
|
|
JumpFlavor Flavor)
|
|
{
|
|
public bool IsCardinal => (XOffset == 0) != (ZOffset == 0);
|
|
|
|
public bool IsDiagonal => XOffset != 0 && ZOffset != 0;
|
|
|
|
public int HorizontalMajor
|
|
=> System.Math.Max(System.Math.Abs(XOffset), System.Math.Abs(ZOffset));
|
|
|
|
public int HorizontalMinor
|
|
=> System.Math.Min(System.Math.Abs(XOffset), System.Math.Abs(ZOffset));
|
|
}
|