namespace NeonSprawl.Server.Game.PositionState; /// Pure movement validation for targets (NS-19). /// /// Precedence when multiple rules fail: , /// then , then . /// 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 = ""; 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; } }