mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2026-08-15 13:04:36 +00:00
fix: stabilize descend landings after braking
This commit is contained in:
parent
33ff02042c
commit
6e4cf4a10e
2 changed files with 99 additions and 5 deletions
|
|
@ -2,6 +2,7 @@ using MinecraftClient.Mapping;
|
|||
using MinecraftClient.Pathing.Core;
|
||||
using MinecraftClient.Pathing.Execution;
|
||||
using MinecraftClient.Pathing.Execution.Templates;
|
||||
using MinecraftClient.Physics;
|
||||
using Xunit;
|
||||
|
||||
namespace MinecraftClient.Tests.Pathing.Execution;
|
||||
|
|
@ -81,4 +82,57 @@ public sealed class GroundedTemplateConvergenceTests
|
|||
Assert.True(state == TemplateState.Complete, $"state={state} finalPos={finalPos} vel={physics.DeltaMovement}");
|
||||
Assert.True(TemplateFootingHelper.IsFootprintInsideTargetBlock(finalPos, segment.End));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DescendTemplate_FinalStop_WithWallAndMisalignedYaw_CompletesOnLandingBlock()
|
||||
{
|
||||
World world = FlatWorldTestBuilder.CreateStoneFloor(min: 198, max: 204);
|
||||
FlatWorldTestBuilder.ClearBox(world, 198, 79, 198, 204, 84, 202);
|
||||
FlatWorldTestBuilder.FillSolid(world, 201, 79, 199, 203, 79, 201);
|
||||
FlatWorldTestBuilder.SetSolid(world, 200, 80, 200);
|
||||
FlatWorldTestBuilder.SetSolid(world, 200, 80, 199);
|
||||
FlatWorldTestBuilder.SetSolid(world, 201, 80, 199);
|
||||
FlatWorldTestBuilder.SetSolid(world, 202, 80, 199);
|
||||
FlatWorldTestBuilder.SetSolid(world, 201, 81, 199);
|
||||
FlatWorldTestBuilder.SetSolid(world, 202, 81, 199);
|
||||
|
||||
var segment = new PathSegment
|
||||
{
|
||||
Start = new Location(200.5, 81, 200.5),
|
||||
End = new Location(201.5, 80, 200.5),
|
||||
MoveType = MoveType.Descend,
|
||||
ExitTransition = PathTransitionType.FinalStop
|
||||
};
|
||||
|
||||
var template = new DescendTemplate(segment, null);
|
||||
var physics = TemplateSimulationRunner.CreateGroundedPhysics(segment.Start, yaw: 0f);
|
||||
|
||||
var input = new MovementInput();
|
||||
var trace = new List<string>();
|
||||
TemplateState state = TemplateState.InProgress;
|
||||
Location finalPos = segment.Start;
|
||||
for (int tick = 0; tick < 240; tick++)
|
||||
{
|
||||
input.Reset();
|
||||
Location pos = new(physics.Position.X, physics.Position.Y, physics.Position.Z);
|
||||
state = template.Tick(pos, physics, input, world);
|
||||
if (tick < 20 || state != TemplateState.InProgress || !physics.OnGround)
|
||||
{
|
||||
trace.Add($"tick={tick} state={state} pos={pos} vel={physics.DeltaMovement} onGround={physics.OnGround} input(F={input.Forward},B={input.Back},S={input.Sprint})");
|
||||
}
|
||||
|
||||
if (state != TemplateState.InProgress)
|
||||
{
|
||||
finalPos = new Location(physics.Position.X, physics.Position.Y, physics.Position.Z);
|
||||
break;
|
||||
}
|
||||
|
||||
physics.ApplyInput(input);
|
||||
physics.Tick(world);
|
||||
finalPos = new Location(physics.Position.X, physics.Position.Y, physics.Position.Z);
|
||||
}
|
||||
|
||||
Assert.True(state == TemplateState.Complete, $"state={state} finalPos={finalPos} vel={physics.DeltaMovement}\n{string.Join('\n', trace)}");
|
||||
Assert.True(TemplateFootingHelper.IsFootprintInsideTargetBlock(finalPos, segment.End));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using MinecraftClient.Mapping;
|
||||
using MinecraftClient.Pathing.Execution;
|
||||
using MinecraftClient.Physics;
|
||||
|
||||
namespace MinecraftClient.Pathing.Execution.Templates
|
||||
|
|
@ -12,6 +13,8 @@ namespace MinecraftClient.Pathing.Execution.Templates
|
|||
/// </summary>
|
||||
public sealed class DescendTemplate : IActionTemplate
|
||||
{
|
||||
private const float PreDropYawToleranceDeg = 12f;
|
||||
|
||||
public Location ExpectedStart { get; }
|
||||
public Location ExpectedEnd { get; }
|
||||
|
||||
|
|
@ -61,10 +64,14 @@ namespace MinecraftClient.Pathing.Execution.Templates
|
|||
|
||||
if (physics.OnGround && Math.Abs(dy) < (_hasFallen ? 1.0 : 0.6))
|
||||
{
|
||||
if (horizDistSq > 0.01)
|
||||
TransitionBrakingDecision decision = TransitionBrakingPlanner.Plan(_segment, _nextSegment, pos, physics, world);
|
||||
if (horizDistSq > 0.01 && !decision.HoldBack)
|
||||
physics.Yaw = TemplateHelper.SmoothYaw(physics.Yaw, targetYaw);
|
||||
|
||||
GroundedSegmentController.Apply(_segment, _nextSegment, pos, physics, input, world);
|
||||
TemplateHelper.ApplyDecision(input, decision);
|
||||
if (decision.HoldBack)
|
||||
TemplateHelper.FaceSegmentHeading(physics, _segment);
|
||||
|
||||
if (GroundedSegmentController.ShouldComplete(_segment, pos, physics))
|
||||
return TemplateState.Complete;
|
||||
}
|
||||
|
|
@ -79,12 +86,45 @@ namespace MinecraftClient.Pathing.Execution.Templates
|
|||
else if (horizDistSq > 0.01)
|
||||
{
|
||||
physics.Yaw = TemplateHelper.SmoothYaw(physics.Yaw, targetYaw);
|
||||
input.Forward = true;
|
||||
if (_needsSprint)
|
||||
input.Sprint = true;
|
||||
if (_hasFallen || YawDifference(physics.Yaw, targetYaw) <= PreDropYawToleranceDeg)
|
||||
{
|
||||
if (!_hasFallen && !_needsSprint && ShouldCoastOffLedge(pos))
|
||||
{
|
||||
// For short descends into a stop or turn, release forward near the lip
|
||||
// so the landing stays on the intended support instead of overshooting it.
|
||||
}
|
||||
else if (!_hasFallen && !_needsSprint)
|
||||
{
|
||||
GroundedSegmentController.Apply(_segment, _nextSegment, pos, physics, input, world);
|
||||
}
|
||||
else
|
||||
{
|
||||
input.Forward = true;
|
||||
if (_needsSprint)
|
||||
input.Sprint = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TemplateState.InProgress;
|
||||
}
|
||||
|
||||
private bool ShouldCoastOffLedge(Location pos)
|
||||
{
|
||||
if (_segment.ExitTransition == PathTransitionType.ContinueStraight)
|
||||
return false;
|
||||
|
||||
double remaining = (_segment.End.X - pos.X) * _segment.HeadingX
|
||||
+ (_segment.End.Z - pos.Z) * _segment.HeadingZ;
|
||||
return remaining <= 0.55;
|
||||
}
|
||||
|
||||
private static float YawDifference(float current, float target)
|
||||
{
|
||||
float delta = target - current;
|
||||
while (delta > 180f) delta -= 360f;
|
||||
while (delta < -180f) delta += 360f;
|
||||
return Math.Abs(delta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue