mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2026-08-29 13:04:59 +00:00
pathing: unify jump moves into MoveJump + IMoveExpander
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
This commit is contained in:
parent
da52aa5c3c
commit
d002930a6a
16 changed files with 1650 additions and 848 deletions
79
MinecraftClient/Pathing/Moves/Impl/MoveJump.cs
Normal file
79
MinecraftClient/Pathing/Moves/Impl/MoveJump.cs
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
using System;
|
||||
using MinecraftClient.Pathing.Core;
|
||||
|
||||
namespace MinecraftClient.Pathing.Moves.Impl
|
||||
{
|
||||
/// <summary>
|
||||
/// Unified jump-family move. A single IMove implementation that dispatches
|
||||
/// on <see cref="JumpFlavor"/> to cover every combination previously
|
||||
/// implemented by seven separate classes (Traverse, Diagonal, Ascend,
|
||||
/// DiagonalAscend, DiagonalDescend, Parkour, SidewallParkour).
|
||||
///
|
||||
/// All feasibility and cost logic lives in <see cref="JumpFeasibility"/>.
|
||||
/// Factory helpers (<see cref="Traverse"/>, <see cref="Parkour"/>, ...)
|
||||
/// produce the right descriptor for each use site without requiring
|
||||
/// callers to remember the mapping between flavor and <see cref="MoveType"/>.
|
||||
/// </summary>
|
||||
public sealed class MoveJump : IMove
|
||||
{
|
||||
public JumpDescriptor Descriptor { get; }
|
||||
public MoveType Type { get; }
|
||||
public int XOffset => Descriptor.XOffset;
|
||||
public int ZOffset => Descriptor.ZOffset;
|
||||
public int YDelta => Descriptor.YDelta;
|
||||
public JumpFlavor Flavor => Descriptor.Flavor;
|
||||
public bool DynamicY => false;
|
||||
|
||||
public MoveJump(JumpDescriptor descriptor)
|
||||
{
|
||||
Descriptor = descriptor;
|
||||
Type = DeriveMoveType(descriptor);
|
||||
}
|
||||
|
||||
public void Calculate(CalculationContext ctx, int x, int y, int z, ref MoveResult result)
|
||||
=> JumpFeasibility.Evaluate(ctx, x, y, z, Descriptor, ref result);
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
double horiz = Math.Sqrt((double)(XOffset * XOffset + ZOffset * ZOffset));
|
||||
return $"MoveJump({Flavor}, off=({XOffset},{ZOffset}), dy={YDelta}, dist={horiz:F2})";
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Factory helpers
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
public static MoveJump Traverse(int dx, int dz)
|
||||
=> new(new JumpDescriptor(dx, dz, 0, JumpFlavor.Walk));
|
||||
|
||||
public static MoveJump Diagonal(int dx, int dz)
|
||||
=> new(new JumpDescriptor(dx, dz, 0, JumpFlavor.Walk));
|
||||
|
||||
public static MoveJump Ascend(int dx, int dz)
|
||||
=> new(new JumpDescriptor(dx, dz, 1, JumpFlavor.Step));
|
||||
|
||||
public static MoveJump DiagonalAscend(int dx, int dz)
|
||||
=> new(new JumpDescriptor(dx, dz, 1, JumpFlavor.Step));
|
||||
|
||||
public static MoveJump DiagonalDescend(int dx, int dz)
|
||||
=> new(new JumpDescriptor(dx, dz, -1, JumpFlavor.Step));
|
||||
|
||||
public static MoveJump Parkour(int dx, int dz, int yDelta = 0)
|
||||
=> new(new JumpDescriptor(dx, dz, yDelta, JumpFlavor.SprintJump));
|
||||
|
||||
public static MoveJump Sidewall(int dx, int dz, int yDelta = 0)
|
||||
=> new(new JumpDescriptor(dx, dz, yDelta, JumpFlavor.Sidewall));
|
||||
|
||||
private static MoveType DeriveMoveType(JumpDescriptor d)
|
||||
{
|
||||
return d.Flavor switch
|
||||
{
|
||||
JumpFlavor.Walk => d.IsCardinal ? MoveType.Traverse : MoveType.Diagonal,
|
||||
JumpFlavor.Step => d.YDelta > 0 ? MoveType.Ascend : MoveType.Descend,
|
||||
JumpFlavor.SprintJump => MoveType.Parkour,
|
||||
JumpFlavor.Sidewall => MoveType.Parkour,
|
||||
_ => MoveType.Traverse,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue