~ruther/NosSmooth

da0563066d4dc554f5078a44c4ced1a733f68063 — Rutherther 2 years ago 4194156
feat(pathfinding): add MateWalkTo to WalkManager
1 files changed, 88 insertions(+), 9 deletions(-)

M Extensions/NosSmooth.Extensions.Pathfinding/WalkManager.cs
M Extensions/NosSmooth.Extensions.Pathfinding/WalkManager.cs => Extensions/NosSmooth.Extensions.Pathfinding/WalkManager.cs +88 -9
@@ 7,6 7,7 @@
using NosSmooth.Core.Client;
using NosSmooth.Core.Commands.Walking;
using NosSmooth.Core.Errors;
using NosSmooth.Extensions.Pathfinding.Errors;
using Remora.Results;

namespace NosSmooth.Extensions.Pathfinding;


@@ 34,7 35,7 @@ public class WalkManager
    }

    /// <summary>
    /// Go to the given position.
    /// Move character to the given position.
    /// </summary>
    /// <remarks>
    /// Expect <see cref="WalkNotFinishedError"/> if the destination could not be reached.


@@ 44,31 45,109 @@ public class WalkManager
    /// <param name="y">The target y coordinate.</param>
    /// <param name="allowUserActions">Whether to allow user actions during the walk operation.</param>
    /// <param name="ct">The cancellation token used for cancelling the operation.</param>
    /// <param name="pets">The positions to walk pets to.</param>
    /// <returns>A result that may not succeed.</returns>
    public async Task<Result> GoToAsync(short x, short y, bool allowUserActions = true, CancellationToken ct = default, params (int Selector, short TargetX, short TargetY)[] pets)
    public async Task<Result> PlayerGoToAsync
    (
        short x,
        short y,
        bool allowUserActions = true,
        CancellationToken ct = default
    )
    {
        var pathResult = _pathfinder.FindPathFromCurrent(x, y);
        if (!pathResult.IsSuccess)
        if (!pathResult.IsDefined(out var path))
        {
            return Result.FromError(pathResult);
        }

        if (pathResult.Entity.Parts.Count == 0)
        return await TakePath
        (
            path,
            _state.Character,
            (x, y) => _client.SendCommandAsync
            (
                new WalkCommand
                (
                    x,
                    y,
                    2,
                    AllowUserCancel: allowUserActions
                ),
                ct
            )
        );
    }

    /// <summary>
    /// Move pet to the given position.
    /// </summary>
    /// <remarks>
    /// Expect <see cref="WalkNotFinishedError"/> if the destination could not be reached.
    /// Expect <see cref="NotFoundError"/> if the path could not be found.
    /// </remarks>
    /// <param name="mateId">The id of the mate to move.</param>
    /// <param name="x">The target x coordinate.</param>
    /// <param name="y">The target y coordinate.</param>
    /// <param name="allowUserActions">Whether to allow user actions during the walk operation.</param>
    /// <param name="ct">The cancellation token used for cancelling the operation.</param>
    /// <returns>A result that may not succeed.</returns>
    public async Task<Result> MateWalkToAsync
    (
        long mateId,
        short x,
        short y,
        bool allowUserActions = true,
        CancellationToken ct = default
    )
    {
        if (!_state.Entities.TryGetValue(mateId, out var entityState) || entityState == _state.Character)
        {
            return new EntityStateNotFoundError(mateId);
        }

        var pathResult = _pathfinder.FindPathFromEntity(mateId, x, y);

        if (!pathResult.IsDefined(out var path))
        {
            return Result.FromError(pathResult);
        }

        return await TakePath
        (
            path,
            entityState,
            (x, y) => _client.SendCommandAsync
            (
                new MateWalkCommand
                (
                    mateId,
                    x,
                    y,
                    2,
                    AllowUserCancel: allowUserActions
                ),
                ct
            )
        );
    }

    private async Task<Result> TakePath(Path path, EntityState state, Func<short, short, Task<Result>> walkFunc)
    {
        if (path.Parts.Count == 0)
        {
            return Result.FromSuccess();
        }
        var target = path.Parts.Last();

        var path = pathResult.Entity;
        while (!path.ReachedEnd)
        {
            if (path.MapId != _state.MapId)
            {
                return new WalkNotFinishedError(_state.X, _state.Y, WalkUnfinishedReason.MapChanged);
                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);
            var walkResult = await walkFunc(next.X, next.Y);
            if (!walkResult.IsSuccess)
            {
                if (path.ReachedEnd && walkResult.Error is WalkNotFinishedError walkNotFinishedError


@@ 77,7 156,7 @@ public class WalkManager
                    return Result.FromSuccess();
                }

                if (_state.X == x && _state.Y == y)
                if (state.X == target.X && state.Y == target.Y)
                {
                    return Result.FromSuccess();
                }

Do not follow this link