//
// WalkManager.cs
//
// Copyright (c) František Boháček. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using NosSmooth.Core.Client;
using NosSmooth.Core.Commands.Walking;
using NosSmooth.Core.Errors;
using Remora.Results;
namespace NosSmooth.Extensions.Pathfinding;
///
/// The walk manager using pathfinding to walk to given position.
///
public class WalkManager
{
private readonly INostaleClient _client;
private readonly Pathfinder _pathfinder;
private readonly PathfinderState _state;
///
/// Initializes a new instance of the class.
///
/// The client.
/// The pathfinder.
/// The state.
public WalkManager(INostaleClient client, Pathfinder pathfinder, PathfinderState state)
{
_client = client;
_pathfinder = pathfinder;
_state = state;
}
///
/// Go to the given position.
///
///
/// Expect if the destination could not be reached.
/// Expect if the path could not be found.
///
/// The target x coordinate.
/// The target y coordinate.
/// Whether to allow user actions during the walk operation.
/// The cancellation token used for cancelling the operation.
/// The positions to walk pets to.
/// A result that may not succeed.
public async Task GoToAsync(short x, short y, bool allowUserActions = true, CancellationToken ct = default, params (int Selector, short TargetX, short TargetY)[] pets)
{
var pathResult = _pathfinder.FindPathFromCurrent(x, y);
if (!pathResult.IsSuccess)
{
return Result.FromError(pathResult);
}
if (pathResult.Entity.Parts.Count == 0)
{
return Result.FromSuccess();
}
var path = pathResult.Entity;
while (!path.ReachedEnd)
{
if (path.MapId != _state.MapId)
{
return new WalkNotFinishedError(_state.X, _state.Y, WalkUnfinishedReason.MapChanged);
}
var next = path.TakeForwardPath();
var walkResult = await _client.SendCommandAsync(new WalkCommand(next.X, next.Y, pets, 2, AllowUserCancel: allowUserActions), ct);
if (!walkResult.IsSuccess)
{
if (path.ReachedEnd && walkResult.Error is WalkNotFinishedError walkNotFinishedError
&& walkNotFinishedError.Reason == WalkUnfinishedReason.MapChanged)
{
return Result.FromSuccess();
}
if (_state.X == x && _state.Y == y)
{
return Result.FromSuccess();
}
return walkResult;
}
}
return Result.FromSuccess();
}
}