refactor: thread parkour profile into runtime segments

This commit is contained in:
BruceChen 2026-04-18 16:04:45 +00:00
parent f64c6be0a9
commit b4b0c6e8ed
8 changed files with 50 additions and 3 deletions

View file

@ -49,6 +49,22 @@ public sealed class PathSegmentBuilderTests
Assert.True(segments[0].PreserveSprint);
}
[Fact]
public void FromPath_CopiesParkourProfile_ToRuntimeSegment()
{
var start = new PathNode(100, 80, 100);
var end = new PathNode(99, 80, 102)
{
MoveUsed = MoveType.Parkour,
ParkourProfile = ParkourProfile.Sidewall
};
List<PathSegment> segments = PathSegmentBuilder.FromPath([start, end]);
Assert.Single(segments);
Assert.Equal(ParkourProfile.Sidewall, segments[0].ParkourProfile);
}
private static List<PathNode> BuildNodes(params (int x, int y, int z, MoveType moveUsed)[] raw)
{
var result = new List<PathNode>(raw.Length);

View file

@ -54,6 +54,21 @@ public sealed class MoveParkourTests
Assert.Equal(2, result.DestX);
}
[Fact]
public void Accepts2x1Gap_TagsDefaultParkourProfile()
{
var world = FlatWorldTestBuilder.CreateStoneFloor(FloorY);
world.SetBlock(new Location(1, FloorY, 0), Block.Air);
var ctx = BuildContext(world);
var move = new MoveParkour(2, 0);
var result = default(MoveResult);
move.Calculate(ctx, 0, FloorY + 1, 0, ref result);
Assert.False(result.IsImpossible);
Assert.Equal(ParkourProfile.Default, result.ParkourProfile);
}
[Fact]
public void Rejects2x1WhenAdjacentBlockIsStillWalkable()
{

View file

@ -9,18 +9,21 @@ namespace MinecraftClient.Pathing.Core
public int DestY;
public int DestZ;
public double Cost;
public ParkourProfile ParkourProfile;
public void Set(int x, int y, int z, double cost)
public void Set(int x, int y, int z, double cost, ParkourProfile parkourProfile = ParkourProfile.None)
{
DestX = x;
DestY = y;
DestZ = z;
Cost = cost;
ParkourProfile = parkourProfile;
}
public void SetImpossible()
{
Cost = ActionCosts.CostInf;
ParkourProfile = ParkourProfile.None;
}
public readonly bool IsImpossible => Cost >= ActionCosts.CostInf;

View file

@ -0,0 +1,9 @@
namespace MinecraftClient.Pathing.Core
{
public enum ParkourProfile
{
None = 0,
Default = 1,
Sidewall = 2
}
}

View file

@ -15,6 +15,7 @@ namespace MinecraftClient.Pathing.Core
public PathNode? Parent;
public MoveType MoveUsed;
public ParkourProfile ParkourProfile;
public int HeapIndex;
public bool IsOpen;

View file

@ -9,6 +9,7 @@ namespace MinecraftClient.Pathing.Execution
public required Location Start { get; init; }
public required Location End { get; init; }
public required MoveType MoveType { get; init; }
public ParkourProfile ParkourProfile { get; init; } = ParkourProfile.None;
public PathTransitionType ExitTransition { get; init; } = PathTransitionType.FinalStop;
public PathTransitionHints ExitHints { get; init; } = PathTransitionHints.Default;
public bool PreserveSprint { get; init; }

View file

@ -22,6 +22,7 @@ namespace MinecraftClient.Pathing.Execution
Start = current.Start,
End = current.End,
MoveType = current.MoveType,
ParkourProfile = current.ParkourProfile,
ExitTransition = exitTransition,
ExitHints = BuildHints(current, next, nextNext, exitTransition),
PreserveSprint = exitTransition is PathTransitionType.ContinueStraight or PathTransitionType.PrepareJump
@ -53,7 +54,8 @@ namespace MinecraftClient.Pathing.Execution
{
Start = new Location(start.X + 0.5, start.Y, start.Z + 0.5),
End = new Location(end.X + 0.5, end.Y, end.Z + 0.5),
MoveType = end.MoveUsed
MoveType = end.MoveUsed,
ParkourProfile = end.ParkourProfile
};
}

View file

@ -207,7 +207,7 @@ namespace MinecraftClient.Pathing.Moves.Impl
else
cost = horizDist * ctx.WalkCost + ctx.JumpPenalty;
result.Set(destX, destY, destZ, cost);
result.Set(destX, destY, destZ, cost, ParkourProfile.Default);
}
/// <summary>