#include "stdafx.h" #include "PortalManager.h" #include #include #include // declared by __NA1279_1281_090209_TIMELINE_QUEST_BASED_MISSION__ #include #include #include struct QuestPortalInfoInAgent : public QuestPortalInfo { enum ePortalState { ePortalState_Init, ePortalState_RoomCreated, ePortalState_Closed, }; typedef STLX_VECTOR UserList; QuestPortalInfoInAgent() : m_PortalState(ePortalState_Init) , m_IsTempPortal(false) , m_PartyKey(0) , m_MasterPlayerKey(0) , m_RoomKey(0) { // no virtual function ZeroMemory(this, sizeof(*(QuestPortalInfo*)this)); } ~QuestPortalInfoInAgent() { //g_ZoneManager.ClosePortal(m_pLobby, m_RoomKey); } void CreatePortalInfo(const QuestPortalInfo& rQuestPortalInfo, BOOLEAN isTempPortal, PORTALKEY portalKey, WORD partyKey, DWORD masterPlayerKey, const RoomArgumentForRoomSetup& rRoomArgument) { *(QuestPortalInfo*)this = rQuestPortalInfo; m_IsTempPortal = isTempPortal; this->portalKey = portalKey; m_PortalState = ePortalState_Init; m_PartyKey = partyKey; m_MasterPlayerKey = masterPlayerKey; // À¯ÄèÇÏÁø ¸øÇÏ´Ù... CopyMemory(&m_RoomArgument, &rRoomArgument, sizeof(m_RoomArgument)); m_LifeTimeout.SetTimer(portalLifetime, true, false); } BOOLEAN IsPortalQuestMember(DWORD playerKey) const { UserList::const_iterator it = std::find(m_UserList.begin(), m_UserList.end(), playerKey); return (it != m_UserList.end()); } void RemoveQuestPortalMember(DWORD playerKey) { UserList::iterator it = std::find(m_UserList.begin(), m_UserList.end(), playerKey); if(it != m_UserList.end()) m_UserList.erase(it); } inline BOOLEAN IsFirstEnterance() const { assert(m_RoomKey ? m_PortalState == ePortalState_RoomCreated : m_PortalState != ePortalState_Init); return m_PortalState == ePortalState_Init; } ePortalState m_PortalState; BOOLEAN m_IsTempPortal; WORD m_PartyKey; DWORD m_MasterPlayerKey; // party°¡ ¾ø¾îµµ ¼³Á¤µÇ´Â °ª. KEYTYPE m_RoomKey; ITimerBase m_LifeTimeout; UserList m_UserList; RoomArgumentForRoomSetup m_RoomArgument; }; static MemberQueryResultOperator partyPortalOperator; typedef MemberQueryResultOperator::UserState UserState; typedef MemberQueryResultOperator::UserStateList UserStateList; PortalManager::PortalManager() : m_pUserManager(UserManager::Instance()) , m_pPartyManager(AgentPartyManager::Instance()) { } PortalManager::~PortalManager() { } BOOLEAN PortalManager::IsValidRequesterForCreatePortal(User* pUser) { KEYTYPE zoneKey = pUser->GetZoneKey(); ZoneInterface* pRequestedZone = g_ZoneManager.FindZone(zoneKey); if(pRequestedZone == 0) return FALSE; eZONE_STATE zoneState = pUser->GetZoneState(); if((zoneState & ePRS_AT_ZONE) == FALSE) return FALSE; eZONETYPE zoneType = pRequestedZone->GetType(); if (zoneType != eZONETYPE_VILLAGE && zoneType != eZONETYPE_DOMINATION_FIELD && zoneType != eZONETYPE_FIELD && zoneType != eZONETYPE_SPA_FIELD) //_NA_008069_20150210_ADD_SPA_SYSTEM return FALSE; return TRUE; } BOOLEAN PortalManager::IsValidCreatingZone(eZONETYPE zoneType) { if(zoneType == eZONETYPE_MISSION || zoneType == eZONETYPE_INSTANCE) return TRUE; return FALSE; } inline QuestPortalInfoInAgent* PortalManager::FindQuestPortalInfo(PORTALKEY portalKey) { PortalTable::iterator it = m_PortalTable.find(portalKey); return (it != m_PortalTable.end()) ? it->second : 0; } PORTALKEY PortalManager::CreatePortal(const QuestPortalInfo& rQuestPortalInfo, BOOLEAN isTempPortal, const RoomArgumentForRoomSetup& rRoomArgument) { PortalManager* const this_ = PortalManager::Instance(); User* pUser = this_->m_pUserManager->GetUserByObjKey(rQuestPortalInfo.requesterKey); if(pUser == 0) return INVALID_PORTAL_KEY; const PORTALKEY portalKey = (PORTALKEY)ObjKeyGender::Instance()->GetKey(OBJKEYTYPE_PORTALKEY); PartyState& partyState = pUser->GetPartyState(); WORD partyKey = partyState.GetPartyKey(); KEYTYPE zoneKey = pUser->GetZoneKey(); partyPortalOperator.Init(ePARTY_OPERATOR_PORTAL_CREATE, 0, zoneKey); partyPortalOperator.SetQuestPortalInfo(isTempPortal, portalKey, &rQuestPortalInfo); if(partyKey) this_->m_pPartyManager->For_eachMembers(partyKey, partyPortalOperator); else partyPortalOperator.PortalCreate(pUser); const PortalUserInfo& stateEnum = pUser->GetPortalUserInfo(); DWORD masterPlayerKey = partyKey ? this_->m_pPartyManager->GetMasterKey(partyKey) : pUser->GetPlayerKey(); QuestPortalInfoInAgent* pPortalInfo = TAllocNew(QuestPortalInfoInAgent); pPortalInfo->CreatePortalInfo(rQuestPortalInfo, isTempPortal, portalKey, partyKey, masterPlayerKey, rRoomArgument); QuestPortalInfoInAgent::UserList& rUserList = pPortalInfo->m_UserList; rUserList.reserve(MAX_PARTYMEMBER_NUM); DWORD successors = 0; const UserStateList& stateList = partyPortalOperator.GetUserStateList(); FOREACH_CONTAINER(const UserState& state, stateList, UserStateList) { const DWORD playerKey = state.pUser->GetPlayerKey(); switch(state.state) { case stateEnum.eState_Success: ++successors; rUserList.push_back(playerKey); break; case stateEnum.eState_ChangedPortal: ++successors; rUserList.push_back(playerKey); if(state.prevPortalKey != portalKey) { // old info remove process QuestPortalInfoInAgent* pOldInfo = this_->FindQuestPortalInfo(state.prevPortalKey); if(pOldInfo) pOldInfo->RemoveQuestPortalMember(playerKey); } break; case stateEnum.eState_Transaction: case stateEnum.eState_NoRelevant: case stateEnum.eState_Fail: //½ÇÆÐ »ç·ÊµéÀÌ ¹ºÁö °í¹ÎÇÒ °Í. //case stateEnum.eState_DuplicatedPortal: //case stateEnum.eState_NotFoundPortal: //case stateEnum.eState_DisabledAction: default: break; } } // Á¦°Å´Â Update¸¦ ÅëÇØ¼­... this_->m_PortalTable[portalKey] = pPortalInfo; return portalKey; } // 1) CreateRoom Event by MSG_CG_ZONE_EX_QUEST_PORTAL_ENTER_SYN RC::eROOM_RESULT PortalManager::RequestEnterZoneTempPortal(User* pUser, PORTALKEY portalKey) { if(pUser->IsBeginTransaction()) return RC::RC_ROOM_ALREADY_DOING_TRANSACTION; PortalManager* const this_ = PortalManager::Instance(); QuestPortalInfoInAgent* pQuestPortalInfo = this_->FindQuestPortalInfo(portalKey); if(pQuestPortalInfo == 0) return RC::RC_ROOM_FAILED; // can't find portal PortalUserInfo& rPortalUserInfo = pUser->GetPortalUserInfo(); if(rPortalUserInfo.GetPortalKey() != portalKey) return RC::RC_ROOM_FAILED; // can't match portal pUser->BeginTransaction(TR_QUERY_PORTAL_UNTIL_GAMESERVER_ACK); MSG_AG_ZONE_QUEST_PORTAL_ENTER_SYN msg; // msg.syncType = msg.eSYNC_TEMP_PORTAL; msg.portalKey = portalKey; msg.mapEnterancePortalIndex = 0; msg.enterableMapCode = pQuestPortalInfo->enterableMapCode; msg.questCode = pQuestPortalInfo->questCode; msg.portalPosision = pQuestPortalInfo->portalPosition; pUser->SendToLinkedServer(&msg, msg.GetSize()); return RC::RC_ROOM_SUCCESS; } //BOOLEAN //PortalManager::IsAcceptableUserByPointedPortal(QuestPortalInfoInAgent* pQuestPortalInfo, // User* pUser, BOOLEAN isTempPortal) //{ // PortalManager* const this_ = PortalManager::Instance(); // BOOLEAN validPortalUser = this_->IsValidRequesterForCreatePortal(pUser); // validPortalUser = validPortalUser && // pQuestPortalInfo->enterableMapCode == pMapPortal->wWorldTo; // validPortalUser = validPortalUser && // pQuestPortalInfo->IsPortalQuestMember(pUser->GetPlayerKey()); // if(isTempPortal == FALSE) // { // WORD partyKey = pUser->GetPartyState().GetPartyKey(); // validPortalUser = validPortalUser && // partyKey && partyKey == pQuestPortalInfo->m_PartyKey; // } // // return validPortalUser; //} // 1) CreateRoom Event by MSG_CG_ZONE_EX_QUEST_PORTAL_ENTER_SYN RC::eROOM_RESULT PortalManager::RequestEnterZoneFixedPortal(User* pUser, WORD enterancePortalIndex) { if(pUser->IsBeginTransaction()) return RC::RC_ROOM_ALREADY_DOING_TRANSACTION; // 1) Check PortalIndex // 2) CG_QUEST_PORTAL_ENTER_SYN // 2-1) Check User Portal State // 2-2) Send AG_QUEST_PORTAL_ENTER_SYN // 3) AG_QUEST_PORTAL_ENTER_ACK + Àӽà Æ÷Å»½Ã 󸮵Ǵ ³»¿ëµéÀ» ¿©±â¿¡ ¼³Á¤ // 3-1) INIT: Create Room const sMAP_ENTERENCE_PORTAL* pMapPortal = MapInfoParser::Instance()->GetMapPortal(enterancePortalIndex); if (pMapPortal == NULL || pMapPortal->byMapType == 0) return RC::RC_ROOM_INVALID_ROOM_TYPE; PortalManager* const this_ = PortalManager::Instance(); QuestPortalInfoInAgent* pQuestPortalInfo = 0; DWORD playerKey = pUser->GetPlayerKey(); BOOLEAN newPortalCreate = TRUE; PortalUserInfo& rPortalUserInfo = pUser->GetPortalUserInfo(); PORTALKEY portalKey = rPortalUserInfo.GetPortalKey(); if(portalKey != INVALID_PORTAL_KEY) { pQuestPortalInfo = this_->FindQuestPortalInfo(portalKey); if(!FlowControl::FCAssert(pQuestPortalInfo)) return RC::RC_ROOM_FAILED; // can't find portal... invalid user state BOOLEAN validPortalUser = this_->IsValidRequesterForCreatePortal(pUser); validPortalUser = pQuestPortalInfo->enterableMapCode == pMapPortal->wWorldTo && pQuestPortalInfo->IsPortalQuestMember(playerKey); if(validPortalUser) { WORD partyKey = pUser->GetPartyState().GetPartyKey(); if(partyKey == 0) // 1ÀÎ ³²Àº »óȲ validPortalUser = TRUE; else validPortalUser = partyKey == pQuestPortalInfo->m_PartyKey; } if(validPortalUser) validPortalUser = pQuestPortalInfo->m_PortalState != pQuestPortalInfo->ePortalState_Closed; ////////////////////////////////////////////////////////////////////////// newPortalCreate = validPortalUser == FALSE; } if(newPortalCreate) { QuestPortalInfo portalInfo; portalInfo.portalKey = INVALID_PORTAL_KEY; portalInfo.enterableMapCode = pMapPortal->wWorldTo; portalInfo.requesterKey = (WORD)playerKey; portalInfo.questCode = 0; portalInfo.portalLifetime = 10 * 60 * 1000; SetVector(&portalInfo.portalPosition, 0.0f, 0.0f, 0.0f); RC::eROOM_RESULT result = g_ZoneManager.CreatePortal(portalInfo, pUser, false); if(result != RC::RC_ROOM_SUCCESS) return result; portalKey = rPortalUserInfo.GetPortalKey(); pQuestPortalInfo = this_->FindQuestPortalInfo(portalKey); if(!FlowControl::FCAssert(pQuestPortalInfo)) return RC::RC_ROOM_FAILED; // can't find portal... invalid user state } pUser->BeginTransaction(TR_QUERY_PORTAL_UNTIL_GAMESERVER_ACK); MSG_AG_ZONE_QUEST_PORTAL_ENTER_SYN msg; // msg.syncType = msg.eSYNC_FIXED_PORTAL; msg.portalKey = portalKey; msg.mapEnterancePortalIndex = enterancePortalIndex; msg.enterableMapCode = pQuestPortalInfo->enterableMapCode; msg.questCode = pQuestPortalInfo->questCode; msg.portalPosision = pQuestPortalInfo->portalPosition; pUser->SendToLinkedServer(&msg, msg.GetSize()); return RC::RC_ROOM_SUCCESS; } // EnterUser Event in ZoneInterface RC::eROOM_RESULT PortalManager::EnterZoneTempPortal(User* pUser, PORTALKEY portalKey) { if(!FlowControl::FCAssert(pUser->IsBeginTransaction() == FALSE)) return RC::RC_ROOM_ALREADY_DOING_TRANSACTION; PortalManager* const this_ = PortalManager::Instance(); PortalUserInfo& rPortalUserInfo = pUser->GetPortalUserInfo(); // ±× »çÀÌ¿¡ ¹Ù²ð ¼ö ÀÖ´Ù. ¿äû ÀÚü´Â µ¿½Ã¿¡ ÇÒ °æ¿ì, ³ªÁß¿¡ ¿äûÇÑ À¯ÀúÀÇ Æ÷ŻŰ·Î //ÀüȯµÈ »óȲ... ÀÌ °æ¿ì, óÀ½ ¿äûÇÑ À¯ÀúÀÇ °æ¿ì¸¸ ¹®Á¦°¡ ¾ß±âµÈ´Ù. Àüȯ! //if(rPortalUserInfo.GetPortalKey() != portalKey) // return RC::RC_ROOM_FAILED; PORTALKEY userPortalKey = rPortalUserInfo.GetPortalKey(); if(userPortalKey != portalKey) { SUNLOG(eCRITICAL_LOG, "TempLog, 1st User Changed Portal by 2nd User { %u != %u }", userPortalKey, portalKey); portalKey = userPortalKey; } QuestPortalInfoInAgent* pQuestPortalInfo = this_->FindQuestPortalInfo(portalKey); if(pQuestPortalInfo == 0) return RC::RC_ROOM_FAILED; const DWORD playerKey = pUser->GetPlayerKey(); if(pQuestPortalInfo->IsPortalQuestMember(playerKey) == FALSE) { // Problem? close portal & clear info. return RC::RC_ROOM_FAILED; } BOOLEAN isCreated = pQuestPortalInfo->ePortalState_RoomCreated == pQuestPortalInfo->m_PortalState; RC::eROOM_RESULT result = RC::RC_ROOM_SUCCESS; // first step switch(pQuestPortalInfo->m_PortalState) { case pQuestPortalInfo->ePortalState_Init: result = g_ZoneManager.CreateRoomByPortal(pQuestPortalInfo->portalKey, pUser, pQuestPortalInfo->m_RoomArgument); return result; case pQuestPortalInfo->ePortalState_RoomCreated: result = g_ZoneManager.EnterPortal(portalKey, pUser, pQuestPortalInfo->m_RoomArgument, pQuestPortalInfo->m_RoomKey); return result; case pQuestPortalInfo->ePortalState_Closed: // need process error result return RC::RC_ROOM_FAILED; } return result; } RC::eROOM_RESULT PortalManager::EnterZoneFixedPortal(User* pUser, PORTALKEY portalKey) { return EnterZoneTempPortal(pUser, portalKey); } //================================================================================================== namespace ns_functor { ; struct OnPortalEnterResultErrorHandling { OnPortalEnterResultErrorHandling(MSG_CG_ZONE_EX_QUEST_PORTAL_ENTER_NAK* msg_nak, User* user); ~OnPortalEnterResultErrorHandling(); // MSG_CG_ZONE_EX_QUEST_PORTAL_ENTER_NAK* msg_nak_; User* user_; }; }; //end of namespace inline ns_functor::OnPortalEnterResultErrorHandling::OnPortalEnterResultErrorHandling( MSG_CG_ZONE_EX_QUEST_PORTAL_ENTER_NAK* msg_nak, User* user) : msg_nak_(msg_nak), user_(user) { } ns_functor::OnPortalEnterResultErrorHandling::~OnPortalEnterResultErrorHandling() { if (msg_nak_->errorCode == RC::RC_ROOM_SUCCESS) { return; }; user_->SendPacket(msg_nak_, sizeof(*msg_nak_)); PortalManager::ClearUserInfo(user_); } //================================================================================================== // CHANGES: f110803.5L, withdraw from portal members BOOLEAN PortalManager::OnPortalEnterResult( const MSG_AG_ZONE_QUEST_PORTAL_ENTER_ACK* recv_result_msg, User* user) { MSG_CG_ZONE_EX_QUEST_PORTAL_ENTER_NAK msg_nak; msg_nak.errorType = recv_result_msg->errorType; msg_nak.errorCode = recv_result_msg->errorCode; ns_functor::OnPortalEnterResultErrorHandling fail_notifier(&msg_nak, user); if (bool invalid_transaction = \ (user->GetTransactionState() != TR_QUERY_PORTAL_UNTIL_GAMESERVER_ACK)) { msg_nak.errorType = recv_result_msg->eRESULT_ROOM; msg_nak.errorCode = RC::RC_ROOM_ALREADY_DOING_TRANSACTION; return false; }; // leave transaction state user->EndTransaction(); // if (bool error_correction = \ (recv_result_msg->errorType != recv_result_msg->eRESULT_ROOM)) { msg_nak.errorType = recv_result_msg->eRESULT_ROOM; msg_nak.errorCode = RC::RC_ROOM_FAILED; return false; }; // ROOM_RESULT ¿¡·¯ ¼¼ºÐÈ­ ÇÒ Çʿ䰡 ÀÖÀ» Áöµµ ¸ð¸¥´Ù. ÀÏ´Ü forward ó¸® if (bool error_occured = (msg_nak.errorCode != RC::RC_ROOM_SUCCESS)) { return false; }; // (NOTE) ´©±¸¶óµµ AG¿¡ ÀÇÇÑ °ËÁõÀº °ÅÃÄ¾ß ÇÑ´Ù. ÀÌ ½ÃÁ¡¿¡ typedef MSG_CG_ZONE_EX_QUEST_PORTAL_ENTER_SYN SYNC_TYPE; if (recv_result_msg->syncType == SYNC_TYPE::eSYNC_TEMP_PORTAL) { msg_nak.errorType = recv_result_msg->eRESULT_ROOM; msg_nak.errorCode = EnterZoneTempPortal(user, recv_result_msg->portalKey); }; if (recv_result_msg->syncType == SYNC_TYPE::eSYNC_FIXED_PORTAL) { msg_nak.errorType = recv_result_msg->eRESULT_ROOM; msg_nak.errorCode = EnterZoneFixedPortal(user, recv_result_msg->portalKey); //ÀÌ ½ÃÁ¡¿¡ Æ÷ŻŰ´Â ÀÌ¹Ì Á¸ÀçÇϰí ACK¿¡ Æ÷ÇԵǾî ÀÖ¾î¾ß ÇÑ´Ù. }; // ROOM_RESULT ¿¡·¯ ¼¼ºÐÈ­ ÇÒ Çʿ䰡 ÀÖÀ» Áöµµ ¸ð¸¥´Ù. ÀÏ´Ü forward ó¸® if (bool error_occured = (msg_nak.errorCode != RC::RC_ROOM_SUCCESS)) { return false; }; return true; } BOOLEAN PortalManager::JoinRoom(User* pUser, MSG_CG_ZONE_EX_ROOM_JOIN_ACK* OUT pJoinInfo) { PortalUserInfo& rPortalUserInfo = pUser->GetPortalUserInfo(); PORTALKEY portalKey = rPortalUserInfo.GetPortalKey(); if(portalKey == INVALID_PORTAL_KEY) return FALSE; PORTALKEY prevPortalKey = 0; PortalManager* const this_ = PortalManager::Instance(); QuestPortalInfoInAgent* pQuestPortalInfo = this_->FindQuestPortalInfo(portalKey); if(pQuestPortalInfo == 0) { rPortalUserInfo.TryChangeState(rPortalUserInfo.eCommand_ClosePortal, portalKey, &prevPortalKey); return FALSE; } KEYTYPE roomKey = pQuestPortalInfo->m_RoomKey; const DWORD playerKey = pUser->GetPlayerKey(); if(roomKey == 0 || pQuestPortalInfo->IsPortalQuestMember(playerKey) == FALSE) { // Problem? close portal & clear info. rPortalUserInfo.TryChangeState(rPortalUserInfo.eCommand_ClosePortal, portalKey, &prevPortalKey); pQuestPortalInfo->RemoveQuestPortalMember(playerKey); SUNLOG(eCRITICAL_LOG, "["__FUNCTION__"][%u] Invalid Status Check Again [%u]", __LINE__, roomKey == 0); return FALSE; } MAPCODE enterableMapCode = pQuestPortalInfo->enterableMapCode; const sMAPINFO* pMapInfo = MapInfoParser::Instance()->FindMapInfo(enterableMapCode); { // make message : MSG_CG_ZONE_EX_ROOM_JOIN_ACK pJoinInfo->m_ktROOMKEY = roomKey; pJoinInfo->m_MapCode = enterableMapCode; pJoinInfo->m_byZONETYPE = pMapInfo->byMKind; pJoinInfo->m_fcCODE = pMapInfo->FCode[0]; } // NOTE, __NA1335_090407_PORTAL_MISSION_ROOM_CONSTRAINTS__ // 1) ÀÌ ½ÃÁ¡¿¡´Â ÇØ´ç À¯Àú´Â ¹Ýµå½Ã ÆÄƼ°¡ Á¸ÀçÇÑ´Ù. (ÆÄƼ »ý¼º/Âü°¡ µîÀÌ ÀÌ¹Ì ÀÌ·ïÁø »óÅÂ) // 2) ½ÇÁ¦ ¹èƲÁ¸ ÀÔÀå½Ã¿¡´Â ´õ ÀÌ»ó Æ÷Å»ÀÌ Á¸ÀçÇÏÁö ¾ÊÀ» ¼ö ÀÖ´Ù. µû¶ó¼­ ÇØ´ç ¹èƲÁ¸ÀÇ //Á¤º¸¿¡ ¸î¸î ±â´ÉÀº ÀÌÀüµÇ¾î¾ß ÇÑ´Ù. (ex: Master Player) // 3) ¹Ý´ë·Î ÇØ´ç ¹èƲÁ¸¿¡ ¿¬°áµÈ Æ÷ŻŰ´Â 2)¿¡ ÀǰŠÀ¯È¿ÇÏÁö ¾ÊÀ» ¼ö ÀÖ´Ù. // Remove Info rPortalUserInfo.TryChangeState(rPortalUserInfo.eCommand_ClosePortal, portalKey, &prevPortalKey); pQuestPortalInfo->RemoveQuestPortalMember(playerKey); return TRUE; } VOID PortalManager::OnEnteredRoom(User* pUser, RoomInterface* pRoom) { const eZONETYPE zoneType = pRoom->GetType(); if(!IsValidCreatingZone(zoneType)) return; PolicymentForRoom& rPolicymentForRoom = pRoom->RoomPolicyment; if((rPolicymentForRoom.FIELD & rPolicymentForRoom.QUEST_PORTAL_CONTROL) == FALSE) return; // ÀÌ ½ÃÁ¡¿¡´Â portalÀÌ Á¸ÀçÇÏÁö ¾ÊÀ» ¼ö ÀÖ´Ù. DWORD playerKey = pUser->GetPlayerKey(); if(playerKey == rPolicymentForRoom.GetReservedPortalMaster()) { WORD partyKey = pUser->GetPartyState().GetPartyKey(); PortalManager* const this_ = PortalManager::Instance(); this_->m_pPartyManager->ChangeMaster(partyKey, playerKey); pRoom->ChangeSpecialType(true, pUser); } else { MSG_CG_ZONE_CHANGE_SPECIALTYPE_CMD msg; msg.m_SpecialType = pRoom->GetRoomInfo()->m_SpecialType; pUser->SendPacket(&msg, sizeof(msg)); } } VOID PortalManager::OnRoomEvent(ZoneInterface* pZone, BOOLEAN isCreate) { const eZONETYPE zoneType = pZone->GetType(); if(!IsValidCreatingZone(zoneType)) return; assert(pZone->IsRoomType()); RoomInterface* pRoom = static_cast(pZone); PolicymentForRoom& rPolicymentForRoom = pRoom->RoomPolicyment; if((rPolicymentForRoom.FIELD & rPolicymentForRoom.QUEST_PORTAL_CONTROL) == FALSE) return; PortalManager* const this_ = PortalManager::Instance(); PORTALKEY portalKey = rPolicymentForRoom.GetPortalKey(); QuestPortalInfoInAgent* pQuestPortalInfo = this_->FindQuestPortalInfo(portalKey); // ¹æÀÌ ÆÄ±«µÉ ¶§´Â pQuestPortalInfoÀÌ ¾øÀ» °¡´É¼ºÀÌ Áö±ØÈ÷ ³ôÀ¸¹Ç·Î, AssertÁ¦°Å if(pQuestPortalInfo == 0) return; KEYTYPE roomKey = pRoom->GetKey(); // À¯Àú °ü·Ã 󸮵µ °í¹ÎÇØ¾ß ÇÒ °ÍÀÌ´Ù. if(isCreate) { pQuestPortalInfo->m_PortalState = pQuestPortalInfo->ePortalState_RoomCreated; pQuestPortalInfo->m_RoomKey = roomKey; rPolicymentForRoom.SetReservedPortalMaster(pQuestPortalInfo->m_MasterPlayerKey); } else { // timeoutÀ̾î¾ß ÇÑ´Ù. pQuestPortalInfo->m_PortalState = pQuestPortalInfo->ePortalState_Closed; } } BOOLEAN PortalManager::CanJoinParty(User* pRequester, User* pResponser) { { PortalUserInfo& rPortalUserInfo = pRequester->GetPortalUserInfo(); PORTALKEY portalKey = rPortalUserInfo.GetPortalKey(); if(portalKey != INVALID_PORTAL_KEY) return FALSE; }; { PortalUserInfo& rPortalUserInfo = pResponser->GetPortalUserInfo(); PORTALKEY portalKey = rPortalUserInfo.GetPortalKey(); if(portalKey != INVALID_PORTAL_KEY) return FALSE; }; return TRUE; } // LeaveParty Event in PartyManager VOID PortalManager::OnLeaveParty(User* pUser) { PortalManager* const this_ = PortalManager::Instance(); PortalUserInfo& rPortalUserInfo = pUser->GetPortalUserInfo(); PORTALKEY portalKey = rPortalUserInfo.GetPortalKey(); if(portalKey == INVALID_PORTAL_KEY) return; if(pUser->IsBeginTransaction()) { // irregular·Î ¹Û¿¡ º¼ ¼ö ¾ø´Ù. return; } const eZONE_STATE zoneState = pUser->GetZoneState(); const BOOLEAN acceptableState = (ePRS_AT_ZONE & zoneState) && (ePRS_AT_CHARSELECT != zoneState); if(!acceptableState) { // irregular return; } PORTALKEY prevPortalKey = 0; QuestPortalInfoInAgent* pQuestPortalInfo = this_->FindQuestPortalInfo(portalKey); if(pQuestPortalInfo == 0) { rPortalUserInfo.TryChangeState(rPortalUserInfo.eCommand_ClosePortal, portalKey, &prevPortalKey); return; } KEYTYPE roomKey = pQuestPortalInfo->m_RoomKey; const DWORD playerKey = pUser->GetPlayerKey(); if(pQuestPortalInfo->IsPortalQuestMember(playerKey) == FALSE) { // Problem? close portal & clear info. rPortalUserInfo.TryChangeState(rPortalUserInfo.eCommand_ClosePortal, portalKey, &prevPortalKey); pQuestPortalInfo->RemoveQuestPortalMember(playerKey); SUNLOG(eCRITICAL_LOG, "["__FUNCTION__"][%u] Invalid Status Check Again [%u]", __LINE__, roomKey == 0); return; } partyPortalOperator.Init(ePARTY_OPERATOR_PORTAL_CLOSE, 0, pUser->GetZoneKey()); partyPortalOperator.SetQuestPortalInfo(pQuestPortalInfo->m_IsTempPortal, portalKey, pQuestPortalInfo); partyPortalOperator.PortalClose(pUser); pQuestPortalInfo->RemoveQuestPortalMember(playerKey); } // Process Event in RoomInterface VOID PortalManager::RoomLifetimeTimeout(RoomInterface* pRoomInterface) { const eZONETYPE zoneType = pRoomInterface->GetType(); if(!IsValidCreatingZone(zoneType)) return; PolicymentForRoom& rPolicymentForRoom = pRoomInterface->RoomPolicyment; if((rPolicymentForRoom.FIELD & rPolicymentForRoom.QUEST_PORTAL_CONTROL) == FALSE) return; PortalManager* const this_ = PortalManager::Instance(); PORTALKEY portalKey = rPolicymentForRoom.GetPortalKey(); QuestPortalInfoInAgent* pQuestPortalInfo = this_->FindQuestPortalInfo(portalKey); if(!FlowControl::FCAssert(pQuestPortalInfo != 0)) return; } // cases = { // Disconnect Event in ~~, // CHANGES: f110803.5L, withdraw from portal members // } // CHANGES: f110803.5L, fixed a garbage data remained problem after the enterance fails void PortalManager::ClearUserInfo(User* user) { PortalUserInfo& portal_user_info = user->GetPortalUserInfo(); PORTALKEY portal_key = portal_user_info.GetPortalKey(); if (portal_key == INVALID_PORTAL_KEY) { return; }; PORTALKEY prev_portal_key = 0; portal_user_info.TryChangeState(\ portal_user_info.eCommand_UserClose, portal_key, &prev_portal_key); // PortalManager* const this_ = PortalManager::Instance(); QuestPortalInfoInAgent* quest_portal_info = this_->FindQuestPortalInfo(portal_key); if (quest_portal_info == NULL) { return; //problem? }; DWORD player_key = user->GetPlayerKey(); quest_portal_info->RemoveQuestPortalMember(player_key); } VOID PortalManager::PortalClose(QuestPortalInfoInAgent* pQuestPortalInfo) { typedef QuestPortalInfoInAgent::UserList UserList; QuestPortalInfoInAgent::UserList& rUserList = pQuestPortalInfo->m_UserList; PORTALKEY portalKey = pQuestPortalInfo->portalKey; partyPortalOperator.Init(ePARTY_OPERATOR_PORTAL_CLOSE, 0, 0); partyPortalOperator.SetQuestPortalInfo(pQuestPortalInfo->m_IsTempPortal, portalKey, pQuestPortalInfo); const BOOLEAN isUserEmpty = rUserList.empty(); FOREACH_CONTAINER(UserList::value_type playerKey, rUserList, UserList) { User* pUser = m_pUserManager->GetUserByObjKey(playerKey); if(pUser) partyPortalOperator.PortalClose(pUser); } const UserStateList& stateList = partyPortalOperator.GetUserStateList(); FOREACH_CONTAINER(const UserState& state, stateList, UserStateList) { const DWORD playerKey = state.pUser->GetPlayerKey(); // Ưº°È÷ Çö ½ÃÁ¡ »óÅ °á°ú¿¡ ´ëÇÑ ±¸ºÐ 󸮸¦ ÇÒ Çʿ䰡 ¾øÁö¸¸... switch(state.state) { case PortalUserInfo::eState_Success: pQuestPortalInfo->RemoveQuestPortalMember(playerKey); break; } } } BOOLEAN PortalManager::RequestClosePortal(User* pUser) { PortalUserInfo& rPortalInfo = pUser->GetPortalUserInfo(); PORTALKEY portalKey = rPortalInfo.GetPortalKey(); if(portalKey == INVALID_PORTAL_KEY) return FALSE; PortalManager* const this_ = PortalManager::Instance(); QuestPortalInfoInAgent* pQuestPortalInfo = this_->FindQuestPortalInfo(portalKey); if(pQuestPortalInfo == NULL) return FALSE; PartyState& partyState = pUser->GetPartyState(); WORD partyKey = partyState.GetPartyKey(); partyPortalOperator.Init(ePARTY_OPERATOR_PORTAL_CLOSE, 0, 0); partyPortalOperator.SetQuestPortalInfo(pQuestPortalInfo->m_IsTempPortal, portalKey, pQuestPortalInfo); if(partyKey) this_->m_pPartyManager->For_eachMembers(partyKey, partyPortalOperator); else partyPortalOperator.PortalClose(pUser); pQuestPortalInfo->m_UserList.clear(); return TRUE; } #ifdef _NA003129_QUEST_PORTAL_CONVENIENCE_EXTENTION bool PortalManager::RequestWithdrawPortalMember(User* user, RC::eROOM_RESULT* const error_code) { if ((user->GetZoneType() == eZONETYPE_LOBBY) || (ePRS_AT_ZONE != (ePRS_AT_ZONE & user->GetZoneState()))) { *error_code = RC::RC_ROOM_INVALIDROOMTYPE; return false; }; PortalUserInfo* const portal_user_info = &user->GetPortalUserInfo(); PORTALKEY portal_key = portal_user_info->GetPortalKey(); if (portal_key == INVALID_PORTAL_KEY) { *error_code = RC::RC_ROOM_INVALIDROOMTYPE; return false; }; if (user->IsBeginTransaction()) { *error_code = RC::RC_ROOM_ALREADY_DOING_TRANSACTION; return false; }; PortalManager* const this_ = PortalManager::Instance(); QuestPortalInfoInAgent* quest_portal_info = this_->FindQuestPortalInfo(portal_key); if (quest_portal_info == NULL || quest_portal_info->m_IsTempPortal) { *error_code = RC::RC_ROOM_INVALIDROOMTYPE; return false; }; const DWORD player_key = user->GetPlayerKey(); if (quest_portal_info->IsPortalQuestMember(player_key) == false) { *error_code = RC::RC_ROOM_NOT_EXIST_MEMBER; return false; }; if (PartyState* party_state = &user->GetPartyState()) { if (WORD party_key = party_state->GetPartyKey()) { RC::ePARTY_RESULT withdraw_result = AgentPartyManager::Instance()->LeaveParty(\ user, eREASON_LEAVE_PARTY_INTEND); if (withdraw_result != RC::RC_PARTY_SUCCESS) { *error_code = RC::RC_ROOM_INVALIDROOMTYPE; return false; }; }; }; partyPortalOperator.Init(ePARTY_OPERATOR_PORTAL_CLOSE, 0, 0); partyPortalOperator.SetQuestPortalInfo(quest_portal_info->m_IsTempPortal, portal_key, quest_portal_info); //if (partyKey) // this_->m_pPartyManager->For_eachMembers(partyKey, partyPortalOperator); //else partyPortalOperator.PortalClose(user); quest_portal_info->RemoveQuestPortalMember(player_key); // *error_code = RC::RC_ROOM_SUCCESS; return true; } #endif // AgentServer Update Process VOID PortalManager::Update() { PortalManager* const this_ = PortalManager::Instance(); PortalTable& rPortalTable = this_->m_PortalTable; PortalTable::iterator it = rPortalTable.begin(); PortalTable::iterator itend = rPortalTable.end(); while(it != itend) { QuestPortalInfoInAgent* pQuestPortalInfo = it->second; BOOLEAN needDelete = pQuestPortalInfo->m_UserList.empty() || pQuestPortalInfo->m_LifeTimeout.IsExpired(); if(needDelete) { g_ZoneManager.ClosePortal(*pQuestPortalInfo, //static_cast(pQuestPortalInfo->m_pLobby), pQuestPortalInfo->m_RoomKey); this_->PortalClose(pQuestPortalInfo); // need release resource, Mission|InstanceDungeonÀÇ °æ¿ì´Â ÀÚµ¿ ŸÀӾƿôÀ» ÀÌ¿ëÇÑ´Ù. // Á¤»óÀûÀÎ °æ¿ì ÀÌ¹Ì À¯ÀúµéÀº ÇØ´ç ¹æ¿¡ µé¾î°¡ Ç÷¹À̸¦ Çϰí ÀÖÀ» °ÍÀÌ´Ù. // lobby´Â º°µµ·Î Á¦°ÅÇÒ Çʿ䰡 ÀÖ´Ù. ObjKeyGender::Instance()->RestoreKey(OBJKEYTYPE_PORTALKEY, pQuestPortalInfo->portalKey); TAllocDelete(QuestPortalInfoInAgent, pQuestPortalInfo); it = rPortalTable.erase(it); continue; } ++it; } }