~ruther/NosSmooth

5aff1615840d40361f11b6ea773b034a99711cbd — Rutherther 2 years ago 33544d7
feat(game): add dialog handling, dialog opened event
A Core/NosSmooth.Game/Apis/DialogHandler.cs => Core/NosSmooth.Game/Apis/DialogHandler.cs +56 -0
@@ 0,0 1,56 @@
//
//  DialogHandler.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.Game.Data.Dialogs;
using Remora.Results;

namespace NosSmooth.Game.Apis;

/// <summary>
/// Handles accepting and denying of dialogs.
/// </summary>
public class DialogHandler
{
    private readonly INostaleClient _client;

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

    /// <summary>
    /// Accept the operation the dialog does.
    /// </summary>
    /// <param name="dialog">The opened dialog.</param>
    /// <param name="ct">The cancellation token used for cancelling the operation.</param>
    /// <returns>A result that may or may not have succeeded.</returns>
    public Task<Result> AcceptAsync(Dialog dialog, CancellationToken ct = default)
        => _client.SendPacketAsync(dialog.AcceptCommand, ct);

    /// <summary>
    /// Try to deny the operation the dialog does.
    /// </summary>
    /// <remarks>
    /// Some dialogs do not allow denying, they are just ignored instead.
    /// </remarks>
    /// <param name="dialog">The opened dialog.</param>
    /// <param name="ct">The cancellation token used for cancelling the operation.</param>
    /// <returns>A result that may or may not have succeeded.</returns>
    public Task<Result> DenyAsync(Dialog dialog, CancellationToken ct = default)
    {
        if (dialog.DenyCommand is null)
        {
            return Task.FromResult(Result.FromSuccess());
        }

        return _client.SendPacketAsync(dialog.DenyCommand, ct);
    }
}
\ No newline at end of file

M Core/NosSmooth.Game/Data/Dialogs/Dialog.cs => Core/NosSmooth.Game/Data/Dialogs/Dialog.cs +5 -2
@@ 4,6 4,9 @@
//  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.Packets.Enums;
using OneOf;

namespace NosSmooth.Game.Data.Dialogs;

/// <summary>


@@ 14,7 17,7 @@ namespace NosSmooth.Game.Data.Dialogs;
public record Dialog
(
    string AcceptCommand,

    // OneOf<Game18NConstString, string> Message,
    string? DenyCommand,
    OneOf<string, Game18NConstString> Message,
    IReadOnlyList<string> Parameters
);
\ No newline at end of file

A Core/NosSmooth.Game/Events/Ui/DialogOpenedEvent.cs => Core/NosSmooth.Game/Events/Ui/DialogOpenedEvent.cs +11 -0
@@ 0,0 1,11 @@
//
//  DialogOpenedEvent.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.Game.Data.Dialogs;

namespace NosSmooth.Game.Events.Ui;

public record DialogOpenedEvent(Dialog Dialog) : IGameEvent;
\ No newline at end of file

M Core/NosSmooth.Game/Extensions/ServiceCollectionExtensions.cs => Core/NosSmooth.Game/Extensions/ServiceCollectionExtensions.cs +1 -0
@@ 68,6 68,7 @@ public static class ServiceCollectionExtensions
            .AddPacketResponder<EqResponder>();

        serviceCollection
            .AddTransient<DialogHandler>()
            .AddTransient<UnsafeMapApi>()
            .AddTransient<UnsafeInventoryApi>()
            .AddTransient<UnsafeMateApi>()

A Core/NosSmooth.Game/PacketHandlers/Ui/DialogOpenResponder.cs => Core/NosSmooth.Game/PacketHandlers/Ui/DialogOpenResponder.cs +147 -0
@@ 0,0 1,147 @@
//
//  DialogOpenResponder.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.Packets;
using NosSmooth.Game.Data.Dialogs;
using NosSmooth.Game.Events.Core;
using NosSmooth.Game.Events.Ui;
using NosSmooth.Packets.Enums;
using NosSmooth.Packets.Server.UI;
using Remora.Results;

namespace NosSmooth.Game.PacketHandlers.Ui;

/// <summary>
/// A responder to dialog events that calls DialogOpen.
/// </summary>
public class DialogOpenResponder : IPacketResponder<QnamlPacket>, IPacketResponder<Qnamli2Packet>,
    IPacketResponder<QnaPacket>, IPacketResponder<DlgPacket>, IPacketResponder<DlgiPacket>
{
    private readonly EventDispatcher _eventDispatcher;

    /// <summary>
    /// Initializes a new instance of the <see cref="DialogOpenResponder"/> class.
    /// </summary>
    /// <param name="eventDispatcher">The event dispatcher.</param>
    public DialogOpenResponder(EventDispatcher eventDispatcher)
    {
        _eventDispatcher = eventDispatcher;

    }

    /// <inheritdoc />
    public Task<Result> Respond(PacketEventArgs<QnamlPacket> packetArgs, CancellationToken ct = default)
    {
        var packet = packetArgs.Packet;
        if (packet.Type != QnamlType.Dialog)
        {
            return Task.FromResult(Result.FromSuccess());
        }

        return _eventDispatcher.DispatchEvent
        (
            new DialogOpenedEvent
            (
                new Dialog
                (
                    packet.AcceptCommand,
                    null,
                    packet.Message,
                    Array.Empty<string>()
                )
            ),
            ct
        );
    }

    /// <inheritdoc />
    public Task<Result> Respond(PacketEventArgs<Qnamli2Packet> packetArgs, CancellationToken ct = default)
    {
        var packet = packetArgs.Packet;
        if (packet.Type != QnamlType.Dialog)
        {
            return Task.FromResult(Result.FromSuccess());
        }

        return _eventDispatcher.DispatchEvent
        (
            new DialogOpenedEvent
            (
                new Dialog
                (
                    packet.AcceptCommand,
                    null,
                    packet.MessageConst,
                    packet.Parameters
                )
            ),
            ct
        );
    }

    /// <inheritdoc />
    public Task<Result> Respond(PacketEventArgs<QnaPacket> packetArgs, CancellationToken ct = default)
    {
        var packet = packetArgs.Packet;

        return _eventDispatcher.DispatchEvent
        (
            new DialogOpenedEvent
            (
                new Dialog
                (
                    packet.AcceptCommand,
                    null,
                    packet.Message,
                    Array.Empty<string>()
                )
            ),
            ct
        );
    }

    /// <inheritdoc />
    public Task<Result> Respond(PacketEventArgs<DlgPacket> packetArgs, CancellationToken ct = default)
    {
        var packet = packetArgs.Packet;

        return _eventDispatcher.DispatchEvent
        (
            new DialogOpenedEvent
            (
                new Dialog
                (
                    packet.AcceptCommand,
                    packet.DenyCommand,
                    packet.Message,
                    Array.Empty<string>()
                )
            ),
            ct
        );
    }

    /// <inheritdoc />
    public Task<Result> Respond(PacketEventArgs<DlgiPacket> packetArgs, CancellationToken ct = default)
    {
        var packet = packetArgs.Packet;

        return _eventDispatcher.DispatchEvent
        (
            new DialogOpenedEvent
            (
                new Dialog
                (
                    packet.AcceptCommand,
                    packet.DenyCommand,
                    packet.MessageConst,
                    packet.Parameters
                )
            ),
            ct
        );
    }
}
\ No newline at end of file

Do not follow this link