~ruther/NosSmooth

d8ff21a89f5b3bd55ace4a1e08cf6ee89688c852 — František Boháček 3 years ago 8fc4cd1
fix: samples to work with NosSmooth packets
M Samples/InterceptNameChanger/NameChangeInterceptor.cs => Samples/InterceptNameChanger/NameChangeInterceptor.cs +15 -7
@@ 5,10 5,11 @@
//  Licensed under the MIT license. See LICENSE file in the project root for full license information.

using Microsoft.Extensions.Logging;
using NosCore.Packets.Enumerations;
using NosCore.Packets.ServerPackets.Chats;
using NosSmooth.Core.Client;
using NosSmooth.LocalClient;
using NosSmooth.Packets.Enums;
using NosSmooth.Packets.Enums.Chat;
using NosSmooth.Packets.Packets.Server.Chat;

namespace InterceptNameChanger
{


@@ 39,11 40,18 @@ namespace InterceptNameChanger
            {
                _name = packet.Substring(5).Replace(" ", "⠀"); // Mind the symbols!
                _logger.LogInformation("Name changed to {Name}", _name);
                _client.ReceivePacketAsync(new SayPacket()
                {
                    Message = $"Name changed to {_name}, change map for it to take effect.",
                    Type = SayColorType.Red
                }).GetAwaiter().GetResult();
                _client.ReceivePacketAsync
                    (
                        new SayPacket
                        (
                            EntityType.Map,
                            1,
                            SayColor.Red,
                            $"Name changed to {_name}, change map for it to take effect."
                        )
                    )
                    .GetAwaiter()
                    .GetResult();
                return false;
            }


M Samples/InterceptNameChanger/NameChanger.cs => Samples/InterceptNameChanger/NameChanger.cs +17 -20
@@ 7,13 7,12 @@
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using NosCore.Packets.Enumerations;
using NosCore.Packets.ServerPackets.Chats;
using NosCore.Shared.Enumerations;
using NosSmooth.Core.Client;
using NosSmooth.Core.Packets;
using NosSmooth.LocalClient;
using NosSmooth.LocalClient.Extensions;
using NosSmooth.Packets.Enums;
using NosSmooth.Packets.Enums.Chat;
using NosSmooth.Packets.Packets.Server.Chat;

namespace InterceptNameChanger
{


@@ 32,31 31,29 @@ namespace InterceptNameChanger
                .AddLocalClient()

                // .AddPacketResponder<SayResponder>()
                .AddLogging(b =>
                {
                    b.ClearProviders();
                    b.AddConsole();
                    b.SetMinimumLevel(LogLevel.Debug);
                })
                .AddLogging
                (
                    b =>
                    {
                        b.ClearProviders();
                        b.AddConsole();
                        b.SetMinimumLevel(LogLevel.Debug);
                    }
                )
                .Configure<LocalClientOptions>(o => o.AllowIntercept = true)
                .AddSingleton<IPacketInterceptor, NameChangeInterceptor>()
                .BuildServiceProvider();

            var dummy1 = provider.GetRequiredService<PacketSerializerProvider>().ServerSerializer;
            var dummy2 = provider.GetRequiredService<PacketSerializerProvider>().ClientSerializer;

            var logger = provider.GetRequiredService<ILogger<NameChanger>>();
            logger.LogInformation("Hello world from NameChanger!");

            var client = provider.GetRequiredService<INostaleClient>();

            var sayResult = await client.ReceivePacketAsync(new SayPacket()
            {
                Message = "The name may be changed by typing #{NewName} into the chat.",
                VisualType = VisualType.Map,
                Type = SayColorType.Red,
                VisualId = 1,
            });
            var sayResult = await client.ReceivePacketAsync
            (
                new SayPacket
                    (EntityType.Map, 1, SayColor.Red, "The name may be changed by typing #{NewName} into the chat.")
            );

            if (!sayResult.IsSuccess)
            {

M Samples/WalkCommands/ChatPacketInterceptor.cs => Samples/WalkCommands/ChatPacketInterceptor.cs +114 -106
@@ 1,106 1,114 @@
//
//  ChatPacketInterceptor.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 NosCore.Packets.Enumerations;
using NosCore.Packets.ServerPackets.Chats;
using NosSmooth.Core.Client;
using NosSmooth.Core.Commands;
using NosSmooth.Core.Extensions;
using NosSmooth.LocalClient;
using Remora.Results;
using WalkCommands.Commands;

namespace WalkCommands;

/// <summary>
/// Interceptor of chat commands.
/// </summary>
public class ChatPacketInterceptor : IPacketInterceptor
{
    private readonly IServiceProvider _provider;
    private readonly ILogger<ChatPacketInterceptor> _logger;
    private readonly INostaleClient _client;

    /// <summary>
    /// Initializes a new instance of the <see cref="ChatPacketInterceptor"/> class.
    /// </summary>
    /// <param name="provider">The service provider.</param>
    /// <param name="logger">The logger.</param>
    /// <param name="client">The nostale client.</param>
    public ChatPacketInterceptor(IServiceProvider provider, ILogger<ChatPacketInterceptor> logger, INostaleClient client)
    {
        _provider = provider;
        _logger = logger;
        _client = client;
    }

    /// <inheritdoc />
    public bool InterceptSend(ref string packet)
    {
        if (packet.StartsWith($"say #"))
        {
            var packetString = packet;
            Task.Run(async () =>
            {
                try
                {
                    await ExecuteCommand(packetString.Substring(5));
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Could not execute command.");
                }
            });
            return false;
        }

        return true;
    }

    /// <inheritdoc />
    public bool InterceptReceive(ref string packet)
    {
        return true;
    }

    private async Task ExecuteCommand(string command)
    {
        await _client.ReceivePacketAsync(new SayPacket
        {
            Type = SayColorType.Green, Message = $"Handling a command {command}."
        });

        var splitted = command.Split(new[] { ' ' });
        using var scope = _provider.CreateScope();
        Result result;
        switch (splitted[0])
        {
            case "walk":
                var walkCommand = scope.ServiceProvider.GetRequiredService<Commands.WalkCommands>();
                result = await walkCommand.HandleWalkToAsync(int.Parse(splitted[1]), int.Parse(splitted[2]), splitted.Length > 3 ? bool.Parse(splitted[3]) : true);
                break;
            case "detach":
                var detachCommand = scope.ServiceProvider.GetRequiredService<DetachCommand>();
                result = await detachCommand.HandleDetach();
                break;
            default:
                await _client.ReceivePacketAsync(new SayPacket
                {
                    Type = SayColorType.Red, Message = $"The command {splitted[0]} was not found."
                });
                return;
        }

        if (!result.IsSuccess)
        {
            _logger.LogError("Could not execute a command");
            _logger.LogResultError(result);
        }
    }
}
\ No newline at end of file
//
//  ChatPacketInterceptor.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.Extensions;
using NosSmooth.LocalClient;
using NosSmooth.Packets.Enums;
using NosSmooth.Packets.Enums.Chat;
using NosSmooth.Packets.Packets.Server.Chat;
using Remora.Results;
using WalkCommands.Commands;

namespace WalkCommands;

/// <summary>
/// Interceptor of chat commands.
/// </summary>
public class ChatPacketInterceptor : IPacketInterceptor
{
    private readonly IServiceProvider _provider;
    private readonly ILogger<ChatPacketInterceptor> _logger;
    private readonly INostaleClient _client;

    /// <summary>
    /// Initializes a new instance of the <see cref="ChatPacketInterceptor"/> class.
    /// </summary>
    /// <param name="provider">The service provider.</param>
    /// <param name="logger">The logger.</param>
    /// <param name="client">The nostale client.</param>
    public ChatPacketInterceptor
        (IServiceProvider provider, ILogger<ChatPacketInterceptor> logger, INostaleClient client)
    {
        _provider = provider;
        _logger = logger;
        _client = client;
    }

    /// <inheritdoc />
    public bool InterceptSend(ref string packet)
    {
        if (packet.StartsWith($"say #"))
        {
            var packetString = packet;
            Task.Run
            (
                async () =>
                {
                    try
                    {
                        await ExecuteCommand(packetString.Substring(5));
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, "Could not execute command.");
                    }
                }
            );
            return false;
        }

        return true;
    }

    /// <inheritdoc />
    public bool InterceptReceive(ref string packet)
    {
        return true;
    }

    private async Task ExecuteCommand(string command)
    {
        await _client.ReceivePacketAsync
            (new SayPacket(EntityType.Map, 1, SayColor.Green, $"Handling a command {command}."));

        var splitted = command.Split(new[] { ' ' });
        using var scope = _provider.CreateScope();
        Result result;
        switch (splitted[0])
        {
            case "walk":
                var walkCommand = scope.ServiceProvider.GetRequiredService<Commands.WalkCommands>();
                result = await walkCommand.HandleWalkToAsync
                (
                    int.Parse(splitted[1]),
                    int.Parse(splitted[2]),
                    splitted.Length > 3 ? bool.Parse(splitted[3]) : true
                );
                break;
            case "detach":
                var detachCommand = scope.ServiceProvider.GetRequiredService<DetachCommand>();
                result = await detachCommand.HandleDetach();
                break;
            default:
                await _client.ReceivePacketAsync
                (
                    new SayPacket(EntityType.Map, 1, SayColor.Green, $"The command {splitted[0]} was not found.")
                );
                return;
        }

        if (!result.IsSuccess)
        {
            _logger.LogError("Could not execute a command");
            _logger.LogResultError(result);
        }
    }
}

M Samples/WalkCommands/Commands/DetachCommand.cs => Samples/WalkCommands/Commands/DetachCommand.cs +51 -53
@@ 1,53 1,51 @@
//
//  DetachCommand.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 NosCore.Packets.Enumerations;
using NosCore.Packets.ServerPackets.Chats;
using NosSmooth.Core.Client;
using Remora.Results;

namespace WalkCommands.Commands;

/// <summary>
/// Group for detaching command that detaches the dll.
/// </summary>
public class DetachCommand
{
    private readonly CancellationTokenSource _dllStop;
    private readonly INostaleClient _client;

    /// <summary>
    /// Initializes a new instance of the <see cref="DetachCommand"/> class.
    /// </summary>
    /// <param name="dllStop">The cancellation token source to stop the client.</param>
    /// <param name="client">The nostale client.</param>
    public DetachCommand(CancellationTokenSource dllStop, INostaleClient client)
    {
        _dllStop = dllStop;
        _client = client;
    }

    /// <summary>
    /// Detach the dll.
    /// </summary>
    /// <returns>A result that may or may not have succeeded.</returns>
    public async Task<Result> HandleDetach()
    {
        var receiveResult = await _client.ReceivePacketAsync(new SayPacket
        {
            Message = "Going to detach!",
            Type = SayColorType.Green
        });

        if (!receiveResult.IsSuccess)
        {
            return receiveResult;
        }

        _dllStop.Cancel();
        return Result.FromSuccess();
    }
}
\ No newline at end of file
//
//  DetachCommand.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.Packets.Enums;
using NosSmooth.Packets.Enums.Chat;
using NosSmooth.Packets.Packets.Server.Chat;
using Remora.Results;

namespace WalkCommands.Commands;

/// <summary>
/// Group for detaching command that detaches the dll.
/// </summary>
public class DetachCommand
{
    private readonly CancellationTokenSource _dllStop;
    private readonly INostaleClient _client;

    /// <summary>
    /// Initializes a new instance of the <see cref="DetachCommand"/> class.
    /// </summary>
    /// <param name="dllStop">The cancellation token source to stop the client.</param>
    /// <param name="client">The nostale client.</param>
    public DetachCommand(CancellationTokenSource dllStop, INostaleClient client)
    {
        _dllStop = dllStop;
        _client = client;
    }

    /// <summary>
    /// Detach the dll.
    /// </summary>
    /// <returns>A result that may or may not have succeeded.</returns>
    public async Task<Result> HandleDetach()
    {
        var receiveResult = await _client.ReceivePacketAsync
            (new SayPacket(EntityType.Map, 1, SayColor.Green, "Going to detach!"));

        if (!receiveResult.IsSuccess)
        {
            return receiveResult;
        }

        _dllStop.Cancel();
        return Result.FromSuccess();
    }
}

M Samples/WalkCommands/Commands/WalkCommands.cs => Samples/WalkCommands/Commands/WalkCommands.cs +77 -77
@@ 1,77 1,77 @@
//
//  WalkCommands.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 NosCore.Packets.Enumerations;
using NosCore.Packets.ServerPackets.Chats;
using NosSmooth.Core.Client;
using NosSmooth.Core.Commands;
using Remora.Results;

namespace WalkCommands.Commands;

/// <summary>
/// Represents command group for walking.
/// </summary>
public class WalkCommands
{
    private readonly INostaleClient _client;

    /// <summary>
    /// Initializes a new instance of the <see cref="WalkCommands"/> class.
    /// </summary>
    /// <param name="client">The nostale client.</param>
    public WalkCommands(INostaleClient client)
    {
        _client = client ?? throw new ArgumentNullException(nameof(client));
    }

    /// <summary>
    /// Attempts to walk the character to the specified lcoation.
    /// </summary>
    /// <param name="x">The x coordinate.</param>
    /// <param name="y">The y coordinate.</param>
    /// <param name="isCancellable">Whether the user can cancel the operation.</param>
    /// <param name="ct">The cancellation token for cancelling the operation.</param>
    /// <returns>A result that may or may not have succeeded.</returns>
    public async Task<Result> HandleWalkToAsync
    (
        int x,
        int y,
        bool isCancellable = true,
        CancellationToken ct = default
    )
    {
        var receiveResult = await _client.ReceivePacketAsync
        (
            new SayPacket
            {
                Type = SayColorType.Red, Message = $"Going to walk to {x} {y}"
            },
            ct
        );

        if (!receiveResult.IsSuccess)
        {
            return receiveResult;
        }

        var command = new WalkCommand(x, y, isCancellable);
        var walkResult = await _client.SendCommandAsync(command, ct);
        if (!walkResult.IsSuccess)
        {
            return walkResult;
        }

        return await _client.ReceivePacketAsync
        (
            new SayPacket
            {
                Type = SayColorType.Red, Message = "Walk has finished successfully."
            },
            ct
        );
    }
}
\ No newline at end of file
//
//  WalkCommands.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;
using NosSmooth.Packets.Enums;
using NosSmooth.Packets.Enums.Chat;
using NosSmooth.Packets.Packets.Server.Chat;
using Remora.Results;

namespace WalkCommands.Commands;

/// <summary>
/// Represents command group for walking.
/// </summary>
public class WalkCommands
{
    private readonly INostaleClient _client;

    /// <summary>
    /// Initializes a new instance of the <see cref="WalkCommands"/> class.
    /// </summary>
    /// <param name="client">The nostale client.</param>
    public WalkCommands(INostaleClient client)
    {
        _client = client ?? throw new ArgumentNullException(nameof(client));
    }

    /// <summary>
    /// Attempts to walk the character to the specified lcoation.
    /// </summary>
    /// <param name="x">The x coordinate.</param>
    /// <param name="y">The y coordinate.</param>
    /// <param name="isCancellable">Whether the user can cancel the operation.</param>
    /// <param name="ct">The cancellation token for cancelling the operation.</param>
    /// <returns>A result that may or may not have succeeded.</returns>
    public async Task<Result> HandleWalkToAsync
    (
        int x,
        int y,
        bool isCancellable = true,
        CancellationToken ct = default
    )
    {
        var receiveResult = await _client.ReceivePacketAsync
        (
            new SayPacket(EntityType.Map, 1, SayColor.Red, $"Going to walk to {x} {y}."),
            ct
        );

        if (!receiveResult.IsSuccess)
        {
            return receiveResult;
        }

        var command = new WalkCommand(x, y, isCancellable);
        var walkResult = await _client.SendCommandAsync(command, ct);
        if (!walkResult.IsSuccess)
        {
            await _client.ReceivePacketAsync
            (
                new SayPacket(EntityType.Map, 1, SayColor.Red, "Could not finish walking."),
                ct
            );
            return walkResult;
        }

        return await _client.ReceivePacketAsync
        (
            new SayPacket(EntityType.Map, 1, SayColor.Red, "Walk has finished successfully."),
            ct
        );
    }
}

M Tests/NosSmooth.Packets.Tests/Converters/Packets/InPacketConverterTests.cs => Tests/NosSmooth.Packets.Tests/Converters/Packets/InPacketConverterTests.cs +2 -1
@@ 4,6 4,7 @@
//  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 System;
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
using NosSmooth.Packets.Attributes;


@@ 13,8 14,8 @@ using NosSmooth.Packets.Enums.Entities;
using NosSmooth.Packets.Enums.Players;
using NosSmooth.Packets.Extensions;
using NosSmooth.Packets.Packets.Server.Entities;
using NosSmooth.Packets.Packets.Server.Entities.Generated;
using NosSmooth.Packets.Packets.Server.Players;
using NosSmooth.Packets.Packets.Server.Skills;
using NosSmooth.Packets.Packets.Server.Weapons;
using Xunit;


Do not follow this link