#include "stdafx.h" #include "./PlayerManager.h" #include #include #include #include #include "Player.h" #include "ObjectFactory.h" #include "StatusManager.h" #include "GameZone.h" #include "WareHouseSlotContainer.h" #include "GuildWareHouseSlotContainer.h" #ifdef _NA_1419_20100121_ACCUMULATE_POINT #include "AccumulatePoint.h" #endif #ifdef _NA_0_20110613_GAME_SHOP_RENEWAL #include "./GameShop/GameShop.Manager.h" #endif //================================================================================================== //================================================================================================== //================================================================================================== #if SUN_CODE_DELETE_RESERVED // __PLAYER_OBJECT_VERIFY_CODE__ static struct sPlayerVerifyCodes { DWORD dwCodeOfPlayer; DWORD dwCodeOfSCPlayer; DWORD dwCodeOfIGridObject; } s_PlayerVerifyCodes; static union s_UNIONPLAYERCODE { Player* player; Character* pCharacter; //SCPlayer* pSCPlayer; IGridObject* pIGridObject; // DWORD* pdwVerifyCode; } s_PCODE; static Player* s_pActivePlayerInUpdate = NULL; static BOOL GenerateObjectOfPlayer() { Player* player = new Player(); s_PCODE.player = player; s_PlayerVerifyCodes.dwCodeOfPlayer = *s_PCODE.pdwVerifyCode; //s_PCODE.pSCPlayer = dynamic_cast(player); //s_PlayerVerifyCodes.dwCodeOfSCPlayer = *s_PCODE.pdwVerifyCode; s_PCODE.pIGridObject = dynamic_cast(player); s_PlayerVerifyCodes.dwCodeOfIGridObject = *s_PCODE.pdwVerifyCode; if (!s_PlayerVerifyCodes.dwCodeOfPlayer) return false; delete player; return true; } Player* Player::VerifyNRestoreTHIS(Player* player) { DWORD dwResult = 0; // Ç÷¹À̾ À¯È¿ÇÑ ¸Þ¸ð¸® »óÅÂÀÎÁö üũ1 if (IsBadWritePtr(player, sizeof(*player))) { SUNLOG(eCRITICAL_LOG, _T("Invalid MemPtr %08X\n"), (DWORD)(__int64)player); return NULL; } if (eVERIFY_MAGICCODE_INIT != player->m_StartCheckCode) dwResult |= 0x01; if (eVERIFY_MAGICCODE_INIT != player->m_StartInitCode) dwResult |= 0x02; if (eVERIFY_MAGICCODE_INIT != player->m_EndCheckCode) dwResult |= 0x04; if (eVERIFY_MAGICCODE_INIT != player->m_EndInitCode) dwResult |= 0x08; s_PCODE.player = player; if (s_PlayerVerifyCodes.dwCodeOfPlayer != *s_PCODE.pdwVerifyCode) { dwResult |= 0x10; *s_PCODE.pdwVerifyCode = s_PlayerVerifyCodes.dwCodeOfPlayer; } s_PCODE.pIGridObject = dynamic_cast(player); if (s_PlayerVerifyCodes.dwCodeOfIGridObject != *s_PCODE.pdwVerifyCode) { dwResult |= 0x20; *s_PCODE.pdwVerifyCode = s_PlayerVerifyCodes.dwCodeOfIGridObject; } //s_PCODE.pSCPlayer = dynamic_cast(player); //if (s_PlayerVerifyCodes.dwCodeOfSCPlayer != *s_PCODE.pdwVerifyCode) //{ // dwResult |= 0x40; // *s_PCODE.pdwVerifyCode = s_PlayerVerifyCodes.dwCodeOfSCPlayer; //} if (dwResult) { MessageOutEx(g_pSunLog, CSunLog::cCRITICAL_LOG, CSunLog::cOUTPUT_FILE, CSunLog::cCATE_DEFAULT, _T("Corrupted Object Restoration REASON [%08X]"), dwResult); return NULL; } return player; } // __PLAYER_OBJECT_VERIFY_CODE__ #endif //SUN_CODE_DELETE_RESERVED //================================================================================================== //================================================================================================== //================================================================================================== //================================================================================================== // PlayerManager::PlayerManager() : sector_delay_interval_(0) , object_key_stream_(new ObjectKeyStream()) { static BOOL bRet = GenerateObjectOfPlayer(); #ifdef _NA_007932_20150112_ATTENDANCE_CHECK_SYSTEM m_attendance_day = 0; #endif //_NA_007932_20150112_ATTENDANCE_CHECK_SYSTEM } PlayerManager::~PlayerManager() { SAFE_DELETE(object_key_stream_); } //================================================================================================== // // void PlayerManager::Update(const util::ServerTimeInfoPerFrame* time_info) { // sector delay interval (0.8 second) const DWORD kUpdateDelayTime = 800; ;{ sector_delay_interval_ += time_info->delta_tick_; m_dwDeltaTick = time_info->delta_tick_; }; ;{ m_SectorUpdateOnUpdate = false; if (sector_delay_interval_ > kUpdateDelayTime) { m_SectorUpdateOnUpdate = true; sector_delay_interval_ -= kUpdateDelayTime; } }; #ifdef _NA_1419_20100121_ACCUMULATE_POINT AccumulatePoint::Calculate_Current_Year(time_info->delta_tick_); #endif for (PLAYER_HASHMAP::iterator it = user_guid_table_.begin(); it != user_guid_table_.end(); ++it) { Player* const player = it->second; if (player == NULL || player->IsDeleted()) { continue; } GameZone* entered_zone = NULL; MAPCODE entered_field_code = 0; const eZONE_STATE room_state = player->GetGameZone(entered_zone, entered_field_code); if (room_state & ePRS_AT_ZONE) { player->Update(time_info, m_SectorUpdateOnUpdate); }; } #ifdef _NA_007932_20150112_ATTENDANCE_CHECK_SYSTEM AttendanceUpdate(time_info); #endif // _NA_007932_20150112_ATTENDANCE_CHECK_SYSTEM } //¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡ // // void PlayerManager::Disconnect(Player* player) { //_NA_008506_20150923_LOG_LOGOUT_IN_GAMESERVER GAMELOG->LogLogout(player); if (player->IsDeleted()) { SUNLOG( eCRITICAL_LOG, _T("|%s|%d|Player is already deleted.|UserGuid = %d|"), __FUNCTION__, __LINE__, player->GetUserGuid() ); } #ifdef _NA_0_20110613_GAME_SHOP_RENEWAL GameShop::Manager::Instance()->CloseShop(player); #endif ReleasePlayer(player); RemovePlayer(player); } void PlayerManager::ReleasePlayer(Player* player) { if (player->IsDeleted()) { SUNLOG( eCRITICAL_LOG, _T("|%s|%d|Player is already deleted.|UserGuid = %d|"), __FUNCTION__, __LINE__, player->GetUserGuid() ); } GameZone * pEnterZone = NULL; MAPCODE EnterFieldCode = 0; eZONE_STATE eRoomState = player->GetGameZone(pEnterZone, EnterFieldCode); if (eRoomState & ePRS_AT_ZONE) { pEnterZone->Leave(player); if ((eRoomState == ePRS_AT_FIELD || eRoomState == ePRS_AT_DOMINATION_FIELD) && player->GetHP() == 0 && player->GetPreVillageMapCode() != 0) //ÇöÀç Çʵ忡¼­ Á×Àº »óÅ¿¡¼­ Á¾·áÇÑ´Ù¸é.. player->SetStartMapCode(player->GetPreVillageMapCode()); //ÀÌÀü¸¶À» À§Ä¡·Î ÀúÀåÇÑ´Ù. } MSG_DG_CHARINFO_UPDATE_TRANSACTION_CONTROL_SYN msg_transaction; msg_transaction.m_byTransControl = msg_transaction.DBUPDATE_LOCKING; msg_transaction.char_guid_ = player->GetCharGuid(); // CHANGES: f110412.2L player->SendToGameDBPServer(&msg_transaction, sizeof(msg_transaction)); player->SerializeInfoToDBProxy(UPDATE_FACTOR_LOGOUT); // ·Î±×¾Æ¿ô½Ã Àκ¥Å丮 Á¤º¸ ·Î±× ³²±â±â. GAMELOG->LogSnapShot(player); MSG_DG_CHARINFO_DISCONNECT_CMD CharInfoMsg; CharInfoMsg.m_ChannelID = g_pGameServer->GetKey().GetChannelID(); player->SendToGameDBPServer(&CharInfoMsg, sizeof(CharInfoMsg)); } //================================================================================================== // void PlayerManager::AllDisconnect() { // Agent¿Í ¿¬°áÀÌ ²÷¾îÁö´Â °æ¿ì¿¡¸¸ »ç¿ëµÈ´Ù. ObjectFactory* pObjectFactory = ObjectFactory::Instance(); FOREACH_CONTAINER(const PLAYER_HASHMAP::value_type& rNode, user_guid_table_, PLAYER_HASHMAP) { Player* const player = rNode.second; ReleasePlayer(player); pObjectFactory->FreeObject(player); } object_key_stream_->Clear(); user_guid_table_.clear(); char_guid_table_.clear(); char_name_table_.clear(); } //¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¡ // <Åë°è °ü·Ã> // // »ç¿ëÀÚ Æò±Õ º¸À¯ ±Ý¾× ±¸ÇÑ´Ù MONEY PlayerManager::GetAveUserTotalMoney() const { MONEY ui64AveUserMoney = 0; ULONGLONG ui64UserNum = (ULONGLONG)user_guid_table_.size(); // 0À¸·Î ³ª´©±â ¹æÁö if (0 == ui64UserNum) { return 0; } ui64AveUserMoney = GetUserTotalMoney(); ui64AveUserMoney = MONEY(ui64AveUserMoney / ui64UserNum); return ui64AveUserMoney; } MONEY PlayerManager::GetUserTotalMoney() const { MONEY total_money = 0; for (PLAYER_HASHMAP::const_iterator it = user_guid_table_.begin(); it != user_guid_table_.end(); ++it) { const Player* const player = it->second; if (player == NULL || player->IsDeleted()) { continue; } total_money += player->GetMoney(); } return total_money; } // À¯Àú Æò±Õ ÅëÈ­·® °è»ê MONEY PlayerManager::GetAveWarehouseTotalMoney() const { MONEY ui64AveUserMoney = 0; ULONGLONG ui64UserNum = (ULONGLONG)user_guid_table_.size(); // 0À¸·Î ³ª´©±â ¹æÁö if (0 == ui64UserNum) { return 0; } ui64AveUserMoney = GetWarehouseTotalMoney(); ui64AveUserMoney = MONEY(ui64AveUserMoney / ui64UserNum); return ui64AveUserMoney; } MONEY PlayerManager::GetWarehouseTotalMoney() const { MONEY total_money = 0; for (PLAYER_HASHMAP::const_iterator it = user_guid_table_.begin(); it != user_guid_table_.end(); ++it) { const Player* const player = it->second; if (player == NULL || player->IsDeleted()) { continue; } if (player->GetWarehouseContainer()->IsStarted()) { total_money += player->GetWarehouseContainer()->GetCurMoney(); } } return total_money; } //================================================================================================== // // bool PlayerManager::AddPlayer(Player* player) { // Ç÷¹À̾îÀÇ »ý¼º Áֱ⠽ÃÀÛ player->Init(); const DWORD ERR_INVALID_KEY = 10; const DWORD ERR_SYNCHRONIZE_FAULT = 20; const DWORD ERR_ALREADY_EXIST_PLAYER = 30; const DWORD user_guid = player->GetUserKey(); const DWORD object_key = player->GetObjectKey(); FlowControl flow; FLOWCONTROL_START() { // start LOGIC_BLOCK IfFailThenBreak(user_guid && object_key, ERR_INVALID_KEY); const ObjectKeyStream::sNode* object_node = object_key_stream_->GetObjectInfo(object_key); IfFailThenBreak(object_node && object_node->pObject == 0, ERR_SYNCHRONIZE_FAULT); IfFailThenBreak(user_guid_table_.find(user_guid) == user_guid_table_.end(), ERR_ALREADY_EXIST_PLAYER); user_guid_table_.insert(PLAYER_HASHMAP::value_type(user_guid, player)); object_key_stream_->AddObjectInfo(object_key, player, PlayerObjectKeyStreamAddin()); return true; } FLOWCONTROL_END; switch (flow.GetErrorCode()) { case ERR_INVALID_KEY: case ERR_SYNCHRONIZE_FAULT: case ERR_ALREADY_EXIST_PLAYER: SUNLOG(eCRITICAL_LOG, _T("[%s][Fail][UserKey:%u] %s"), __FUNCTION__, user_guid, flow.GetErrorString()); break; default: SUNLOG(eCRITICAL_LOG, _T("[%s][Fail] Unexpected Result = %s"), __FUNCTION__, flow.GetErrorString()); break; } return false; } //================================================================================================== Player* PlayerManager::FindPlayerByName(const char* char_name) const { //__NA003373_20090402_NOT_FIND_ENGLISHNAME_BUG char lower_char_name[MAX_CHARNAME_LENGTH + 1]; strncpy(lower_char_name, char_name, _countof(lower_char_name)); lower_char_name[_countof(lower_char_name) - 1] = '\0'; _strlwr(lower_char_name); ulong hash_value = util::StreamHashKey::GetStringHashKey(lower_char_name); PLAYER_NAME_HASH::const_iterator found_it = char_name_table_.find(hash_value); if (found_it == char_name_table_.end()) { return NULL; }; const DWORD object_key = found_it->second; const ObjectKeyStream::sNode* object_node = object_key_stream_->GetObjectInfo(object_key); if (object_node == NULL) { return NULL; }; Player* const player = object_node->pObject; if (player != NULL && player->IsDeleted()) { return NULL; } return player; // } bool PlayerManager::AddPlayerName(Player* player) { player->GetLoadingCheckTimer().SetTimer( ServerOptionParserEx::Instance()->GetServerOption().m_wABUSE_MIN_CLIENT_LOADING_TIME); const DWORD user_guid = player->GetUserKey(); const char* char_name = player->GetCharName(); //---------------------------------------------------------------------------------------------- // CharGuidµµ Á¸Àç const DWORD object_key = player->GetObjectKey(); const DWORD char_guid = player->GetCharGuid(); if (object_key_stream_->UpdateObjectAddinInfo(object_key, PlayerObjectKeyStreamAddin(char_guid)) == false) { SUNLOG(eFULL_LOG, "[%s]PlayerCharGuid[%s][%u][charguid:%u]", __FUNCTION__, char_name, user_guid, char_guid); return false; } char_guid_table_[char_guid] = object_key; //---------------------------------------------------------------------------------------------- char lower_char_name[MAX_CHARNAME_LENGTH + 1]; strncpy(lower_char_name, char_name, _countof(lower_char_name)); lower_char_name[_countof(lower_char_name) - 1] = '\0'; _strlwr(lower_char_name); const ulong hash_value = util::StreamHashKey::GetStringHashKey(lower_char_name); player->char_name_hash_ = 0; PLAYER_NAME_HASH::iterator found_it = char_name_table_.find(hash_value); if (found_it != char_name_table_.end()) { SUNLOG(eCRITICAL_LOG, "[%s][CharGuid=%u]PlayerName exist [%s]", __FUNCTION__, user_guid, char_name); return false; }; player->char_name_hash_ = hash_value; char_name_table_[hash_value] = object_key; return true; } //================================================================================================== bool PlayerManager::RemovePlayer(Player* player) { const DWORD ERR_INVALID_USERKEY = 10; const DWORD ERR_CANT_FIND_USER = 20; // Ç÷¹À̾îÀÇ »ý¼º Áֱ⠻èÁ¦ const DWORD user_guid = player->GetUserKey(); const DWORD object_key = player->GetObjectKey(); const DWORD char_guid = player->GetCharGuid(); FlowControl flow; FLOWCONTROL_START() { // start LOGIC_BLOCK IfFailThenBreak(user_guid && object_key, ERR_INVALID_USERKEY); PLAYER_HASHMAP::iterator found_it = user_guid_table_.find(user_guid); IfFailThenBreak(found_it != user_guid_table_.end(), ERR_CANT_FIND_USER); user_guid_table_.erase(found_it); object_key_stream_->RemoveObjectInfo(object_key); if (char_guid) { char_guid_table_.erase(char_guid); }; const DWORD char_name_hash = player->GetCharNameHash(); if (char_name_hash) { char_name_table_.erase(char_name_hash); }; ObjectFactory::Instance()->FreeObject(player); return true; } FLOWCONTROL_END; //---------------------------------------------------------------------------------------------- switch (flow.GetErrorCode()) { case ERR_INVALID_USERKEY: case ERR_CANT_FIND_USER: SUNLOG(eCRITICAL_LOG, _T("[%s][Fail][UserKey:%u] '%s'"), __FUNCTION__, user_guid, flow.GetErrorString()); break; default: SUNLOG(eCRITICAL_LOG, _T("[%s][Fail] Unexpected Result = '%s'"), __FUNCTION__, flow.GetErrorString()); break; } return false; } #ifdef _NA_007919_20141211_ADD_GMCOMMAND_EVENT VOID PlayerManager::SendPacketToAllPlayer(MSG_BASE_FORWARD* msg, size_t size,bool single) { if (GetNumberOfPlayers() == 0) { return ; } PLAYER_HASHMAP::iterator itr = user_guid_table_.begin(); while (itr != user_guid_table_.end() ) { Player* player = itr->second; if (player == NULL) { return; } player->SendPacket(msg, size); if(single){ return; } ++itr; } } #endif //_NA_007919_20141211_ADD_GMCOMMAND_EVENT VOID PlayerManager::SendGmNotice(TCHAR *notice, eNOTICE_TYPE type){ //xiaomi Ìí¼ÓÈ«·þ¹«¸æ MSG_AG_GM_NOTICE_CMD msg_cmd; msg_cmd.m_eType = type; memcpy( msg_cmd.m_tszNoticeMsg,notice,MAX_NOTICE_LEN + 1); msg_cmd.m_wLen = _countof( msg_cmd.m_tszNoticeMsg); SendPacketToAllPlayer(&msg_cmd,msg_cmd.GetSize(),true); } #ifdef _NA_007932_20150112_ATTENDANCE_CHECK_SYSTEM void PlayerManager::AttendanceUpdate(const util::ServerTimeInfoPerFrame* time_info) { if (m_attendance_day != time_info->system_time.wDay) { m_attendance_day = time_info->system_time.wDay; for (PLAYER_HASHMAP::iterator it = user_guid_table_.begin(); it != user_guid_table_.end(); ++it) { Player* const player = it->second; if (player == NULL || player->IsDeleted()) { continue; } if (player->GetExtraInfoManager().GetAttendanceManager().Attend( time_info->system_time.wYear, time_info->system_time.wMonth, time_info->system_time.wDay - 1, player) == true) { MSG_CG_CHARINFO_ATTENDANCE_INFO_PACKET msg; memcpy(&msg.attendance_infos, &player->GetExtraInfoManager().GetAttendanceManager().GetAttendanceInfos(), sizeof(msg.attendance_infos)); player->SendPacket(&msg, sizeof(msg)); } } } } #endif // _NA_007932_20150112_ATTENDANCE_CHECK_SYSTEM