using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using ServerCore; using ServerBase; using ServerCommon; using ServerCommon.BusinessLogDomain; using MetaAssets; using USER_GUID = System.String; namespace GameServer.PacketHandler; [PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.InvitePartyReq), typeof(InvitePartyPacketHandler), typeof(GameLoginListener))] public class InvitePartyPacketHandler : PacketRecvHandler { private static void send_S2C_ACK_INVITE_PARTY(Player owner, Result result, Dictionary<(USER_GUID? userGuid, string? nickname), ServerErrorCode>? errInvites) { var ack_packet = new ClientToGame { Response = new ClientToGameRes { ErrorCode = result.ErrorCode, InvitePartyRes = new() } }; if (result.isSuccess()) { foreach (var err_member in errInvites ?? new()) { var invite_err = new InvitePartyErrorMember { ErrorCode = err_member.Value, InviteUserGuid = err_member.Key.userGuid ?? USER_GUID.Empty, InviteUserNickname = err_member.Key.nickname ?? string.Empty }; ack_packet.Response.InvitePartyRes.ErrorMemberList.Add(invite_err); } } GameServerApp.getServerLogic().onSendPacket(owner, ack_packet); } public override async Task onProcessPacket(ISession entityWithSession, IMessage recvMessage) { var player = entityWithSession as Player; NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!"); var recv_msg = recvMessage as ClientToGame; ArgumentNullReferenceCheckHelper.throwIfNull(recv_msg, () => $"recv_msg is null !!! - {player.toBasicString()}"); var request = recv_msg.Request.InvitePartyReq; ArgumentNullReferenceCheckHelper.throwIfNull(request, () => $"request is null !!! - {player.toBasicString()}"); var result = new Result(); var err_msg = string.Empty; var player_action = player.getEntityAction(); NullReferenceCheckHelper.throwIfNull(player_action, () => $"player_action is null !!! - {player.toBasicString()}"); var selected_character = player_action.getSelectedCharacter(); if (null == selected_character) { err_msg = $"Not selected Character !!! - {player.toBasicString()}"; result.setFail(ServerErrorCode.CharacterNotSelected, err_msg); Log.getLogger().error(result.toBasicString()); send_S2C_ACK_INVITE_PARTY(player, result, null); return result; } var character_action = selected_character.getEntityAction(); NullReferenceCheckHelper.throwIfNull(character_action, () => $"character_action is null !!! - {selected_character.toBasicString()}"); if (character_action.isFarming()) { err_msg = $"Character is Farming !!! - {selected_character.toBasicString()}, {player.toBasicString()}"; result.setFail(ServerErrorCode.FarimgState, err_msg); Log.getLogger().error(result.toBasicString()); send_S2C_ACK_INVITE_PARTY(player, result, null); return result; } var err_invites = new Dictionary<(USER_GUID? userGuid, string? nickname), ServerErrorCode>(); // 1. 초대하는 User 리스트 획득 var request_invite_infos = await getInviteUserInfos(request); NullReferenceCheckHelper.throwIfNull(request_invite_infos, () => $"request_invite_infos is null !!! - {player.toBasicString()}"); var invite_users = new List(); foreach (var info in request_invite_infos) { if (info.Value == false) { var err = ServerErrorCode.Success; if (info.Key.nickname == null) err = ServerErrorCode.NotFoundNickName; if (info.Key.userGuid == null) err = ServerErrorCode.NotFoundUser; err_invites.Add((info.Key.userGuid, info.Key.nickname), err); continue; } if (null == info.Key.userGuid) continue; if (info.Key.userGuid == player.getUserGuid()) continue; invite_users.Add(info.Key.userGuid); } if (invite_users.Count <= 0) { err_msg = $"Failed to invite party !!! : invite user is zero!!"; result.setFail(ServerErrorCode.InvitePartyInvalidUsers, err_msg); Log.getLogger().error(err_msg); send_S2C_ACK_INVITE_PARTY(player, result, null); return result; } // 2. 파티가 없으면 생성하기 var personal_party_action = player.getEntityAction(); var party = personal_party_action.getPersonalParty(); var is_create = false; if (null == party) { result = await personal_party_action.createDefaultParty(); if (result.isFail()) { send_S2C_ACK_INVITE_PARTY(player, result, null); return result; } party = personal_party_action.getPersonalParty(); is_create = true; } NullReferenceCheckHelper.throwIfNull(party, () => $"party is null !!"); // 4. 파티 초대 var party_invite_action = party.getEntityAction(); if (null == party_invite_action) { err_msg = $"Failed to get entity action !!! : {nameof(PartyInviteAction)}"; result.setFail(ServerErrorCode.EntityActionNotFound, err_msg); Log.getLogger().error(err_msg); send_S2C_ACK_INVITE_PARTY(player, result, null); return result; } var invite_party = await party_invite_action.inviteParty(invite_users); // 5. 에러 유저 정리 foreach (var invite_result in invite_party.err_invites ?? new()) { var nickname = string.Empty; foreach (var user in request_invite_infos.Where(user => user.Key.userGuid == invite_result.Key)) { nickname = user.Key.nickname; break; } err_invites.Add((invite_result.Key, nickname), invite_result.Value); } // 6. 데이터 정리 if (is_create && (invite_party.result.isFail() || request.InviteUserGuids.Count + request.InviteUserNicknames.Count == err_invites.Count)) { await personal_party_action.clearPersonalParty(); } // 7. 결과 전송 send_S2C_ACK_INVITE_PARTY(player, invite_party.result, err_invites); // 8. Business Log 기록 if (invite_party.result.isSuccess()) { writeBusinessLog(player, is_create, party.getPartyGuid(), invite_users); } return result; } private async Task> getInviteUserInfos(ClientToGameReq.Types.InvitePartyReq request) { var infos = new Dictionary<(USER_GUID?, string?), bool>(); // 1. nickname 으로 guid 획득 foreach (var nickname in request.InviteUserNicknames) { var find = await NicknameHelper.findNickname(nickname); if (find.Item1.isFail() || null == find.Item2) { infos.Add((null, nickname), false); continue; } infos.Add((find.Item2.UserGuid, nickname), true); } // 2. guid 로 nickname 획득 foreach (var guid in request.InviteUserGuids) { var nickname = await PartyHelper.getUserNicknameFromGuid(guid); if (null == nickname) { infos.Add((guid, null), false); continue; } infos.Add((guid, nickname), true); } return infos; } private void writeBusinessLog(Player player, bool isCreate, string partyGuid, List inviteUsers) { var party_log_data = PartyBusinessLogHelper.toPartyLogData(partyGuid, isCreate); // 1. 파티 생성 기록 PartyBusinessLog party_business_log; if (isCreate) { party_business_log = new PartyBusinessLog(new LogActionEx(LogActionType.CreateParty), party_log_data); BusinessLogger.collectLog(player, party_business_log); } // 2. 파티 초대 기록 var invite_logs = new List(); foreach (var invite in inviteUsers) { var log_data = PartyBusinessLogHelper.toPartyMemberLogData(partyGuid, invite, PartyMemberActionType.Invite); var party_member_business_log = new PartyMemberBusinessLog(log_data); invite_logs.Add(party_member_business_log); } party_business_log = new PartyBusinessLog(party_log_data); invite_logs.Add(party_business_log); BusinessLogger.collectLogs(new LogActionEx(LogActionType.InviteParty), player, invite_logs); } }