~ruther/NosSmooth

324e7e358fed12b8d00ce9351dfff486edd542bc — František Boháček 2 years ago 60b80a0
fix(game): handle raid leader before rdlst (raid initialized) correctly
M Core/NosSmooth.Game/Data/Raids/Raid.cs => Core/NosSmooth.Game/Data/Raids/Raid.cs +1 -0
@@ 19,6 19,7 @@ public record Raid
    RaidState State,
    short MinimumLevel,
    short MaximumLevel,
    long? LeaderId,
    GroupMember? Leader,
    RaidProgress? Progress,
    Monster? Boss,

M Core/NosSmooth.Game/PacketHandlers/Raids/RaidResponder.cs => Core/NosSmooth.Game/PacketHandlers/Raids/RaidResponder.cs +29 -16
@@ 41,31 41,42 @@ public class RaidResponder : IPacketResponder<RaidPacket>
    public async Task<Result> Respond(PacketEventArgs<RaidPacket> packetArgs, CancellationToken ct = default)
    {
        var packet = packetArgs.Packet;
        if (packet.Type is not(RaidPacketType.Leader or RaidPacketType.ListMembers or RaidPacketType.PlayerHealths or RaidPacketType.JoinLeave))
        if (packet.Type is not(RaidPacketType.Leader or RaidPacketType.ListMembers or RaidPacketType.PlayerHealths))
        {
            return Result.FromSuccess();
        }

        Raid? prevRaid = null;
        var currentRaid = await _game.UpdateRaidAsync
        var currentRaid = await _game.CreateOrUpdateRaidAsync
        (
            () =>
            {
                if (packet.Type == RaidPacketType.Leader)
                { // leader was sent before raid was created. That is a problem,
                  // we have to create the raid without correctly initialized members here.
                  // a better way to handle this could be by creating some kind of a cache.
                    return new Raid
                    (
                        (RaidType)(-1),
                        (RaidState)(-1),
                        -1,
                        -1,
                        packet.LeaderId,
                        null,
                        null,
                        null,
                        null,
                        null
                    );
                }

                return null;
            },
            raid =>
            {
                prevRaid = raid;
                switch (packet.Type)
                {
                    case RaidPacketType.JoinLeave:
                        if (packet.JoinLeaveType is not null && packet.JoinLeaveType == RaidJoinLeaveType.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.


@@ 74,12 85,14 @@ public class RaidResponder : IPacketResponder<RaidPacket>

                        return raid with
                        {
                            Leader = raid.Members?.FirstOrDefault(x => x.PlayerId == packet.LeaderId.Value)
                            Leader = raid.Members?.FirstOrDefault(x => x.PlayerId == packet.LeaderId.Value),
                            LeaderId = packet.LeaderId
                        };
                    case RaidPacketType.ListMembers:
                        return raid with
                        {
                            Members = raid.Members?.Where(x => packet.ListMembersPlayerIds?.Contains(x.PlayerId) ?? true).ToList()
                            Members = raid.Members?.Where
                                (x => packet.ListMembersPlayerIds?.Contains(x.PlayerId) ?? true).ToList()
                        };
                    case RaidPacketType.PlayerHealths:
                        // update healths

M Core/NosSmooth.Game/PacketHandlers/Raids/RdlstResponder.cs => Core/NosSmooth.Game/PacketHandlers/Raids/RdlstResponder.cs +20 -4
@@ 72,23 72,31 @@ public class RdlstResponder : IPacketResponder<RdlstPacket>, IPacketResponder<Rd
                null,
                null,
                null,
                null,
                UpdateMembers(null)
            ),
            raid =>
            {
                prevRaid = raid;
                var members = UpdateMembers(raid.Members);
                var leader = members.FirstOrDefault(x => x.PlayerId == raid.LeaderId);
                return raid with
                {
                    Type = packet.RaidType,
                    MinimumLevel = packet.MinimumLevel,
                    MaximumLevel = packet.MaximumLevel,
                    Members = UpdateMembers(raid.Members),
                    Members = members,
                    Leader = leader,
                    State = raid.State == (RaidState)(-1) ? RaidState.Waiting : raid.State
                };
            },
            ct: ct
        );

        if (prevRaid is null && currentRaid is not null)
        // State is equal to -1 in case Leader (raid 2 <leaderId>) was sent BEFORE rdlst.
        // Rdlst is the packet that initializes the raid, but in this case we have to make an exception
        // and initialize it from raid packet. That is because the leader won't be sent again.
        if ((prevRaid is null || prevRaid?.State == (RaidState)(-1)) && currentRaid is not null)
        {
            return await _eventDispatcher.DispatchEvent(new RaidJoinedEvent(currentRaid), ct);
        }


@@ 135,23 143,31 @@ public class RdlstResponder : IPacketResponder<RdlstPacket>, IPacketResponder<Rd
                null,
                null,
                null,
                null,
                UpdateMembers(null)
            ),
            raid =>
            {
                prevRaid = raid;
                var members = UpdateMembers(raid.Members);
                var leader = members.FirstOrDefault(x => x.PlayerId == raid.LeaderId);
                return raid with
                {
                    Type = packet.RaidType,
                    MinimumLevel = packet.MinimumLevel,
                    MaximumLevel = packet.MaximumLevel,
                    Members = UpdateMembers(raid.Members),
                    Members = members,
                    Leader = leader,
                    State = raid.State == (RaidState)(-1) ? RaidState.Waiting : raid.State
                };
            },
            ct: ct
        );

        if (prevRaid is null && currentRaid is not null)
        // State is equal to -1 in case Leader (raid 2 <leaderId>) was sent BEFORE rdlst.
        // Rdlst is the packet that initializes the raid, but in this case we have to make an exception
        // and initialize it from raid packet. That is because the leader won't be sent again.
        if ((prevRaid is null || prevRaid?.State == (RaidState)(-1)) && currentRaid is not null)
        {
            return await _eventDispatcher.DispatchEvent(new RaidJoinedEvent(currentRaid), ct);
        }

Do not follow this link