Minecraft-Console-Client/MinecraftClient/Pathing/Moves/Impl/MoveDiagonalDescend.cs
BruceChen 285c3000c3 feat: add diagonal ascend/descend moves, fix pitch, smooth look angles
- Add MoveDiagonalAscend and MoveDiagonalDescend for "corner" moves:
  step diagonally around a wall edge while ascending/descending 1 block.
  Requires at least one intermediate cardinal direction to be passable.

- Fix pitch calculation: look toward target's eye level (same height
  delta as feet delta) instead of subtracting eye height, which caused
  the player to stare at the ground during flat walks.

- Add Yaw/Pitch smoothing via SmoothYaw/SmoothPitch in TemplateHelper.
  Max 35 deg/tick for yaw, 25 deg/tick for pitch. Prevents instant
  camera snaps between path segments while still being responsive
  enough for sprint-jumps and tight maneuvers.

- Apply smoothing to all five action templates (Walk, Ascend, Descend,
  Climb, SprintJump).

Made-with: Cursor
2026-04-12 18:43:32 +00:00

77 lines
2.5 KiB
C#

using MinecraftClient.Mapping;
using MinecraftClient.Pathing.Core;
namespace MinecraftClient.Pathing.Moves.Impl
{
/// <summary>
/// Walk diagonally (1 block in X and Z) and drop 1 block.
/// Handles the "corner drop" pattern: step around a wall edge and land
/// one block lower on a platform that is diagonally adjacent.
/// </summary>
public sealed class MoveDiagonalDescend : IMove
{
public MoveType Type => MoveType.Descend;
public int XOffset { get; }
public int ZOffset { get; }
public bool DynamicY => false;
public MoveDiagonalDescend(int xOffset, int zOffset)
{
XOffset = xOffset;
ZOffset = zOffset;
}
public void Calculate(CalculationContext ctx, int x, int y, int z, ref MoveResult result)
{
int destX = x + XOffset;
int destZ = z + ZOffset;
int destY = y - 1;
// Destination must have ground, body space, and head space
if (!ctx.CanWalkOn(destX, destY - 1, destZ))
{
result.SetImpossible();
return;
}
if (!ctx.CanWalkThrough(destX, destY, destZ) ||
!ctx.CanWalkThrough(destX, destY + 1, destZ))
{
result.SetImpossible();
return;
}
Material landOn = ctx.GetMaterial(destX, destY - 1, destZ);
if (MoveHelper.IsHazardous(landOn))
{
result.SetImpossible();
return;
}
// Don't descend from climbable blocks
Material fromDown = ctx.GetMaterial(x, y - 1, z);
if (fromDown.CanBeClimbedOn())
{
result.SetImpossible();
return;
}
// At least one of the two intermediate cardinal directions must be passable
// (player needs clearance to cut the corner).
bool pathViaX = ctx.CanWalkThrough(x + XOffset, y, z) &&
ctx.CanWalkThrough(x + XOffset, y + 1, z);
bool pathViaZ = ctx.CanWalkThrough(x, y, z + ZOffset) &&
ctx.CanWalkThrough(x, y + 1, z + ZOffset);
if (!pathViaX && !pathViaZ)
{
result.SetImpossible();
return;
}
double cost = ActionCosts.WalkOffBlock * ActionCosts.DiagonalMultiplier
+ ActionCosts.FallCost(1);
result.Set(destX, destY, destZ, cost);
}
}
}