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