namespace NeonSprawl.Server.Game.PositionState;
/// Pure movement validation for targets (NS-19).
///
/// Precedence when multiple rules fail: ,
/// then , then .
/// Vertical uses abs(ΔY), so descending (target Y lower than current) is allowed when the
/// drop is within — same as climbing.
///
public static class MoveCommandValidation
{
/// Returns false and sets when the move must be rejected.
public static bool TryValidate(
in PositionSnapshot from,
PositionVector to,
MovementValidationOptions rules,
out string reasonCode)
{
reasonCode = "";
if (rules.HorizontalStepEnabled)
{
var dx = to.X - from.X;
var dz = to.Z - from.Z;
var horizontal = Math.Sqrt((dx * dx) + (dz * dz));
if (horizontal > rules.MaxHorizontalStep)
{
reasonCode = MoveCommandReasonCodes.HorizontalStepExceeded;
return false;
}
}
var dy = Math.Abs(to.Y - from.Y);
if (dy > rules.MaxVerticalStep)
{
reasonCode = MoveCommandReasonCodes.VerticalStepExceeded;
return false;
}
if (rules.DistrictBoundsEnabled)
{
if (to.X < rules.DistrictMinX || to.X > rules.DistrictMaxX ||
to.Y < rules.DistrictMinY || to.Y > rules.DistrictMaxY ||
to.Z < rules.DistrictMinZ || to.Z > rules.DistrictMaxZ)
{
reasonCode = MoveCommandReasonCodes.OutOfBounds;
return false;
}
}
return true;
}
}