From 8f7c60d23d6b045eb9daae93c62d3f339472d6b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franti=C5=A1ek=20Boh=C3=A1=C4=8Dek?= Date: Sat, 14 Jan 2023 11:38:34 +0100 Subject: [PATCH] feat(game): add raid handling --- Core/NosSmooth.Game/Data/Raids/Raid.cs | 17 ++- .../NosSmooth.Game/Data/Raids/RaidProgress.cs | 17 +++ Core/NosSmooth.Game/Data/Raids/RaidState.cs | 52 ++++++++ .../NosSmooth.Game/Data/Social/GroupMember.cs | 2 +- .../Events/Raids/RaidFinishedEvent.cs | 11 ++ .../Events/Raids/RaidJoinedEvent.cs | 11 ++ .../Events/Raids/RaidStateChangedEvent.cs | 16 +++ .../Extensions/ServiceCollectionExtensions.cs | 46 ++++++- Core/NosSmooth.Game/Game.cs | 54 +++++++++ .../PacketHandlers/Raids/RaidBfResponder.cs | 69 +++++++++++ .../PacketHandlers/Raids/RaidMbfResponder.cs | 53 ++++++++ .../PacketHandlers/Raids/RaidResponder.cs | 114 ++++++++++++++++++ .../PacketHandlers/Raids/RbossResponder.cs | 80 ++++++++++++ .../PacketHandlers/Raids/RdlstResponder.cs | 98 +++++++++++++++ .../Enums/Raids/RaidBfPacketType.cs | 25 ++++ 15 files changed, 657 insertions(+), 8 deletions(-) create mode 100644 Core/NosSmooth.Game/Data/Raids/RaidProgress.cs create mode 100644 Core/NosSmooth.Game/Data/Raids/RaidState.cs create mode 100644 Core/NosSmooth.Game/Events/Raids/RaidFinishedEvent.cs create mode 100644 Core/NosSmooth.Game/Events/Raids/RaidJoinedEvent.cs create mode 100644 Core/NosSmooth.Game/Events/Raids/RaidStateChangedEvent.cs create mode 100644 Core/NosSmooth.Game/PacketHandlers/Raids/RaidBfResponder.cs create mode 100644 Core/NosSmooth.Game/PacketHandlers/Raids/RaidMbfResponder.cs create mode 100644 Core/NosSmooth.Game/PacketHandlers/Raids/RaidResponder.cs create mode 100644 Core/NosSmooth.Game/PacketHandlers/Raids/RbossResponder.cs create mode 100644 Core/NosSmooth.Game/PacketHandlers/Raids/RdlstResponder.cs create mode 100644 Packets/NosSmooth.Packets/Enums/Raids/RaidBfPacketType.cs diff --git a/Core/NosSmooth.Game/Data/Raids/Raid.cs b/Core/NosSmooth.Game/Data/Raids/Raid.cs index ba8fb9b..61a3371 100644 --- a/Core/NosSmooth.Game/Data/Raids/Raid.cs +++ b/Core/NosSmooth.Game/Data/Raids/Raid.cs @@ -4,9 +4,24 @@ // 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.Entities; +using NosSmooth.Game.Data.Social; +using NosSmooth.Packets.Enums.Raids; + namespace NosSmooth.Game.Data.Raids; /// /// Represents nostale raid. /// -public record Raid(); \ No newline at end of file +public record Raid +( + RaidType Type, + RaidState State, + short MinimumLevel, + short MaximumLevel, + GroupMember? Leader, + RaidProgress? Progress, + Monster? Boss, + IReadOnlyList? Bosses, + IReadOnlyList? Members +); \ No newline at end of file diff --git a/Core/NosSmooth.Game/Data/Raids/RaidProgress.cs b/Core/NosSmooth.Game/Data/Raids/RaidProgress.cs new file mode 100644 index 0000000..35d05a6 --- /dev/null +++ b/Core/NosSmooth.Game/Data/Raids/RaidProgress.cs @@ -0,0 +1,17 @@ +// +// RaidProgress.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. + +namespace NosSmooth.Game.Data.Raids; + +public record RaidProgress +( + short MonsterLockerInitial, + short MonsterLockerCurrent, + short ButtonLockerInitial, + short ButtonLockerCurrent, + short CurrentLives, + short InitialLives +); \ No newline at end of file diff --git a/Core/NosSmooth.Game/Data/Raids/RaidState.cs b/Core/NosSmooth.Game/Data/Raids/RaidState.cs new file mode 100644 index 0000000..417f8a8 --- /dev/null +++ b/Core/NosSmooth.Game/Data/Raids/RaidState.cs @@ -0,0 +1,52 @@ +// +// RaidState.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. + +namespace NosSmooth.Game.Data.Raids; + +/// +/// A state of a . +/// +public enum RaidState +{ + /// + /// Waiting for a raid start. + /// + Waiting, + + /// + /// The raid has started, the current room is not boss room. + /// + Started, + + /// + /// The raid has started and the current room is boss room. + /// + BossFight, + + /// + /// The raid has ended, successfully. + /// + EndedSuccessfully, + + /// + /// The raid has ended unsuccessfully. The whole team has failed. + /// + TeamFailed, + + /// + /// The raid has ended unsuccessfully for the character. He ran out of lifes. + /// + MemberFailed, + + /// + /// The character has left the raid. + /// + /// + /// The previous state is needed to be able to tell whether + /// the raid was already started or was in the state. + /// + Left +} \ No newline at end of file diff --git a/Core/NosSmooth.Game/Data/Social/GroupMember.cs b/Core/NosSmooth.Game/Data/Social/GroupMember.cs index 9c13d09..c9613ee 100644 --- a/Core/NosSmooth.Game/Data/Social/GroupMember.cs +++ b/Core/NosSmooth.Game/Data/Social/GroupMember.cs @@ -43,7 +43,7 @@ public record GroupMember(long PlayerId) /// /// Gets the morph vnum of the player. /// - public long MorphVNum { get; internal set; } + public int? MorphVNum { get; internal set; } /// /// Gets the hp of the member. diff --git a/Core/NosSmooth.Game/Events/Raids/RaidFinishedEvent.cs b/Core/NosSmooth.Game/Events/Raids/RaidFinishedEvent.cs new file mode 100644 index 0000000..733edfc --- /dev/null +++ b/Core/NosSmooth.Game/Events/Raids/RaidFinishedEvent.cs @@ -0,0 +1,11 @@ +// +// RaidFinishedEvent.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.Raids; + +namespace NosSmooth.Game.Events.Raids; + +public record RaidFinishedEvent(Raid Raid) : IGameEvent; \ No newline at end of file diff --git a/Core/NosSmooth.Game/Events/Raids/RaidJoinedEvent.cs b/Core/NosSmooth.Game/Events/Raids/RaidJoinedEvent.cs new file mode 100644 index 0000000..a589413 --- /dev/null +++ b/Core/NosSmooth.Game/Events/Raids/RaidJoinedEvent.cs @@ -0,0 +1,11 @@ +// +// RaidJoinedEvent.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.Raids; + +namespace NosSmooth.Game.Events.Raids; + +public record RaidJoinedEvent(Raid Raid) : IGameEvent; \ No newline at end of file diff --git a/Core/NosSmooth.Game/Events/Raids/RaidStateChangedEvent.cs b/Core/NosSmooth.Game/Events/Raids/RaidStateChangedEvent.cs new file mode 100644 index 0000000..e1093ce --- /dev/null +++ b/Core/NosSmooth.Game/Events/Raids/RaidStateChangedEvent.cs @@ -0,0 +1,16 @@ +// +// RaidStateChangedEvent.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.Raids; + +namespace NosSmooth.Game.Events.Raids; + +public record RaidStateChangedEvent +( + RaidState PreviousState, + RaidState CurrentState, + Raid Raid +) : IGameEvent; \ No newline at end of file diff --git a/Core/NosSmooth.Game/Extensions/ServiceCollectionExtensions.cs b/Core/NosSmooth.Game/Extensions/ServiceCollectionExtensions.cs index 6c2f5d9..f244882 100644 --- a/Core/NosSmooth.Game/Extensions/ServiceCollectionExtensions.cs +++ b/Core/NosSmooth.Game/Extensions/ServiceCollectionExtensions.cs @@ -18,9 +18,11 @@ using NosSmooth.Game.PacketHandlers.Characters; using NosSmooth.Game.PacketHandlers.Entities; using NosSmooth.Game.PacketHandlers.Inventory; using NosSmooth.Game.PacketHandlers.Map; +using NosSmooth.Game.PacketHandlers.Raids; using NosSmooth.Game.PacketHandlers.Relations; using NosSmooth.Game.PacketHandlers.Skills; using NosSmooth.Game.PacketHandlers.Specialists; +using NosSmooth.Packets.Server.Raids; namespace NosSmooth.Game.Extensions; @@ -43,17 +45,35 @@ public static class ServiceCollectionExtensions serviceCollection.TryAddSingleton(); serviceCollection + + // act4 .AddPacketResponder() + + // character .AddPacketResponder() + .AddPacketResponder() + + // skills .AddPacketResponder() .AddPacketResponder() - .AddPacketResponder() .AddPacketResponder() + + // friends .AddPacketResponder() + + // inventory .AddPacketResponder() + + // groups .AddPacketResponder() + + // mates .AddPacketResponder() + + // skills .AddPacketResponder() + + // map .AddPacketResponder() .AddPacketResponder() .AddPacketResponder() @@ -61,11 +81,22 @@ public static class ServiceCollectionExtensions .AddPacketResponder() .AddPacketResponder() .AddPacketResponder() + + // hp, mp .AddPacketResponder() .AddPacketResponder() .AddPacketResponder() + + // equip .AddPacketResponder() - .AddPacketResponder(); + .AddPacketResponder() + + // raids + .AddPacketResponder() + .AddPacketResponder() + .AddPacketResponder() + .AddPacketResponder() + .AddPacketResponder(); serviceCollection .AddTransient() @@ -102,13 +133,16 @@ public static class ServiceCollectionExtensions /// The collection. public static IServiceCollection AddGameResponder(this IServiceCollection serviceCollection, Type gameResponder) { - if (!gameResponder.GetInterfaces().Any( + if (!gameResponder.GetInterfaces().Any + ( i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IGameResponder<>) )) { - throw new ArgumentException( + throw new ArgumentException + ( $"{nameof(gameResponder)} should implement IGameResponder.", - nameof(gameResponder)); + nameof(gameResponder) + ); } var handlerTypeInterfaces = gameResponder.GetInterfaces(); @@ -124,4 +158,4 @@ public static class ServiceCollectionExtensions return serviceCollection; } -} +} \ No newline at end of file diff --git a/Core/NosSmooth.Game/Game.cs b/Core/NosSmooth.Game/Game.cs index 4a7182d..cbca20e 100644 --- a/Core/NosSmooth.Game/Game.cs +++ b/Core/NosSmooth.Game/Game.cs @@ -359,6 +359,60 @@ public class Game : IStatefulEntity ); } + /// + /// Updates the current raid, if it is not null. + /// + /// The function for updating the raid. + /// Whether to release the semaphore used for changing the raid. + /// The cancellation token for cancelling the operation. + /// The updated raid. + internal Task UpdateRaidAsync + ( + Func update, + bool releaseSemaphore = true, + CancellationToken ct = default + ) + { + return CreateOrUpdateAsync + ( + GameSemaphoreType.Raid, + () => CurrentRaid, + m => CurrentRaid = m, + () => null, + update, + releaseSemaphore, + ct + ); + } + + /// + /// Creates the raid if it is null, or updates the current raid. + /// + /// The function for creating the raid. + /// The function for updating the raid. + /// Whether to release the semaphore used for changing the raid. + /// The cancellation token for cancelling the operation. + /// The updated raid. + internal Task CreateOrUpdateRaidAsync + ( + Func create, + Func update, + bool releaseSemaphore = true, + CancellationToken ct = default + ) + { + return CreateOrUpdateAsync + ( + GameSemaphoreType.Raid, + () => CurrentRaid, + m => CurrentRaid = m, + create, + update, + releaseSemaphore, + ct + ); + } + private async Task CreateAsync ( GameSemaphoreType type, diff --git a/Core/NosSmooth.Game/PacketHandlers/Raids/RaidBfResponder.cs b/Core/NosSmooth.Game/PacketHandlers/Raids/RaidBfResponder.cs new file mode 100644 index 0000000..68d2d5d --- /dev/null +++ b/Core/NosSmooth.Game/PacketHandlers/Raids/RaidBfResponder.cs @@ -0,0 +1,69 @@ +// +// RaidBfResponder.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 System.Data; +using NosSmooth.Core.Packets; +using NosSmooth.Game.Data.Raids; +using NosSmooth.Game.Events.Core; +using NosSmooth.Game.Events.Raids; +using NosSmooth.Packets.Enums.Raids; +using NosSmooth.Packets.Server.Raids; +using Remora.Results; + +namespace NosSmooth.Game.PacketHandlers.Raids; + +/// +/// A responder to . +/// +public class RaidBfResponder : IPacketResponder +{ + private readonly Game _game; + private readonly EventDispatcher _eventDispatcher; + + /// + /// Initializes a new instance of the class. + /// + /// The game. + /// The event dispatcher. + public RaidBfResponder(Game game, EventDispatcher eventDispatcher) + { + _game = game; + _eventDispatcher = eventDispatcher; + } + + /// + public async Task Respond(PacketEventArgs packetArgs, CancellationToken ct = default) + { + var packet = packetArgs.Packet; + Raid? previousRaid = null; + var currentRaid = await _game.UpdateRaidAsync + ( + raid => + { + previousRaid = raid; + return raid with + { + State = packet.WindowType switch + { + RaidBfPacketType.MissionStarted => RaidState.Started, + RaidBfPacketType.MissionCleared => RaidState.EndedSuccessfully, + _ => RaidState + .TeamFailed // TODO: figure out whether OutOfLives is sent for both individual member and whole team + } + }; + }, + ct: ct + ); + + if (previousRaid is not null && currentRaid is not null && previousRaid.State != currentRaid.State) + { + return await _eventDispatcher.DispatchEvent + (new RaidStateChangedEvent(previousRaid.State, currentRaid.State, currentRaid), ct); + } + + return Result.FromSuccess(); + } +} \ No newline at end of file diff --git a/Core/NosSmooth.Game/PacketHandlers/Raids/RaidMbfResponder.cs b/Core/NosSmooth.Game/PacketHandlers/Raids/RaidMbfResponder.cs new file mode 100644 index 0000000..25eea56 --- /dev/null +++ b/Core/NosSmooth.Game/PacketHandlers/Raids/RaidMbfResponder.cs @@ -0,0 +1,53 @@ +// +// RaidMbfResponder.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.Raids; +using NosSmooth.Packets.Server.Raids; +using Remora.Results; + +namespace NosSmooth.Game.PacketHandlers.Raids; + +/// +/// A responder to . +/// +public class RaidMbfResponder : IPacketResponder +{ + private readonly Game _game; + + /// + /// Initializes a new instance of the class. + /// + /// The game. + public RaidMbfResponder(Game game) + { + _game = game; + } + + /// + public async Task Respond(PacketEventArgs packetArgs, CancellationToken ct = default) + { + var packet = packetArgs.Packet; + + await _game.UpdateRaidAsync + ( + raid => raid with + { + Progress = new RaidProgress + ( + packet.MonsterLockerInitial, + packet.MonsterLockerCurrent, + packet.ButtonLockerInitial, + packet.ButtonLockerCurrent, + packet.CurrentLives, + packet.InitialLives + ) + }, + ct: ct + ); + return Result.FromSuccess(); + } +} \ No newline at end of file diff --git a/Core/NosSmooth.Game/PacketHandlers/Raids/RaidResponder.cs b/Core/NosSmooth.Game/PacketHandlers/Raids/RaidResponder.cs new file mode 100644 index 0000000..ff658b4 --- /dev/null +++ b/Core/NosSmooth.Game/PacketHandlers/Raids/RaidResponder.cs @@ -0,0 +1,114 @@ +// +// RaidResponder.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 System.Net.Http.Headers; +using NosSmooth.Core.Packets; +using NosSmooth.Game.Data.Info; +using NosSmooth.Game.Data.Raids; +using NosSmooth.Game.Data.Social; +using NosSmooth.Game.Events.Core; +using NosSmooth.Game.Events.Raids; +using NosSmooth.Packets.Enums.Raids; +using NosSmooth.Packets.Server.Raids; +using Remora.Results; + +namespace NosSmooth.Game.PacketHandlers.Raids; + +/// +/// A responder to . +/// +public class RaidResponder : IPacketResponder +{ + private readonly Game _game; + private readonly EventDispatcher _eventDispatcher; + + /// + /// Initializes a new instance of the class. + /// + /// The game. + /// The event dispatcher. + public RaidResponder(Game game, EventDispatcher eventDispatcher) + { + _game = game; + _eventDispatcher = eventDispatcher; + + } + + /// + public async Task Respond(PacketEventArgs packetArgs, CancellationToken ct = default) + { + var packet = packetArgs.Packet; + if (packet.Type is not(RaidPacketType.Leader or RaidPacketType.ListMembers or RaidPacketType.PlayerHealths or RaidPacketType.Leave)) + { + return Result.FromSuccess(); + } + + Raid? prevRaid = null; + var currentRaid = await _game.UpdateRaidAsync + ( + raid => + { + prevRaid = raid; + switch (packet.Type) + { + case RaidPacketType.Leave: + if (packet.LeaveType is not null && packet.LeaveType == RaidLeaveType.PlayerLeft) + { // the player has left. + prevRaid = raid with + { + State = RaidState.Left + }; + + return null; + } + + return raid; + case RaidPacketType.Leader: + if (packet.LeaderId is null) + { // set the raid to null. + return null; + } + + return raid with + { + Leader = raid.Members?.FirstOrDefault(x => x.PlayerId == packet.LeaderId.Value) + }; + case RaidPacketType.ListMembers: + return raid with + { + Members = raid.Members?.Where(x => packet.ListMembersPlayerIds?.Contains(x.PlayerId) ?? true).ToList() + }; + case RaidPacketType.PlayerHealths: + // update healths + foreach (var member in raid.Members ?? (IReadOnlyList)Array.Empty()) + { + var data = packet.PlayerHealths?.FirstOrDefault(x => x.PlayerId == member.PlayerId); + + if (data is not null) + { + member.Hp ??= new Health(); + member.Mp ??= new Health(); + + member.Hp.Percentage = data.HpPercentage; + member.Mp.Percentage = data.MpPercentage; + } + } + return raid; + } + + return raid; + }, + ct: ct + ); + + if (currentRaid == null && prevRaid != null) + { + return await _eventDispatcher.DispatchEvent(new RaidFinishedEvent(prevRaid), ct); + } + + return Result.FromSuccess(); + } +} \ No newline at end of file diff --git a/Core/NosSmooth.Game/PacketHandlers/Raids/RbossResponder.cs b/Core/NosSmooth.Game/PacketHandlers/Raids/RbossResponder.cs new file mode 100644 index 0000000..0266695 --- /dev/null +++ b/Core/NosSmooth.Game/PacketHandlers/Raids/RbossResponder.cs @@ -0,0 +1,80 @@ +// +// RbossResponder.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.Entities; +using NosSmooth.Game.Data.Raids; +using NosSmooth.Game.Events.Core; +using NosSmooth.Game.Events.Raids; +using NosSmooth.Packets.Server.Raids; +using Remora.Results; + +namespace NosSmooth.Game.PacketHandlers.Raids; + +/// +/// A responder to . +/// +public class RbossResponder : IPacketResponder +{ + private readonly Game _game; + private readonly EventDispatcher _eventDispatcher; + + /// + /// Initializes a new instance of the class. + /// + /// The game. + /// The event dispatcher. + public RbossResponder(Game game, EventDispatcher eventDispatcher) + { + _game = game; + _eventDispatcher = eventDispatcher; + } + + /// + public async Task Respond(PacketEventArgs packetArgs, CancellationToken ct = default) + { + var packet = packetArgs.Packet; + var map = _game.CurrentMap; + if (map is null) + { + return Result.FromSuccess(); + } + + var bossEntity = packet.EntityId is not null ? map.Entities.GetEntity(packet.EntityId.Value) : null; + + RaidState? previousState = null; + var currentRaid = await _game.UpdateRaidAsync + ( + raid => + { + previousState = raid.State; + if (bossEntity is not null && (raid.Bosses is null || !raid.Bosses.Contains(bossEntity))) + { + return raid with + { + Boss = bossEntity, + Bosses = (raid.Bosses ?? Array.Empty()).Append(bossEntity).ToList(), + State = RaidState.BossFight + }; + } + + return raid with + { // this will oscillate between more bosses ... + Boss = bossEntity + }; + }, + ct: ct + ); + + if (currentRaid is not null && previousState is not null && previousState != currentRaid.State) + { + return await _eventDispatcher.DispatchEvent + (new RaidStateChangedEvent(previousState.Value, currentRaid.State, currentRaid), ct); + } + + return Result.FromSuccess(); + } +} \ No newline at end of file diff --git a/Core/NosSmooth.Game/PacketHandlers/Raids/RdlstResponder.cs b/Core/NosSmooth.Game/PacketHandlers/Raids/RdlstResponder.cs new file mode 100644 index 0000000..66a5224 --- /dev/null +++ b/Core/NosSmooth.Game/PacketHandlers/Raids/RdlstResponder.cs @@ -0,0 +1,98 @@ +// +// RdlstResponder.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.Raids; +using NosSmooth.Game.Data.Social; +using NosSmooth.Game.Events.Core; +using NosSmooth.Game.Events.Raids; +using NosSmooth.Packets.Server.Raids; +using Remora.Results; + +namespace NosSmooth.Game.PacketHandlers.Raids; + +/// +/// A responder to . +/// +public class RdlstResponder : IPacketResponder +{ + private readonly Game _game; + private readonly EventDispatcher _eventDispatcher; + + /// + /// Initializes a new instance of the class. + /// + /// The game. + /// The event dispatcher. + public RdlstResponder(Game game, EventDispatcher eventDispatcher) + { + _game = game; + _eventDispatcher = eventDispatcher; + } + + /// + public async Task Respond(PacketEventArgs packetArgs, CancellationToken ct = default) + { + var packet = packetArgs.Packet; + + IReadOnlyList UpdateMembers(IReadOnlyList? currentMembers) + { + return packet.Players + .Select + ( + packetMember => + { + var newMember = currentMembers?.FirstOrDefault + (member => packetMember.Id == member.PlayerId) ?? new GroupMember(packetMember.Id); + + newMember.Class = packetMember.Class; + newMember.Level = packetMember.Level; + newMember.HeroLevel = packetMember.HeroLevel; + newMember.Sex = packetMember.Sex; + newMember.MorphVNum = packetMember.MorphVNum; + + return newMember; + } + ).ToArray(); + } + + Raid? prevRaid = null; + var currentRaid = await _game.CreateOrUpdateRaidAsync + ( + () => new Raid + ( + packet.RaidType, + RaidState.Waiting, + packet.MinimumLevel, + packet.MaximumLevel, + null, + null, + null, + null, + null + ), + raid => + { + prevRaid = raid; + return raid with + { + Type = packet.RaidType, + MinimumLevel = packet.MinimumLevel, + MaximumLevel = packet.MaximumLevel, + Members = UpdateMembers(raid.Members), + }; + }, + ct: ct + ); + + if (prevRaid is null && currentRaid is not null) + { + return await _eventDispatcher.DispatchEvent(new RaidJoinedEvent(currentRaid), ct); + } + + return Result.FromSuccess(); + } +} \ No newline at end of file diff --git a/Packets/NosSmooth.Packets/Enums/Raids/RaidBfPacketType.cs b/Packets/NosSmooth.Packets/Enums/Raids/RaidBfPacketType.cs new file mode 100644 index 0000000..9a21c8e --- /dev/null +++ b/Packets/NosSmooth.Packets/Enums/Raids/RaidBfPacketType.cs @@ -0,0 +1,25 @@ +// +// RaidBfPacketType.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 System.Diagnostics.CodeAnalysis; +using NosSmooth.Packets.Server.Raids; +#pragma warning disable CS1591 + +namespace NosSmooth.Packets.Enums.Raids; + +/// +/// A type of . +/// +[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1602:Enumeration items should be documented", Justification = "Self-explanatory.")] +public enum RaidBfPacketType +{ + MissionStarted = 0, + MissionCleared = 1, + TimeUp = 2, + LeaderDied = 3, + NoLivesLeft = 4, + MissionFailed = 5 +} \ No newline at end of file -- 2.49.0