diff --git a/MinecraftClient.Tests/Pathing/Execution/PathSegmentBuilderTests.cs b/MinecraftClient.Tests/Pathing/Execution/PathSegmentBuilderTests.cs index a15dc070..7f620ec9 100644 --- a/MinecraftClient.Tests/Pathing/Execution/PathSegmentBuilderTests.cs +++ b/MinecraftClient.Tests/Pathing/Execution/PathSegmentBuilderTests.cs @@ -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 segments = PathSegmentBuilder.FromPath([start, end]); + + Assert.Single(segments); + Assert.Equal(ParkourProfile.Sidewall, segments[0].ParkourProfile); + } + private static List BuildNodes(params (int x, int y, int z, MoveType moveUsed)[] raw) { var result = new List(raw.Length); diff --git a/MinecraftClient.Tests/Pathing/Moves/MoveParkourTests.cs b/MinecraftClient.Tests/Pathing/Moves/MoveParkourTests.cs index f6bf0493..9088bb88 100644 --- a/MinecraftClient.Tests/Pathing/Moves/MoveParkourTests.cs +++ b/MinecraftClient.Tests/Pathing/Moves/MoveParkourTests.cs @@ -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() { diff --git a/MinecraftClient/Pathing/Core/MoveResult.cs b/MinecraftClient/Pathing/Core/MoveResult.cs index 59045b48..d1c71e58 100644 --- a/MinecraftClient/Pathing/Core/MoveResult.cs +++ b/MinecraftClient/Pathing/Core/MoveResult.cs @@ -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; diff --git a/MinecraftClient/Pathing/Core/ParkourProfile.cs b/MinecraftClient/Pathing/Core/ParkourProfile.cs new file mode 100644 index 00000000..990ea68b --- /dev/null +++ b/MinecraftClient/Pathing/Core/ParkourProfile.cs @@ -0,0 +1,9 @@ +namespace MinecraftClient.Pathing.Core +{ + public enum ParkourProfile + { + None = 0, + Default = 1, + Sidewall = 2 + } +} diff --git a/MinecraftClient/Pathing/Core/PathNode.cs b/MinecraftClient/Pathing/Core/PathNode.cs index 1cab8d78..85ced9a6 100644 --- a/MinecraftClient/Pathing/Core/PathNode.cs +++ b/MinecraftClient/Pathing/Core/PathNode.cs @@ -15,6 +15,7 @@ namespace MinecraftClient.Pathing.Core public PathNode? Parent; public MoveType MoveUsed; + public ParkourProfile ParkourProfile; public int HeapIndex; public bool IsOpen; diff --git a/MinecraftClient/Pathing/Execution/PathSegment.cs b/MinecraftClient/Pathing/Execution/PathSegment.cs index f3b163a9..1eebceae 100644 --- a/MinecraftClient/Pathing/Execution/PathSegment.cs +++ b/MinecraftClient/Pathing/Execution/PathSegment.cs @@ -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; } diff --git a/MinecraftClient/Pathing/Execution/PathSegmentBuilder.cs b/MinecraftClient/Pathing/Execution/PathSegmentBuilder.cs index 4370068e..d7cba809 100644 --- a/MinecraftClient/Pathing/Execution/PathSegmentBuilder.cs +++ b/MinecraftClient/Pathing/Execution/PathSegmentBuilder.cs @@ -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 }; } diff --git a/MinecraftClient/Pathing/Moves/Impl/MoveParkour.cs b/MinecraftClient/Pathing/Moves/Impl/MoveParkour.cs index aa7fe159..09ff7cc0 100644 --- a/MinecraftClient/Pathing/Moves/Impl/MoveParkour.cs +++ b/MinecraftClient/Pathing/Moves/Impl/MoveParkour.cs @@ -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); } ///