// // NostaleLocalClient.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.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using NosSmooth.Core.Client; using NosSmooth.Core.Commands; using NosSmooth.Core.Packets; using NosSmoothCore; using Remora.Results; namespace NosSmooth.LocalClient; /// /// The local nostale client. /// /// /// Client used for living in the same process as NostaleClientX.exe. /// It hooks the send and receive packet methods. /// public class NostaleLocalClient : BaseNostaleClient { private readonly IPacketSerializer _packetSerializer; private readonly IPacketHandler _packetHandler; private readonly ILogger _logger; private readonly NosClient _client; private readonly LocalClientOptions _options; private readonly IPacketInterceptor? _interceptor; /// /// Initializes a new instance of the class. /// /// The command processor. /// The packet serializer. /// The packet handler. /// The logger. /// The options for the client. /// The dependency injection provider. /// The nostale managed client. public NostaleLocalClient ( CommandProcessor commandProcessor, IPacketSerializer packetSerializer, IPacketHandler packetHandler, ILogger logger, IOptions options, IServiceProvider provider, NosClient client ) : base(commandProcessor, packetSerializer) { _options = options.Value; _packetSerializer = packetSerializer; _packetHandler = packetHandler; _logger = logger; _client = client; if (_options.AllowIntercept) { _interceptor = provider.GetRequiredService(); } } /// public override async Task RunAsync(CancellationToken stopRequested = default) { _logger.LogInformation("Starting local client"); NetworkCallback receiveCallback = ReceiveCallback; NetworkCallback sendCallback = SendCallback; _client.GetNetwork().SetReceiveCallback(receiveCallback); _client.GetNetwork().SetSendCallback(sendCallback); _logger.LogInformation("Packet methods hooked successfully"); try { await Task.Delay(-1, stopRequested); } catch { } _client.ResetHooks(); return Result.FromSuccess(); } /// public override Task ReceivePacketAsync(string packetString, CancellationToken ct = default) { ReceivePacket(packetString); return Task.FromResult(Result.FromSuccess()); } /// public override Task SendPacketAsync(string packetString, CancellationToken ct = default) { SendPacket(packetString); return Task.FromResult(Result.FromSuccess()); } private bool ReceiveCallback(string packet) { if (_options.AllowIntercept) { if (_interceptor is null) { throw new InvalidOperationException("The interceptor cannot be null if interception is allowed."); } return _interceptor.InterceptReceive(ref packet); } // TODO: handlers _logger.LogInformation($"Received packet {packet}"); return true; } private bool SendCallback(string packet) { if (_options.AllowIntercept) { if (_interceptor is null) { throw new InvalidOperationException("The interceptor cannot be null if interception is allowed."); } return _interceptor.InterceptSend(ref packet); } // TODO: handlers _logger.LogInformation($"Sent packet {packet}"); return true; } private void SendPacket(string packetString) { _client.GetNetwork().SendPacket(packetString); } private void ReceivePacket(string packetString) { _client.GetNetwork().ReceivePacket(packetString); } }