#include "stdafx.h" ////////////////////////////////////////////////////////////////////////// // #include ////////////////////////////////////////////////////////////////////////// // #include #include #include #include #include #include #include #include #include "User.h" #include "TempUser.h" #include "UserManager.h" #include "Zone/CharSelect.h" #include #ifdef _NA_0_20110329_GAMEOPTION_SETTING #include "../Function/GameOptionManager.h" #endif #ifdef _NA_004707_20120416_1202_DELETE_RESERVATION_ROOM_LIST #include #endif // _NA_005026_20120527_CHAOS_ZONE_BATTLE_GROUND #include #include #ifdef _NA_008543_20151027_ONE_DAYS_GUILD_MISSION #include #endif //_NA_008543_20151027_ONE_DAYS_GUILD_MISSION #include "Zone/DungeonChaosZone.h" ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// User::User() : m_State(POOL_STATE) , m_eBehaveState(PLAYER_BEHAVE_IDLE_STATE) , m_eTransactionState(TR_END) , closing_user_trans_controller_(closing_user_trans_info_) { }; User::~User() { } VOID User::CopyInfo(TempUser* pTempUser) { SetAuthID(pTempUser->GetAuthID()); SetUserGUID(pTempUser->GetUserGUID()); SetUserKey(pTempUser->GetUserGUID()); //< 用钥匙设置USER GUID! SetUserID(pTempUser->GetUserID()); SetClientIP(pTempUser->GetClientIP()); SetLastSSNKey(pTempUser->GetLastSSNKey()); SetBillingType(pTempUser->GetBillingType()); //_PCBANG_POLICY_CHANGE_POST_EXPIRED SetReservedValue(pTempUser->GetReservedValue(true)); SetAuthUserType(pTempUser->GetAuthUserType()); SetSts(pTempUser->GetSts()); SetPCRoomSts(pTempUser->GetPCRoomSts()); SetLoginTime(pTempUser->GetLoginTime()); SetLoginTime_t(pTempUser->GetLoginTime_t()); #ifdef __CN_OO0510__FATIGUE_MATCHING_UPDATE SetAge(pTempUser->GetAge()); SetRealNameAuth(pTempUser-> GetRealNameAuth()); #endif //__CN_OO0510__FATIGUE_MATCHING_UPDATE #ifdef _JP_0_20100723_GAMECHU_AUTHFLOW_ SetGameChuUSN(pTempUser->GetGameChuUSN()); #endif #ifdef _NA_20100307_BETAKEY_SYSTEM SetBetaKey(pTempUser->GetBetaKeyInfo()->GetBetaKey()); #endif #ifdef _NA_20100802_SPEED_HACK_DETECTION GetTickSpeedChecker().SetUserID(); #endif } VOID User::Init() { UserSession::Init(); m_eTransactionState = TR_END; UnlinkServer(); SECUREINFO.Init(); SECUREINFO.HEARTBEAT().Init(); // HEARTBEAT的检查开始在角色选择窗口中进行. #ifdef _NA_20100802_SPEED_HACK_DETECTION SECUREINFO.TICKSPEED().Init(this); #endif SSQHandler = ISSQHandlerD(this, NULL); // 重置角色栏(初始值SelectedIndex=MAX CHARACTER LIST NUM) character_list_.Init(); SetZoneType(eZONETYPE_MAX); SetMoveZoneType(eZONETYPE_MAX, eZONETYPE_MAX, 0); SetZoneState(ePRS_NOT_AT_ZONE); closing_user_trans_controller_.Init(); SetReady(FALSE); SetMaster(FALSE); SetTeam(0); GetMissionManager()->Clear(); SetSelectedCharCHuntingVCount(0); SetSelectedCharCHuntingTotCount(0); m_bLogOutWait = false; m_bExecuteDisconnectUser = false; world_service_enabled_state_ = false; m_ItemOwnFlag.Init(); SetState(INIT_STATE); #ifdef __CN_OO0510__FATIGUE_MATCHING_UPDATE m_byAge = 0; m_byRealNameAuth = 0; #endif m_LockItemPosForInstanceDungeon = INVALID_POSTYPE_VALUE; //重置非正常连接结束信息 m_PartyReturnInfo.Init(); m_PortalUserInfo.SetUser(this); #ifdef __NA001334_090420_SERVER_SELECT_FACILITY__ m_ReAuthInfo.Clear(); #endif m_ReservedHP = 0; m_PlayerStateEvent = PlayerStatEvent::eFlag_None; //_NA_20110630_BATTLE_ZONE_RENEWAL m_isInvaitPartyRoom = TRUE; } VOID User::Release() { // __NA000630_070817_MOLA_5th_UPDATE SECUREINFO.MOLAController().SendQueryRelease(this); // 返回池时强制解除客户端连接。 //case:游戏服务器瘫痪时 SetDisconnectCode(RC::RC_DISCONNECT_USER_RELEASE); DisconnectUser(); //< 不加入tempuser or userssion. UnlinkServer(); SECUREINFO.Release(); #ifdef __NA001334_090420_SERVER_SELECT_FACILITY__ m_ReAuthInfo.Clear(); #endif m_PortalUserInfo.SetUser(0); character_list_.Release(); // CHANGES: f110517.2L UserSession::Release(); SetState(POOL_STATE); } VOID User::OnAccept(DWORD dwNetworkIndex) { __UNUSED(dwNetworkIndex); ASSERT(!"不访问的部分"); } void User::OnDisconnect() { _DisconnectUser(); // 处理网络连接完全结束时要处理的部分. UserManager* const user_manager = UserManager::Instance(); // CHANGES: f110516.6L, 用户的char_guid和char_name可能为空 //当用户在char_select区域上断开连接时. GAMELOG->DisconnectChar(this); const CHARGUID char_guid = this->GetSelectedCharGuid(); if (char_guid) { user_manager->RemoveUserForSelectedCharInfoHashes(this); }; EndCharLoginTime(); UserSession::OnDisconnectInfoToAuth(); UserSession::OnDisconnect(); } VOID User::DisconnectLinkedServerUser() { UserSession::DisconnectUser(TRUE); if(m_bExecuteDisconnectUser) return; // 加入队伍就退出!<-(080212)(WAVERIX)这是因为服务器断开而引起的问题. eREASON_LEAVE_PARTY eReason = m_bLogOutWait ? eREASON_LEAVE_PARTY_INTEND : eREASON_LEAVE_PARTY_ABNORMAL; AgentPartyManager::Instance()->LeaveParty(this, eReason); // 在房间里的话就从里面删除UnLink LeaveRoom(); // 向世界服务器通知断开. MSG_AW_USER_LOGOUT msgCMD; msgCMD.m_byCategory = AW_USER_STATUS; msgCMD.m_byProtocol = AW_USER_LOGOUT; msgCMD.m_dwKey = GetUserKey(); SendToWorldServer(&msgCMD, sizeof(msgCMD)); m_bExecuteDisconnectUser = true; world_service_enabled_state_ = false; } VOID User::DisconnectUser(BOOL bGracefulDisconnect) { UserSession::DisconnectUser(bGracefulDisconnect); // 在结束玩家时,不一定非要等待OnDisconnect(实际网络上的完全结束),而是处理需要提前处理的部分. _DisconnectUser(); } // 除了RemoveUser以外,OnDisconnect的大部分处理都在这里处理. VOID User::_DisconnectUser() { if(m_bExecuteDisconnectUser) return; // CHANGES: f110705.2L, 已从“DisconnectUser”移动以防止重复调用。 //完成时间:(sun:r54618,namka199),这是一个毫无意义的重试实例,在找不到用户时释放. #ifdef _NA_0_20110329_GAMEOPTION_SETTING GameOptionManager::Instance()->Disconnect_User(this); #endif if(GetLinkedServer()) { // Send To Game Server MSG_AG_CONNECTION_DISCONNECT_CMD msgCMD; //_NA_0_20091118_GAMEROOM_BATTLE_RESULT msgCMD.m_AbNormalExit = m_bLogOutWait ? 0 : 1; SendToLinkedServer(&msgCMD, sizeof(msgCMD)); } else { MSG_AD_CONNECTION_DISCONNECT_CMD msgCMD; msgCMD.m_dwKey = GetUserKey(); msgCMD.m_GuildGuid = GetSelectedCharGuildGuid(); msgCMD.m_CharGuid = GetSelectedCharGuid(); msgCMD.m_ChannelID = AgentServer::GetInstance()->GetKey().GetChannelID(); AgentServer::GetInstance()->SendToDBPServer(&msgCMD, sizeof(msgCMD)); } // 加入队伍就退出!<-(080212)(WAVERIX)这是因为服务器断开而引起的问题. eREASON_LEAVE_PARTY eReason = m_bLogOutWait ? eREASON_LEAVE_PARTY_INTEND : eREASON_LEAVE_PARTY_ABNORMAL; AgentPartyManager::Instance()->LeaveParty(this, eReason); #ifdef __NA001334_090420_SERVER_SELECT_FACILITY__ OnServerSelectQueryResult(m_ReAuthInfo.eReAuthSlot_AllSide, m_ReAuthInfo.eReAuthStep_None, 0); #endif PortalManager::ClearUserInfo(this); // 在房间里的话就从里面删除UnLink LeaveRoom(); #ifdef _NA_004707_20120416_1202_DELETE_RESERVATION_ROOM_LIST AgentPartyManager* const party_manager = AgentPartyManager::Instance(); PartyRoomFinder* room_finder = party_manager->GetPartyRoomFinder(); if (room_finder != NULL) { room_finder->DeleteAllCharGuidFromMissionList(this->GetSelectedCharGuid()); } #endif // _NA_004707_20120416_1202_DELETE_RESERVATION_ROOM_LIST // _NA_005026_20120527_CHAOS_ZONE_BATTLE_GROUND BattleGroundManager::Instance()->ProcessDisconnectUser(this, GetTRRoomKey(), eReason); #ifdef _NA_008543_20151027_ONE_DAYS_GUILD_MISSION OneDaysGuildMissionManager* const onedaysGuildMissionmanager = OneDaysGuildMissionManager::Instance(); if(onedaysGuildMissionmanager) { onedaysGuildMissionmanager->LeaveRoom(GetTRRoomKey(), this); } #endif //_NA_008543_20151027_ONE_DAYS_GUILD_MISSION // 向世界服务器通知断开. MSG_AW_USER_LOGOUT msgCMD; msgCMD.m_byCategory = AW_USER_STATUS; msgCMD.m_byProtocol = AW_USER_LOGOUT; msgCMD.m_dwKey = GetUserKey(); SendToWorldServer(&msgCMD, sizeof(msgCMD)); m_bExecuteDisconnectUser = true; world_service_enabled_state_ = false; } BOOL User::IsMovingBetweenServer() { // 服务器间移动 //FieldServer和BattleServer之间是否移动 switch(m_eToZoneType) { case eZONETYPE_VILLAGE: { switch(m_eFromZoneType) { case eZONETYPE_LOBBY: case eZONETYPE_FIELD: case eZONETYPE_DOMINATION_FIELD: case eZONETYPE_CHARSELECT: case eZONETYPE_SPA_FIELD: break; default: return TRUE; }; } break; case eZONETYPE_MISSION: case eZONETYPE_HUNTING: case eZONETYPE_CHUNTING: case eZONETYPE_PVP: return TRUE; } return FALSE; } VOID User::LeaveRoom() { const eZONE_STATE zsSTATE = GetZoneState(); const BOOL bRet = (ePRS_AT_ZONE&zsSTATE) ? TRUE : (ePRS_BEFORE_ENTER_ZONE&zsSTATE) ? TRUE : FALSE; if(bRet) { ZoneInterface* pZone = g_ZoneManager.FindZone(GetZoneKey()); pZone->LeaveUser(this, eSEND_NONE, eZONETYPE_MAX, 0); } } // NOTE: f110622.2L bool User::NotifyHeIsHereIfSatisfied() { if (m_bExecuteDisconnectUser) { return false; }; if (LinkedServer.GetLinkedServer() != NULL) { return false; }; if (he_is_in_char_select_timer_.IsExpired() == false) { return false; }; AgentServer* const agent_server = AgentServer::GetInstance(); MSG_AD_CONNECTION_HE_IS_HERE_CMD msg_ntf; msg_ntf.m_dwKey = GetUserKey(); msg_ntf.channel_id_ = agent_server->GetKey().GetChannelID(); agent_server->SendToDBPServer(&msg_ntf, sizeof(msg_ntf)); return true; } // NOTE: f110622.2L, 如果他位于角色选择区,可以使用以下方法 void User::ChangeHeIsHereNotificationTimer(bool started) { if (started) { he_is_in_char_select_timer_.SetTimer(CharSelect::kHeIsHereNotificationInterval); } else { he_is_in_char_select_timer_.Clear(); } } VOID User::SerializePartyInfo(_PARTY_MEMBER_INFO& memberInfo) { ZeroMemory(&memberInfo, sizeof(memberInfo)); memberInfo.m_dwMemberKey = GetPlayerKey(); const char* charName = GetSelectedCharName(); if(charName) { // (WAVERIX) (090408) (BUG-FIX) 缓冲溢出修正 strncpy(memberInfo.m_szCharName, charName, _countof(memberInfo.m_szCharName)); memberInfo.m_szCharName[_countof(memberInfo.m_szCharName) - 1] = '\0'; } memberInfo.m_wLevel = GetCharLV(); memberInfo.m_byClassType = GetSelectedCharClass(); memberInfo.m_byChaoState = GetSelectedCharChaoState(); const DWORD maxHP = GetSelectedCharMaxHP(); const DWORD curHP = GetSelectedCharCurHP(); const DWORD maxMP = GetSelectedCharMaxMP(); const DWORD curMP = GetSelectedCharCurMP(); memberInfo.m_byHPRatio = maxHP ? (BYTE)(100 * curHP / maxHP) : 100; memberInfo.m_byMPRatio = maxMP ? (BYTE)(100 * curMP / maxMP) : 100; #ifdef _NA_006638_20120415_ADD_SHIELD_INFO_IN_TARGET_INFO const DWORD maxSD = GetSelectedCharMaxSD(); const DWORD curSD = GetSelectedCharCurSD(); memberInfo.m_bySDRatio = maxSD ? (BYTE)(100 * curSD / maxSD) : 100; #endif // _NA_006638_20120415_ADD_SHIELD_INFO_IN_TARGET_INFO #ifdef _NA_002050_20110216_ADD_GENDER memberInfo.m_byGender = GetSelectedCharGender(); #endif // _NA_20110630_BATTLE_ZONE_RENEWAL memberInfo.m_selecteTeam = GetTeam(); memberInfo.m_isReady = AgentPartyManager::Instance()->GetMemberReadyState(this); #ifdef _NA_006164_20121012_FREE_PVP_ROOM_PARTY_MEMBER_INFO_CURRENT_ZONE_MODIFY ZoneInterface* const current_zone = g_ZoneManager.FindZone(GetZoneKey()); if (current_zone) { memberInfo.map_code_ = current_zone->GetMapCode(); } #else memberInfo.map_code_ = GetSelectedCharMapCode(); #endif // _NA_006164_20121012_FREE_PVP_ROOM_PARTY_MEMBER_INFO_CURRENT_ZONE_MODIFY #ifdef _NA_20111220_CHANGE_DISCONNECTED_USER_PROCESS memberInfo.m_isConnected = true; #endif // reporting if((maxHP && maxMP) == false) { SUNLOG(eCRITICAL_LOG, "["__FUNCTION__"][ErrorReport] " "UID(%u) Name(%s) CurHP/MaxHP = (%u/%u), CurMP/MaxMP = (%u/%u)", GetUserKey(), charName, curHP, maxHP, curMP, maxMP); } } #ifdef __NA001334_090420_SERVER_SELECT_FACILITY__ BOOLEAN User::OnServerSelectQueryResult(nsPacket::ReAuthInfo::eReAuthSlot reAuthSlot, nsPacket::ReAuthInfoBase::eReAuthStep reAuthStep, const nsPacket::ReAuthTokenStream* arg) { using namespace nsPacket; ReAuthInfo::ReAuthStepSlot& slots = m_ReAuthInfo.m_ReAuthSteps; BOOLEAN bStepCanceled = 0; if(reAuthSlot == m_ReAuthInfo.eReAuthSlot_AllSide) { if(reAuthStep != m_ReAuthInfo.eReAuthStep_Canceled) { if(!FlowControl::FCAssert(reAuthStep == m_ReAuthInfo.eReAuthStep_None || reAuthStep == m_ReAuthInfo.eReAuthStep_Requested)) return false; m_ReAuthInfo.Clear(); if(reAuthStep == m_ReAuthInfo.eReAuthStep_Requested) { m_ReAuthInfo.m_Timeout.SetNextTimeoutByCurTickBased(10 * 1000); slots[m_ReAuthInfo.eReAuthSlot_AuthServerSide] = m_ReAuthInfo.eReAuthStep_Requested; slots[m_ReAuthInfo.eReAuthSlot_GameServerSide] = m_ReAuthInfo.eReAuthStep_Requested; m_ReAuthInfo.m_bUseReAuth = TRUE; } return TRUE; } else bStepCanceled = TRUE; } if(bStepCanceled == 0 && reAuthSlot == m_ReAuthInfo.eReAuthSlot_AuthServerSide) { if(reAuthStep == m_ReAuthInfo.eReAuthStep_Accepted) { // assert(arg) if(slots[m_ReAuthInfo.eReAuthSlot_AuthServerSide] == m_ReAuthInfo.eReAuthStep_Requested) slots[m_ReAuthInfo.eReAuthSlot_AuthServerSide] = m_ReAuthInfo.eReAuthStep_Accepted; else bStepCanceled = TRUE; if(bStepCanceled == 0 && arg) { m_ReAuthInfo.SetReAuthStream(arg); SUNLOG(eCRITICAL_LOG, "[Game->Client] key : %s", arg->stream); } } else { slots[m_ReAuthInfo.eReAuthSlot_AuthServerSide] = reAuthStep; } } else if(bStepCanceled == 0 && reAuthSlot == m_ReAuthInfo.eReAuthSlot_GameServerSide) { if(reAuthStep == m_ReAuthInfo.eReAuthStep_Accepted) { if(slots[m_ReAuthInfo.eReAuthSlot_GameServerSide] == m_ReAuthInfo.eReAuthStep_Requested) slots[m_ReAuthInfo.eReAuthSlot_GameServerSide] = m_ReAuthInfo.eReAuthStep_Accepted; else bStepCanceled = TRUE; } else { slots[m_ReAuthInfo.eReAuthSlot_GameServerSide] = reAuthStep; } } if(bStepCanceled) { if(slots[m_ReAuthInfo.eReAuthSlot_AuthServerSide] != m_ReAuthInfo.eReAuthStep_None) { MSG_AU_AUTH_SERVER_SELECT_SYN msgSYN; msgSYN.m_AuthUserID = GetAuthID(); msgSYN.m_Request = msgSYN.eRequest_Cancel; AgentServer::GetInstance()->SendToAuthAgentServer((BYTE*)&msgSYN, sizeof(msgSYN)); slots[m_ReAuthInfo.eReAuthSlot_AuthServerSide] = m_ReAuthInfo.eReAuthStep_None; } if(slots[m_ReAuthInfo.eReAuthSlot_GameServerSide] != m_ReAuthInfo.eReAuthStep_None) { MSG_AG_CONNECTION_SERVER_SELECT_CONTROL_SYN msgSYN; msgSYN.m_Control = msgSYN.eControl_StopTransaction; SendToLinkedServer(&msgSYN, sizeof(msgSYN)); slots[m_ReAuthInfo.eReAuthSlot_GameServerSide] = m_ReAuthInfo.eReAuthStep_None; } m_ReAuthInfo.Clear(); } return TRUE; } BOOLEAN User::OnServerSelectQueryUpdate() { using namespace nsPacket; if(m_ReAuthInfo.m_bUseReAuth == 0) return TRUE; BOOLEAN toBeNext = !!m_ReAuthInfo.m_Timeout.IsExpired(); if(toBeNext == 0) return TRUE; ReAuthInfo::ReAuthStepSlot& slots = m_ReAuthInfo.m_ReAuthSteps; BOOLEAN bAcceptedAuth = slots[m_ReAuthInfo.eReAuthSlot_AuthServerSide] == m_ReAuthInfo.eReAuthStep_Accepted; BOOLEAN bAcceptedGame = slots[m_ReAuthInfo.eReAuthSlot_GameServerSide] == m_ReAuthInfo.eReAuthStep_Accepted; toBeNext = bAcceptedAuth; if (toBeNext && bAcceptedGame) { MSG_CG_CONNECTION_SERVER_SELECT_REQUEST_ACK msgACK; msgACK.m_Result = RC::RC_ROOM_SUCCESS; const ReAuthTokenStream* pToken = m_ReAuthInfo.GetReAuthStream(); if(!FlowControl::FCAssert(pToken != 0)) return FALSE; msgACK.m_ReAuthToken = *pToken; SendPacket(&msgACK, msgACK.GetSize()); SetLogOutWait(); SetDisconnectCode(RC::RC_DISCONNECT_FOR_SERVER_SELECT_TRANSACTION); DisconnectUser(TRUE); } else { OnServerSelectQueryResult(m_ReAuthInfo.eReAuthSlot_AllSide, m_ReAuthInfo.eReAuthStep_Canceled, 0); } return toBeNext; } #endif //__NA001334_090420_SERVER_SELECT_FACILITY__ //#ifdef _PCBANG_POLICY_CHANGE_POST_EXPIRED void User::NotifyPcBangBillingStatus(BOOLEAN send_to_dbproxy, BOOLEAN send_to_world) { DWORD pc_room_id = GetReservedValue(); // complex operation by GetBillingType() // status.eStatus_None | status.eStatus_PcRoom | status.eStatus_PcRoomExpired //GetReservedValue() 0 id 0 AgentServer* pAgentServer = AgentServer::GetInstance(); DWORD user_key = GetUserKey(); // Status : added in UserManager(user_key) // request character list ( -> dbproxy) // notify new user enter ( -> world) #ifdef _PCBANG_POLICY_CHANGE_POST_EXPIRED if(send_to_dbproxy) { MSG_AD_CHARINFO_PCBANG_BILLING_NTF msgNTF; msgNTF.m_dwKey = user_key; msgNTF.m_PcRoomId = pc_room_id; pAgentServer->SendToDBPServer(&msgNTF, sizeof(msgNTF)); } if(send_to_world) { MSG_AW_USER_STATUS_PCBANG_BILLING_NTF msgNTF; msgNTF.m_dwKey = user_key; msgNTF.m_PcRoomId = pc_room_id; #ifdef _NA_006413_20130201_PREMIUMSERVICE_ITEM msgNTF.premiumservice_ = GetPremiumService(); #endif //_NA_006413_20130201_PREMIUMSERVICE_ITEM pAgentServer->SendToWorldServer(&msgNTF, sizeof(msgNTF)); } #endif //_PCBANG_POLICY_CHANGE_POST_EXPIRED ;{ MSG_AG_CHARINFO_PCBANG_BILL_CMD cmd; cmd.m_PcRoomId = pc_room_id; SendToLinkedServer(&cmd, sizeof(cmd)); }; // post estimated status // gameserver -> gameserver || gameserver -> agentserver (character select) // update pc billing status } //#endif //_NA_008679_20160202_REWORK_BATTLEGROUND BOOL User::IsThereBattleGround() { if (GetZoneType() == eZONETYPE_INSTANCE) { ZoneInterface* cur_zone = g_ZoneManager.FindZone(GetZoneKey()); if (cur_zone != NULL) { InstanceDungeon* indun = static_cast(cur_zone); if (indun->GetDungeonType() == INDUN_KIND_CHAOS_ZONE) { DungeonChaosZone* chaos_zone = static_cast(indun); if (chaos_zone->GetChaosZoneType() == kBattleGround) { return TRUE; } } } } return FALSE; }