From 60baf8dfdae217778e2353fd302048d38b150aa6 Mon Sep 17 00:00:00 2001 From: Rutherther Date: Thu, 27 Jan 2022 20:25:49 +0100 Subject: [PATCH] feat(localclient): use take control command in local client --- .../PlayerWalkCommand.cs} | 41 ++-- .../Walk/Errors/WalkNotFinishedError.cs | 2 +- .../Walk/PlayerWalkCommandHandler.cs | 144 ++++++++++++++ .../CommandHandlers/Walk/WalkCancelReason.cs | 43 ----- .../Walk/WalkCommandHandler.cs | 97 ---------- .../Walk/WalkCommandHandlerOptions.cs | 14 +- .../Walk/WalkPacketResponder.cs | 58 ------ .../CommandHandlers/Walk/WalkStatus.cs | 177 ------------------ .../Walk/WalkUnfinishedReason.cs | 36 ++++ .../Extensions/ServiceCollectionExtensions.cs | 5 +- .../NosSmooth.LocalClient.csproj | 4 - .../NostaleLocalClient.cs | 32 +++- 12 files changed, 242 insertions(+), 411 deletions(-) rename Core/NosSmooth.Core/Commands/{WalkCommand.cs => Walking/PlayerWalkCommand.cs} (56%) create mode 100644 Local/NosSmooth.LocalClient/CommandHandlers/Walk/PlayerWalkCommandHandler.cs delete mode 100644 Local/NosSmooth.LocalClient/CommandHandlers/Walk/WalkCancelReason.cs delete mode 100644 Local/NosSmooth.LocalClient/CommandHandlers/Walk/WalkCommandHandler.cs delete mode 100644 Local/NosSmooth.LocalClient/CommandHandlers/Walk/WalkPacketResponder.cs delete mode 100644 Local/NosSmooth.LocalClient/CommandHandlers/Walk/WalkStatus.cs create mode 100644 Local/NosSmooth.LocalClient/CommandHandlers/Walk/WalkUnfinishedReason.cs diff --git a/Core/NosSmooth.Core/Commands/WalkCommand.cs b/Core/NosSmooth.Core/Commands/Walking/PlayerWalkCommand.cs similarity index 56% rename from Core/NosSmooth.Core/Commands/WalkCommand.cs rename to Core/NosSmooth.Core/Commands/Walking/PlayerWalkCommand.cs index 5c7f7cea1f9f335ec7a0f08748675b4818d42954..8e0ced30b30dbb9a17b0db5c1417f32a004a8478 100644 --- a/Core/NosSmooth.Core/Commands/WalkCommand.cs +++ b/Core/NosSmooth.Core/Commands/Walking/PlayerWalkCommand.cs @@ -1,16 +1,25 @@ -// -// WalkCommand.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. - -namespace NosSmooth.Core.Commands; - -/// -/// Command that moves the player to the specified target position. -/// May be used only in world. -/// -/// The x coordinate of the target position to move to. -/// The y coordinate of the target position to move to. -/// Whether to cancel the walk when the user clicks to move somewhere. -public record WalkCommand(ushort TargetX, ushort TargetY, bool CancelOnUserMove = true) : ICommand; \ No newline at end of file +// +// PlayerWalkCommand.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.Commands.Control; + +namespace NosSmooth.Core.Commands.Walking; + +/// +/// Command that moves the player to the specified target position. +/// May be used only in world. +/// +/// The x coordinate of the target position to move to. +/// The y coordinate of the target position to move to. +public record PlayerWalkCommand +( + ushort TargetX, + ushort TargetY, + bool CanBeCancelledByAnother = true, + bool WaitForCancellation = true, + bool AllowUserCancel = true, + bool CancelOnMapChange = true +) : ICommand, ITakeControlCommand; \ No newline at end of file diff --git a/Local/NosSmooth.LocalClient/CommandHandlers/Walk/Errors/WalkNotFinishedError.cs b/Local/NosSmooth.LocalClient/CommandHandlers/Walk/Errors/WalkNotFinishedError.cs index 81b4f889b2686e03b84560bd340949daae73fbcf..72cd86133309f7917de4df1127620e0b302bc8ec 100644 --- a/Local/NosSmooth.LocalClient/CommandHandlers/Walk/Errors/WalkNotFinishedError.cs +++ b/Local/NosSmooth.LocalClient/CommandHandlers/Walk/Errors/WalkNotFinishedError.cs @@ -14,5 +14,5 @@ namespace NosSmooth.LocalClient.CommandHandlers.Walk.Errors; /// The x coordinate where the player is. (if known) /// The y coordinate where the player is. (if known) /// -public record WalkNotFinishedError(int? X, int? Y, WalkCancelReason Reason) +public record WalkNotFinishedError(int? X, int? Y, WalkUnfinishedReason Reason) : ResultError($"Could not finish the walk to {X} {Y}, because {Reason}"); \ No newline at end of file diff --git a/Local/NosSmooth.LocalClient/CommandHandlers/Walk/PlayerWalkCommandHandler.cs b/Local/NosSmooth.LocalClient/CommandHandlers/Walk/PlayerWalkCommandHandler.cs new file mode 100644 index 0000000000000000000000000000000000000000..04c46435a5b1a584aae14e098e1d753df63b9202 --- /dev/null +++ b/Local/NosSmooth.LocalClient/CommandHandlers/Walk/PlayerWalkCommandHandler.cs @@ -0,0 +1,144 @@ +// +// PlayerWalkCommandHandler.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 Microsoft.Extensions.Options; +using NosSmooth.Core.Client; +using NosSmooth.Core.Commands; +using NosSmooth.Core.Commands.Control; +using NosSmooth.Core.Commands.Walking; +using NosSmooth.Core.Extensions; +using NosSmooth.LocalBinding.Objects; +using NosSmooth.LocalClient.CommandHandlers.Walk.Errors; +using Remora.Results; + +namespace NosSmooth.LocalClient.CommandHandlers.Walk; + +/// +/// Handles . +/// +public class PlayerWalkCommandHandler : ICommandHandler +{ + /// + /// Group that is used for . + /// + public const string PlayerWalkControlGroup = "PlayerWalk"; + + private readonly PlayerManagerBinding _playerManagerBinding; + private readonly INostaleClient _nostaleClient; + private readonly WalkCommandHandlerOptions _options; + + private ushort _x; + private ushort _y; + + /// + /// Initializes a new instance of the class. + /// + /// The character object binding. + /// The nostale client. + /// The options. + public PlayerWalkCommandHandler + ( + PlayerManagerBinding playerManagerBinding, + INostaleClient nostaleClient, + IOptions options + ) + { + _options = options.Value; + _playerManagerBinding = playerManagerBinding; + _nostaleClient = nostaleClient; + } + + /// + /// 1) If client called walk, cancel. + /// 2) If another walk command requested, cancel. + /// 3) If at the correct spot, cancel. + /// 4) If not walking for over x ms, cancel. + public async Task HandleCommand(PlayerWalkCommand command, CancellationToken ct = default) + { + _x = command.TargetX; + _y = command.TargetY; + + using CancellationTokenSource linked = CancellationTokenSource.CreateLinkedTokenSource(ct); + WalkUnfinishedReason? reason = null; + var takeControlCommand = command.CreateTakeControl + ( + PlayerWalkControlGroup, + WalkGrantedCallback, + (r) => + { + reason = r switch + { + ControlCancelReason.AnotherTask => WalkUnfinishedReason.AnotherTask, + ControlCancelReason.UserAction => WalkUnfinishedReason.UserAction, + _ => WalkUnfinishedReason.Unknown + }; + return Task.FromResult(Result.FromSuccess()); + } + ); + + var commandResult = await _nostaleClient.SendCommandAsync(takeControlCommand, ct); + if (!commandResult.IsSuccess) + { + return commandResult; + } + + if (reason is null && !IsAt(command.TargetX, command.TargetY)) + { + reason = WalkUnfinishedReason.PathNotFound; + } + + if (reason is null) + { + return Result.FromSuccess(); + } + + return new WalkNotFinishedError + ( + _playerManagerBinding.PlayerManager.X, + _playerManagerBinding.PlayerManager.Y, + (WalkUnfinishedReason)reason + ); + } + + private bool IsAtTarget() + { + return _playerManagerBinding.PlayerManager.TargetX == _playerManagerBinding.PlayerManager.Player.X + && _playerManagerBinding.PlayerManager.TargetY == _playerManagerBinding.PlayerManager.Player.Y; + } + + private bool IsAt(ushort x, ushort y) + { + return _playerManagerBinding.PlayerManager.Player.X == x && _playerManagerBinding.PlayerManager.Player.Y == y; + } + + private async Task WalkGrantedCallback(CancellationToken ct) + { + while (!ct.IsCancellationRequested) + { + var result = _playerManagerBinding.Walk(_x, _y); + if (!result.IsSuccess) + { + return Result.FromError(result); + } + + try + { + await Task.Delay(_options.CheckDelay, ct); + } + catch + { + // ignored + } + + if (IsAtTarget() || IsAt(_x, _y)) + { + return Result.FromSuccess(); + } + } + + return Result.FromSuccess(); // cancellation is handled in cancellation callback. + } +} \ No newline at end of file diff --git a/Local/NosSmooth.LocalClient/CommandHandlers/Walk/WalkCancelReason.cs b/Local/NosSmooth.LocalClient/CommandHandlers/Walk/WalkCancelReason.cs deleted file mode 100644 index 51cb1df437366b7b0806c89170b2013220008ed0..0000000000000000000000000000000000000000 --- a/Local/NosSmooth.LocalClient/CommandHandlers/Walk/WalkCancelReason.cs +++ /dev/null @@ -1,43 +0,0 @@ -// -// WalkCancelReason.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.Commands; - -namespace NosSmooth.LocalClient.CommandHandlers.Walk; - -/// -/// Reason of cancellation of . -/// -public enum WalkCancelReason -{ - /// - /// There was an unknown cancel reason. - /// - Unknown, - - /// - /// The user walked and CancelOnUserMove flag was set. - /// - UserWalked, - - /// - /// The map has changed during the walk was in progress. - /// - MapChanged, - - /// - /// The client was not walking for too long. - /// - NotWalkingTooLong, - - /// - /// The nostale walk function has returned false. - /// - /// - /// The player may be stunned or immobile. - /// - NosTaleReturnedFalse -} \ No newline at end of file diff --git a/Local/NosSmooth.LocalClient/CommandHandlers/Walk/WalkCommandHandler.cs b/Local/NosSmooth.LocalClient/CommandHandlers/Walk/WalkCommandHandler.cs deleted file mode 100644 index 58db073314557265cacac43d14db34cc020fd902..0000000000000000000000000000000000000000 --- a/Local/NosSmooth.LocalClient/CommandHandlers/Walk/WalkCommandHandler.cs +++ /dev/null @@ -1,97 +0,0 @@ -// -// WalkCommandHandler.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 Microsoft.Extensions.Options; -using NosSmooth.Core.Commands; -using NosSmooth.LocalBinding.Objects; -using NosSmooth.LocalClient.CommandHandlers.Walk.Errors; -using Remora.Results; - -namespace NosSmooth.LocalClient.CommandHandlers.Walk; - -/// -/// Handles . -/// -public class WalkCommandHandler : ICommandHandler -{ - private readonly PlayerManagerBinding _playerManagerBinding; - private readonly WalkStatus _walkStatus; - private readonly WalkCommandHandlerOptions _options; - - /// - /// Initializes a new instance of the class. - /// - /// The character object binding. - /// The walk status. - /// The options. - public WalkCommandHandler(PlayerManagerBinding playerManagerBinding, WalkStatus walkStatus, IOptions options) - { - _options = options.Value; - _playerManagerBinding = playerManagerBinding; - _walkStatus = walkStatus; - } - - /// - /// 1) If client called walk, cancel. - /// 2) If another walk command requested, cancel. - /// 3) If at the correct spot, cancel. - /// 4) If not walking for over x ms, cancel. - public async Task HandleCommand(WalkCommand command, CancellationToken ct = default) - { - CancellationTokenSource linked = CancellationTokenSource.CreateLinkedTokenSource(ct); - ct = linked.Token; - await _walkStatus.SetWalking(linked, command.TargetX, command.TargetY, command.CancelOnUserMove); - while (!ct.IsCancellationRequested) - { - var walkResult = _playerManagerBinding.Walk(command.TargetX, command.TargetY); - if (!walkResult.IsSuccess) - { - try - { - await _walkStatus.CancelWalkingAsync(ct: ct); - } - catch - { - // ignored, just for cancellation - } - - return Result.FromError(walkResult); - } - - if (walkResult.Entity == false) - { - await _walkStatus.CancelWalkingAsync(WalkCancelReason.NosTaleReturnedFalse); - return new WalkNotFinishedError(_walkStatus.CurrentX, _walkStatus.CurrentY, WalkCancelReason.NosTaleReturnedFalse); - } - try - { - await Task.Delay(_options.CheckDelay, ct); - } - catch - { - // ignored - } - - if (_walkStatus.IsFinished) - { - return Result.FromSuccess(); - } - - if (_walkStatus.Error is not null) - { - return new WalkNotFinishedError(_walkStatus.CurrentX, _walkStatus.CurrentY, (WalkCancelReason)_walkStatus.Error); - } - - if ((DateTimeOffset.Now - _walkStatus.LastWalkTime).TotalMilliseconds > _options.NotWalkingTooLongTrigger) - { - await _walkStatus.CancelWalkingAsync(WalkCancelReason.NotWalkingTooLong); - return new WalkNotFinishedError(_walkStatus.CurrentX, _walkStatus.CurrentY, WalkCancelReason.NotWalkingTooLong); - } - } - - return new WalkNotFinishedError(_walkStatus.CurrentX, _walkStatus.CurrentY, WalkCancelReason.Unknown); - } -} \ No newline at end of file diff --git a/Local/NosSmooth.LocalClient/CommandHandlers/Walk/WalkCommandHandlerOptions.cs b/Local/NosSmooth.LocalClient/CommandHandlers/Walk/WalkCommandHandlerOptions.cs index 723f0499fa0517a0a7cd269d5b6a7a4c56e0e80e..4acc353d97d68a5c10f7177bc762fcbf14d2504f 100644 --- a/Local/NosSmooth.LocalClient/CommandHandlers/Walk/WalkCommandHandlerOptions.cs +++ b/Local/NosSmooth.LocalClient/CommandHandlers/Walk/WalkCommandHandlerOptions.cs @@ -7,25 +7,17 @@ namespace NosSmooth.LocalClient.CommandHandlers.Walk { /// - /// Options for . + /// Options for . /// public class WalkCommandHandlerOptions { /// - /// After what time to trigger not walking for too long error in milliseconds. - /// - /// - /// Use at least 2000 to avoid problems with false triggers. - /// - public int NotWalkingTooLongTrigger { get; set; } = 2000; - - /// - /// The command handler sleeps for this duration, then checks new info in milliseconds. + /// The command handler sleeps for this duration, then checks for new info. Unit is milliseconds. /// /// /// The operation is done with a cancellation token, if there is an outer event, then it can be faster. /// Walk function is called again as well after this delay. /// - public int CheckDelay { get; set; } = 100; + public int CheckDelay { get; set; } = 50; } } diff --git a/Local/NosSmooth.LocalClient/CommandHandlers/Walk/WalkPacketResponder.cs b/Local/NosSmooth.LocalClient/CommandHandlers/Walk/WalkPacketResponder.cs deleted file mode 100644 index 71ccb148c64f4356e91b1144b0eea5346d73708b..0000000000000000000000000000000000000000 --- a/Local/NosSmooth.LocalClient/CommandHandlers/Walk/WalkPacketResponder.cs +++ /dev/null @@ -1,58 +0,0 @@ -// -// WalkPacketResponder.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.Commands; -using NosSmooth.Core.Packets; -using NosSmooth.Packets.Client.Movement; -using NosSmooth.Packets.Server.Maps; -using Remora.Results; - -namespace NosSmooth.LocalClient.CommandHandlers.Walk; - -/// -/// Responds to to manage . -/// -public class WalkPacketResponder : IPacketResponder, IPacketResponder -{ - private readonly WalkStatus _walkStatus; - - /// - /// Initializes a new instance of the class. - /// - /// The walk status. - public WalkPacketResponder(WalkStatus walkStatus) - { - _walkStatus = walkStatus; - } - - /// - public async Task Respond(PacketEventArgs packet, CancellationToken ct = default) - { - if (_walkStatus.IsWalking) - { - _walkStatus.UpdateWalkTime(packet.Packet.PositionX, packet.Packet.PositionY); - if (packet.Packet.PositionX == _walkStatus.TargetX && packet.Packet.PositionY == _walkStatus.TargetY) - { - await _walkStatus.FinishWalkingAsync(ct); - } - } - - return Result.FromSuccess(); - } - - /// - public async Task Respond(PacketEventArgs packet, CancellationToken ct = default) - { - if (_walkStatus.IsWalking) - { - await _walkStatus.CancelWalkingAsync(WalkCancelReason.MapChanged, ct); - } - - return Result.FromSuccess(); - } - - // TODO: handle teleport on map -} diff --git a/Local/NosSmooth.LocalClient/CommandHandlers/Walk/WalkStatus.cs b/Local/NosSmooth.LocalClient/CommandHandlers/Walk/WalkStatus.cs deleted file mode 100644 index ec4feda200cbcca50d606114b9bbeba92adb0d53..0000000000000000000000000000000000000000 --- a/Local/NosSmooth.LocalClient/CommandHandlers/Walk/WalkStatus.cs +++ /dev/null @@ -1,177 +0,0 @@ -// -// WalkStatus.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.LocalBinding.Objects; - -namespace NosSmooth.LocalClient.CommandHandlers.Walk; - -/// -/// The status for . -/// -public class WalkStatus -{ - private readonly PlayerManagerBinding _playerManagerBinding; - private readonly SemaphoreSlim _semaphore; - private CancellationTokenSource? _walkingCancellation; - private bool _userCanCancel; - private bool _walkHooked; - - /// - /// Initializes a new instance of the class. - /// - /// The character binding. - public WalkStatus(PlayerManagerBinding playerManagerBinding) - { - _playerManagerBinding = playerManagerBinding; - _semaphore = new SemaphoreSlim(1, 1); - } - - /// - /// Gets if the walk command is in progress. - /// - public bool IsWalking => _walkingCancellation is not null; - - /// - /// Gets if the current walk command has been finished. - /// - public bool IsFinished { get; private set; } - - /// - /// Gets the last time of walk. - /// - public DateTimeOffset LastWalkTime { get; private set; } - - /// - /// Gets the walk target x coordinate. - /// - public int TargetX { get; private set; } - - /// - /// Gets the walk target y coordinate. - /// - public int TargetY { get; private set; } - - /// - /// Gets the characters current x coordinate. - /// - public int? CurrentX { get; private set; } - - /// - /// Gets the characters current y coordinate. - /// - public int? CurrentY { get; private set; } - - /// - /// Gets the error cause of cancellation. - /// - public WalkCancelReason? Error { get; private set; } - - /// - /// Update the time of last walk, called on WalkPacket. - /// - /// The current characters x coordinate. - /// The current characters y coordinate. - internal void UpdateWalkTime(int currentX, int currentY) - { - CurrentX = currentX; - CurrentY = currentY; - LastWalkTime = DateTimeOffset.Now; - } - - /// - /// Sets that the walk command handler is handling walk command. - /// - /// The cancellation token source for cancelling the operation. - /// The walk target x coordinate. - /// The walk target y coordinate. - /// Whether the user can cancel the operation by moving elsewhere. - /// A task that may or may not have succeeded. - internal async Task SetWalking(CancellationTokenSource cancellationTokenSource, int targetX, int targetY, bool userCanCancel) - { - await _semaphore.WaitAsync(cancellationTokenSource.Token); - if (IsWalking) - { - // Cannot call CancelWalkingAsync as that would result in a deadlock - _walkingCancellation?.Cancel(); - _walkingCancellation = null; - } - - IsFinished = false; - Error = null; - TargetX = targetX; - TargetY = targetY; - CurrentX = CurrentY = null; - _walkingCancellation = cancellationTokenSource; - LastWalkTime = DateTime.Now; - _userCanCancel = userCanCancel; - - if (!_walkHooked) - { - _playerManagerBinding.WalkCall += OnCharacterWalked; - _walkHooked = true; - } - - _semaphore.Release(); - } - - /// - /// Cancel the walking token. - /// - /// The cause. - /// The cancellation token for cancelling the operation. - /// A task that may or may not have succeeded. - internal async Task CancelWalkingAsync(WalkCancelReason? error = null, CancellationToken ct = default) - { - await _semaphore.WaitAsync(ct); - if (!IsWalking) - { - _semaphore.Release(); - return; - } - - Error = error; - try - { - _walkingCancellation?.Cancel(); - } - catch - { - // ignored - } - - _walkingCancellation = null; - _semaphore.Release(); - } - - /// - /// Finish the walk successfully. - /// - /// The cancellation token for cancelling the operation. - /// A task that may or may not have succeeded. - internal async Task FinishWalkingAsync(CancellationToken ct = default) - { - await _semaphore.WaitAsync(ct); - IsFinished = true; - _semaphore.Release(); - await CancelWalkingAsync(ct: ct); - } - - private bool OnCharacterWalked(ushort x, ushort y) - { - if (IsWalking) - { - if (!_userCanCancel) - { - return false; - } - - CancelWalkingAsync(WalkCancelReason.UserWalked) - .GetAwaiter() - .GetResult(); - } - return true; - } -} \ No newline at end of file diff --git a/Local/NosSmooth.LocalClient/CommandHandlers/Walk/WalkUnfinishedReason.cs b/Local/NosSmooth.LocalClient/CommandHandlers/Walk/WalkUnfinishedReason.cs new file mode 100644 index 0000000000000000000000000000000000000000..51e228e6862c83b888eb783f171da97953276c83 --- /dev/null +++ b/Local/NosSmooth.LocalClient/CommandHandlers/Walk/WalkUnfinishedReason.cs @@ -0,0 +1,36 @@ +// +// WalkUnfinishedReason.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. + +namespace NosSmooth.LocalClient.CommandHandlers.Walk; + +/// +/// Reason for not finishing a walk. +/// +public enum WalkUnfinishedReason +{ + /// + /// There was an unknown unfinished reason. + /// + Unknown, + + /// + /// The client could not find path to the given location. + /// + /// + /// The user walked just some part of the path. + /// + PathNotFound, + + /// + /// The user has took an action that has cancelled the walk. + /// + UserAction, + + /// + /// There was another walk action that cancelled this one. + /// + AnotherTask +} \ No newline at end of file diff --git a/Local/NosSmooth.LocalClient/Extensions/ServiceCollectionExtensions.cs b/Local/NosSmooth.LocalClient/Extensions/ServiceCollectionExtensions.cs index 47d882c7b6b201e281a560c9085aede4df77cda6..03d8fe5683d65998dea8d4a99d89aa56a29ff3c4 100644 --- a/Local/NosSmooth.LocalClient/Extensions/ServiceCollectionExtensions.cs +++ b/Local/NosSmooth.LocalClient/Extensions/ServiceCollectionExtensions.cs @@ -28,9 +28,8 @@ public static class ServiceCollectionExtensions serviceCollection.AddNostaleCore(); serviceCollection.AddNostaleBindings(); serviceCollection - .AddCommandHandler() - .AddPacketResponder() - .AddSingleton(); + .AddTakeControlCommand() + .AddCommandHandler(); serviceCollection.TryAddSingleton(); serviceCollection.TryAddSingleton(p => p.GetRequiredService()); diff --git a/Local/NosSmooth.LocalClient/NosSmooth.LocalClient.csproj b/Local/NosSmooth.LocalClient/NosSmooth.LocalClient.csproj index 88fee3e2c267555215386439616151444196a699..b3fe80dc4c48b4d05ae6087faec63796f65c76b0 100644 --- a/Local/NosSmooth.LocalClient/NosSmooth.LocalClient.csproj +++ b/Local/NosSmooth.LocalClient/NosSmooth.LocalClient.csproj @@ -18,8 +18,4 @@ - - - - diff --git a/Local/NosSmooth.LocalClient/NostaleLocalClient.cs b/Local/NosSmooth.LocalClient/NostaleLocalClient.cs index c6178e43ce81991add2fa6fcae82c7d39da3e406..99cbd2940d5fbdeb6c372db65b140c6d282bb95c 100644 --- a/Local/NosSmooth.LocalClient/NostaleLocalClient.cs +++ b/Local/NosSmooth.LocalClient/NostaleLocalClient.cs @@ -9,9 +9,11 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using NosSmooth.Core.Client; using NosSmooth.Core.Commands; +using NosSmooth.Core.Commands.Control; using NosSmooth.Core.Extensions; using NosSmooth.Core.Packets; using NosSmooth.LocalBinding.Objects; +using NosSmooth.LocalBinding.Structs; using NosSmooth.Packets; using NosSmooth.Packets.Errors; using NosSmooth.PacketSerializer.Abstractions.Attributes; @@ -29,6 +31,8 @@ namespace NosSmooth.LocalClient; public class NostaleLocalClient : BaseNostaleClient { private readonly NetworkBinding _networkBinding; + private readonly PlayerManagerBinding _playerManagerBinding; + private readonly ControlCommands _controlCommands; private readonly IPacketSerializer _packetSerializer; private readonly IPacketHandler _packetHandler; private readonly ILogger _logger; @@ -41,6 +45,8 @@ public class NostaleLocalClient : BaseNostaleClient /// Initializes a new instance of the class. /// /// The network binding. + /// The player manager binding. + /// The control commands. /// The command processor. /// The packet serializer. /// The packet handler. @@ -50,6 +56,8 @@ public class NostaleLocalClient : BaseNostaleClient public NostaleLocalClient ( NetworkBinding networkBinding, + PlayerManagerBinding playerManagerBinding, + ControlCommands controlCommands, CommandProcessor commandProcessor, IPacketSerializer packetSerializer, IPacketHandler packetHandler, @@ -61,6 +69,8 @@ public class NostaleLocalClient : BaseNostaleClient { _options = options.Value; _networkBinding = networkBinding; + _playerManagerBinding = playerManagerBinding; + _controlCommands = controlCommands; _packetSerializer = packetSerializer; _packetHandler = packetHandler; _logger = logger; @@ -75,6 +85,9 @@ public class NostaleLocalClient : BaseNostaleClient _networkBinding.PacketSend += SendCallback; _networkBinding.PacketReceive += ReceiveCallback; + _playerManagerBinding.FollowEntityCall += FollowEntity; + _playerManagerBinding.WalkCall += Walk; + try { await Task.Delay(-1, stopRequested); @@ -86,6 +99,8 @@ public class NostaleLocalClient : BaseNostaleClient _networkBinding.PacketSend -= SendCallback; _networkBinding.PacketReceive -= ReceiveCallback; + _playerManagerBinding.FollowEntityCall -= FollowEntity; + _playerManagerBinding.WalkCall -= Walk; return Result.FromSuccess(); } @@ -183,4 +198,19 @@ public class NostaleLocalClient : BaseNostaleClient _logger.LogResultError(result); } } -} + + private bool FollowEntity(MapBaseObj? obj) + { + Task.Run + ( + async () => await _controlCommands.CancelAsync + (ControlCommandsFilter.UserCancellable, false, (CancellationToken)_stopRequested!) + ); + return true; + } + + private bool Walk(ushort x, ushort y) + { + return _controlCommands.AllowUserActions; + } +} \ No newline at end of file