Ahmedramadan24's picture
Add src/SilkroadBot.Navigation/Interfaces/IPathfinding.cs
5797d5e verified
using SilkroadBot.Domain.Models;
namespace SilkroadBot.Navigation.Interfaces;
/// <summary>
/// Abstract pathfinding algorithm interface.
/// Allows NavMesh, A*, Dijkstra, or any other algorithm to be plugged in.
/// </summary>
public interface IPathfindingAlgorithm
{
/// <summary>Algorithm name.</summary>
string Name { get; }
/// <summary>Find a path between two world positions.</summary>
Task<PathResult> FindPathAsync(WorldPosition start, WorldPosition end, PathfindingOptions? options = null);
/// <summary>Check if a position is traversable.</summary>
bool IsPositionWalkable(WorldPosition position);
/// <summary>Get the nearest walkable position to the given point.</summary>
WorldPosition GetNearestWalkablePosition(WorldPosition position);
}
/// <summary>
/// Map data provider interface for loading navigation data.
/// </summary>
public interface IMapDataProvider
{
/// <summary>Load navigation data for a region.</summary>
Task<RegionNavData?> LoadRegionAsync(short regionId);
/// <summary>Check if navigation data is available for a region.</summary>
bool HasRegion(short regionId);
/// <summary>Get all available region IDs.</summary>
IReadOnlyList<short> GetAvailableRegions();
}
/// <summary>
/// Navigation data for a single map region.
/// </summary>
public class RegionNavData
{
public short RegionId { get; init; }
public int Width { get; init; }
public int Height { get; init; }
public byte[,] WalkabilityGrid { get; init; } = new byte[0, 0];
public List<NavNode> Nodes { get; init; } = new();
public List<NavEdge> Edges { get; init; } = new();
}
/// <summary>
/// A node in the navigation graph.
/// </summary>
public record NavNode(int Id, float X, float Y, float Z, bool IsWalkable = true);
/// <summary>
/// An edge connecting two navigation nodes.
/// </summary>
public record NavEdge(int FromNodeId, int ToNodeId, float Cost);
/// <summary>
/// Result of a pathfinding operation.
/// </summary>
public record PathResult
{
public bool Success { get; init; }
public IReadOnlyList<WorldPosition> Waypoints { get; init; } = Array.Empty<WorldPosition>();
public double TotalDistance { get; init; }
public TimeSpan ComputeTime { get; init; }
public string? ErrorMessage { get; init; }
public static PathResult Failed(string reason) => new() { Success = false, ErrorMessage = reason };
}
/// <summary>
/// Options for pathfinding calculations.
/// </summary>
public record PathfindingOptions
{
public bool AllowDiagonal { get; init; } = true;
public double MaxDistance { get; init; } = double.MaxValue;
public int MaxIterations { get; init; } = 10000;
public bool SmoothPath { get; init; } = true;
public double WaypointSpacing { get; init; } = 10.0;
}