~ruther/NosSmooth

ad1078c592d416b0a88aa4b85da94274fbc53be5 — Rutherther 2 years ago 57e494d
feat(game): add friends processing
M Core/NosSmooth.Game/Data/Chat/Friend.cs => Core/NosSmooth.Game/Data/Chat/Friend.cs +4 -12
@@ 4,24 4,16 @@
//  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.Relations;

namespace NosSmooth.Game.Data.Chat;

/// <summary>
/// Represents character's friend.
/// </summary>
public class Friend
public record Friend(long PlayerId, CharacterRelationType RelationType)
{
    /// <summary>
    /// The id of the character.
    /// </summary>
    public long CharacterId { get; internal set; }

    // <summary>
    // The type of the relation.
    // </summary>
    // public CharacterRelationType RelationType { get; internal set; }

    /// <summary>
    /// The name of the character.
    /// </summary>
    public string? CharacterName { get; internal set; }


@@ 29,5 21,5 @@ public class Friend
    /// <summary>
    /// Whether the friend is connected to the server.
    /// </summary>
    public bool IsOnline { get; internal set; }
    public bool IsConnected { get; internal set; }
}
\ No newline at end of file

M Core/NosSmooth.Game/Extensions/ServiceCollectionExtensions.cs => Core/NosSmooth.Game/Extensions/ServiceCollectionExtensions.cs +1 -0
@@ 42,6 42,7 @@ public static class ServiceCollectionExtensions
            .AddPacketResponder<PlayerSkillResponder>()
            .AddPacketResponder<WalkResponder>()
            .AddPacketResponder<SkillUsedResponder>()
            .AddPacketResponder<FriendInitResponder>()
            .AddPacketResponder<InventoryInitResponder>()
            .AddPacketResponder<GroupInitResponder>()
            .AddPacketResponder<AoeSkillUsedResponder>()

M Core/NosSmooth.Game/Game.cs => Core/NosSmooth.Game/Game.cs +28 -0
@@ 189,6 189,34 @@ public class Game : IStatefulEntity
    }

    /// <summary>
    /// Creates the friends if it is null, or updates the current friends.
    /// </summary>
    /// <param name="create">The function for creating the friends.</param>
    /// <param name="update">The function for updating the friends.</param>
    /// <param name="releaseSemaphore">Whether to release the semaphore used for changing the friends.</param>
    /// <param name="ct">The cancellation token for cancelling the operation.</param>
    /// <returns>The updated friends.</returns>
    internal async Task<IReadOnlyList<Friend>?> CreateOrUpdateFriendsAsync
    (
        Func<IReadOnlyList<Friend>?> create,
        Func<IReadOnlyList<Friend>, IReadOnlyList<Friend>?> update,
        bool releaseSemaphore = true,
        CancellationToken ct = default
    )
    {
        return await CreateOrUpdateAsync
        (
            GameSemaphoreType.Friends,
            () => Friends,
            c => Friends = c,
            create,
            update,
            releaseSemaphore,
            ct
        );
    }

    /// <summary>
    /// Creates the group if it is null, or updates the current group.
    /// </summary>
    /// <param name="create">The function for creating the group.</param>

A Core/NosSmooth.Game/PacketHandlers/Relations/FriendInitResponder.cs => Core/NosSmooth.Game/PacketHandlers/Relations/FriendInitResponder.cs +83 -0
@@ 0,0 1,83 @@
//
//  FriendInitResponder.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.Chat;
using NosSmooth.Packets.Enums.Relations;
using NosSmooth.Packets.Server.Relations;
using Remora.Results;

namespace NosSmooth.Game.PacketHandlers.Relations;

/// <summary>
/// A friends initialization responder.
/// </summary>
public class FriendInitResponder : IPacketResponder<FInfoPacket>, IPacketResponder<FInitPacket>
{
    private readonly Game _game;

    /// <summary>
    /// Initializes a new instance of the <see cref="FriendInitResponder"/> class.
    /// </summary>
    /// <param name="game">The game.</param>
    public FriendInitResponder(Game game)
    {
        _game = game;
    }

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

        await _game.CreateOrUpdateFriendsAsync
        (
            () => null,
            friends => friends
                .Select(
                    x =>
                    {
                        if (x.PlayerId == packet.PlayerId)
                        {
                            x.IsConnected = packet.IsConnected;
                            x.CharacterName = packet.Name;
                        }

                        return x;
                    })
                .ToList(),
            ct: ct
        );

        return Result.FromSuccess();
    }

    /// <inheritdoc />
    public async Task<Result> Respond(PacketEventArgs<FInitPacket> packetArgs, CancellationToken ct = default)
    {
        var packet = packetArgs.Packet;
        var friends = packet.FriendSubPackets
            .Select
            (
                x => new Friend(x.PlayerId, x.RelationType ?? CharacterRelationType.Blocked)
                {
                    PlayerId = x.PlayerId,
                    CharacterName = x.Name,
                    IsConnected = x.IsConnected
                }
            )
            .ToList();

        await _game.CreateOrUpdateFriendsAsync
        (
            () => friends,
            _ => friends,
            ct: ct
        );

        return Result.FromSuccess();
    }
}
\ No newline at end of file

Do not follow this link