#include "Stdafx.h" #include "DNLadderRoomRepository.h" #include "DNLadderRoom.h" #include "DNUserSession.h" #include "DnLadderMatchingSystem.h" #include "DNLadderSystemManager.h" #include "DNDBConnectionManager.h" #include "DNDBConnection.h" #include "DNFieldManager.h" #if defined(PRE_ADD_DWC) #include "DNDWCSystem.h" #include "DNDWCTeam.h" #endif extern TVillageConfig g_Config; using namespace LadderSystem; CRoomRepository::CRoomRepository() :m_bIIncRoomIndex(timeGetTime()) { m_pMatchingSystem = new CMatchingSystem( this ); m_dwCUCountUpdateTick = timeGetTime(); } CRoomRepository::~CRoomRepository() { delete m_pMatchingSystem; } void CRoomRepository::_QueryCUCount( MatchType::eCode MatchType ) { if( LadderSystem::bIsServiceMatchType( MatchType ) == false ) return; size_t Sum = 0; for( std::map::iterator itor=m_mRoomIndexRoomPtr.begin() ; itor!=m_mRoomIndexRoomPtr.end() ; ++itor ) { if( (*itor).second->GetMatchType() == MatchType ) Sum += (*itor).second->GetUserInfo().size(); } BYTE cThreadID; CDNDBConnection* pDBCon = g_pDBConnectionManager->GetDBConnection( cThreadID ); pDBCon->QueryAddPvPLadderCUCount( cThreadID, g_Config.nWorldSetID, MatchType, static_cast(Sum) ); //g_Log.Log( LogType::_LADDER, L"[Ladder] MatchType:%d CU:%d\r\n", MatchType, static_cast(Sum) ); } void CRoomRepository::Process( DWORD dwCurTick ) { m_pMatchingSystem->Process( dwCurTick ); for( std::map::iterator itor=m_mRoomIndexRoomPtr.begin() ; itor!=m_mRoomIndexRoomPtr.end() ; ++itor ) (*itor).second->Process( dwCurTick ); // Àӽà 30ºÐ if( dwCurTick-m_dwCUCountUpdateTick >= 1000*60*30 ) { m_dwCUCountUpdateTick = dwCurTick; // PvP ·Îºñ Æ÷ÇÔµÈ ºô¸®Áö¼­¹ö¸¸ ·Î±×³¯¸°´Ù. if( g_pFieldManager->bIsIncludePvPLobby() == true ) { _QueryCUCount( MatchType::_1vs1 ); _QueryCUCount( MatchType::_2vs2 ); _QueryCUCount( MatchType::_3vs3 ); _QueryCUCount( MatchType::_4vs4 ); #if defined(PRE_ADD_DWC) _QueryCUCount( MatchType::_3vs3_DWC ); _QueryCUCount( MatchType::_3vs3_DWC_PRACTICE ); #endif } } } int CRoomRepository::Create( CDNUserSession* pSession, MatchType::eCode MatchType ) { if( LadderSystem::bIsServiceMatchType( MatchType ) == false ) return ERROR_INVALIDPACKET; // PvP ¹æ¿¡ ÀÖÀ¸¸é ÀÔÀå ÇÒ ¼ö ¾øÀ½µÕ¿ä~ if( pSession->GetPvPIndex() > 0 ) return ERROR_PVP_ALREADY_PVPROOM; // ÀÌ¹Ì ·¡´õ¹æ¿¡ ÀÖ´ÂÁö °Ë»ç if( bIsExist( pSession->GetCharacterName() ) ) return ERROR_ALREADY_LADDERROOM; // DWC ±ÇÇÑ °Ë»ç #if defined(PRE_ADD_DWC) if( MatchType == MatchType::_3vs3_DWC || MatchType == MatchType::_3vs3_DWC_PRACTICE ) { if(pSession->GetDWCTeamID() <= 0) return ERROR_DWC_HAVE_NOT_TEAM; if(!pSession->IsDWCCharacter() ) return ERROR_DWC_PERMIT_FAIL; if( !g_pDWCTeamManager || !g_pDWCTeamManager->CheckDWCMatchTime(MatchType)) return ERROR_DWC_LADDER_MATCH_CLOSED; } else //DWC ¸é ·¹º§ °Ë»ç ¾ÈÇÔ { #endif // ·¹º§ Á¦ÇÑ °Ë»ç if( pSession->GetLevel() < static_cast(CGlobalWeightTable::GetInstance().GetValue( CGlobalWeightTable::PvPLadder_LimitLevel )) ) return ERROR_LADDERSYSTEM_CANT_ENTER_LEVELLIMIT; #if defined(PRE_ADD_DWC) } #endif CRoom* pRoom = new CRoom( _GenerateRoomIndex(), MatchType, pSession ); #if defined(PRE_ADD_DWC) if( MatchType == MatchType::_3vs3_DWC || MatchType == MatchType::_3vs3_DWC_PRACTICE ) { CDnDWCTeam *pDWCTeam = g_pDWCTeamManager->GetDWCTeam(pSession->GetDWCTeamID()); if(!pDWCTeam) return ERROR_DWC_NOTEXIST_TEAMINFO; pRoom->SetDWCInfo(pDWCTeam->GetTeamID(), //¿¬½À¸ðµå´Â InitGradePoint ·Î¸¸ ¸ÅνÃŲ´Ù. MatchType == MatchType::_3vs3_DWC ? pDWCTeam->GetTeamInfo()->nHiddenDWCPoint : LadderSystem::Stats::InitGradePoint); } #endif m_mRoomIndexRoomPtr.insert( std::make_pair( pRoom->GetRoomIndex(), pRoom ) ); m_mCharNameRoomIndex.insert( std::make_pair(pSession->GetCharacterName(), pRoom->GetRoomIndex() ) ); pSession->SetLadderUser( true ); return ERROR_NONE; } int CRoomRepository::Join( CDNUserSession* pSession, CRoom* pRoom ) { m_mRoomIndexRoomPtr.insert( std::make_pair( pRoom->GetRoomIndex(), pRoom ) ); m_mCharNameRoomIndex.insert( std::make_pair(pSession->GetCharacterName(), pRoom->GetRoomIndex() ) ); pSession->SetLadderUser( true ); pRoom->JoinUser( pSession ); return ERROR_NONE; } int CRoomRepository::Leave( CDNUserSession* pSession, Reason::eCode Reason ) { CRoom* pLadderRoom = GetRoomPtr( pSession->GetCharacterName() ); if( pLadderRoom == NULL ) return ERROR_INVALIDUSER_LADDERROOM; if( pLadderRoom->OutUser( pSession->GetCharacterDBID(), pSession->GetCharacterName(), Reason ) == false ) return ERROR_INVALIDUSER_LADDERROOM; pSession->SetLadderUser( false ); m_mCharNameRoomIndex.erase( pSession->GetCharacterName() ); // Delete LadderRoom if( pLadderRoom->bIsEmpty() ) { m_mRoomIndexRoomPtr.erase( pLadderRoom->GetRoomIndex() ); _OnDestroyRoom( pLadderRoom ); } pLadderRoom->AdjustNewLeader(); return ERROR_NONE; } int CRoomRepository::Matching( CDNUserSession* pSession, bool bIsCancel ) { CRoom* pLadderRoom = GetRoomPtr( pSession->GetCharacterName() ); if( pLadderRoom == NULL ) return ERROR_INVALIDUSER_LADDERROOM; if( pLadderRoom->GetLeaderCharDBID() != pSession->GetCharacterDBID() ) return ERROR_LADDERSYSTEM_NOLEADER; // ¸ÅĪÃë¼Ò¿äû if( bIsCancel == true ) { switch( pLadderRoom->GetRoomState() ) { case RoomState::WaitMatching: case RoomState::Matched: { break; } default: { return ERROR_LADDERSYSTEM_CANT_MATCHINGCANCLE_ROOMSTATE; } } pLadderRoom->ChangeRoomState( RoomState::WaitUser ); } // ¸ÅĪ¿äû else { #if defined(PRE_ADD_DWC) && defined(_WORK) //Ç®¹æ ¾Æ´Ï´õ¶óµµ ½ÇÇà °¡´ÉÇÏ°Ô ÀÓ½Ãó¸® #else if( pLadderRoom->bIsFullUser() == false ) return ERROR_LADDERSYSTEM_NOTENOUGH_USER; #endif if( pLadderRoom->bIsAllConnectUser() == false ) return ERROR_LADDERSYSTEM_CANT_MATCHING_ROOMSTATE; #if defined(PRE_ADD_DWC) if( pLadderRoom->GetMatchType() == MatchType::_3vs3_DWC || pLadderRoom->GetMatchType() == MatchType::_3vs3_DWC_PRACTICE ) // #84578 { if( !g_pDWCTeamManager || !g_pDWCTeamManager->CheckDWCMatchTime(pLadderRoom->GetMatchType()) ) { //´Ù¸¥ ÆÀ¿øµéµµ ´ë±â¹æÀ¸·Î ¹Ðµµ·Ï ºê·Îµåij½ºÆ® pLadderRoom->SendLadderMatching( ERROR_DWC_LADDER_MATCH_CLOSED, true ); return ERROR_DWC_LADDER_MATCH_CLOSED; } } #endif // RoomState °Ë»ç if( pLadderRoom->GetRoomState() != RoomState::WaitUser ) return ERROR_LADDERSYSTEM_CANT_MATCHINGCANCLE_ROOMSTATE; pLadderRoom->ChangeRoomState( RoomState::WaitMatching ); } return ERROR_NONE; } void CRoomRepository::DisconnectUser( INT64 biCharDBID, WCHAR* pwszCharName ) { CRoom* pLadderRoom = GetRoomPtr( pwszCharName ); if( pLadderRoom == NULL ) return; pLadderRoom->OutUser( biCharDBID, pwszCharName, Reason::Disconnect ); m_mCharNameRoomIndex.erase( pwszCharName ); // Delete LadderRoom if( pLadderRoom->bIsEmpty() ) { m_mRoomIndexRoomPtr.erase( pLadderRoom->GetRoomIndex() ); _OnDestroyRoom( pLadderRoom ); } else if( pLadderRoom->GetLeaderCharDBID() == 0 ) { pLadderRoom->AdjustNewLeader(); } } void CRoomRepository::SendPlayingRoomList( CDNUserSession* pSession, MatchType::eCode MatchType, UINT uiPage/*=1*/ ) { std::vector vRoomList; UINT uiMaxPage = 0; #if defined(PRE_ADD_DWC) UINT uiRoomPerPage = Common::RoomListPerPage/ LadderSystem::GetNeedTeamCount(MatchType); #else UINT uiRoomPerPage = Common::RoomListPerPage/MatchType; #endif int iRet = ERROR_GENERIC_INVALIDREQUEST; std::map>::iterator itor = m_mMatchTypePlayingRoomIndex.find( MatchType ); if( itor != m_mMatchTypePlayingRoomIndex.end() ) { UINT uiRoomSize = static_cast((*itor).second.size()); uiMaxPage = uiRoomSize%uiRoomPerPage == 0 ? uiRoomSize/uiRoomPerPage : (uiRoomSize/uiRoomPerPage)+1; } if( uiPage > uiMaxPage || uiPage == 0 ) { iRet = uiMaxPage == 0 ? ERROR_NONE : ERROR_LADDERSYSTEM_CANT_EXIST_ROOMLIST_PAGE; } else { iRet = ERROR_NONE; vRoomList.reserve( Common::RoomListPerPage ); std::list::iterator Litor = (*itor).second.begin(); if( (*itor).second.size() >= (uiPage-1)*Common::RoomListPerPage ) { std::advance( Litor, (uiPage-1)*Common::RoomListPerPage ); for( Litor ; Litor!=(*itor).second.end() ; ++Litor ) { vRoomList.push_back( GetRoomPtr( *Litor ) ); if( vRoomList.size() >= uiRoomPerPage ) break; } } else { iRet = ERROR_LADDERSYSTEM_CANT_EXIST_ROOMLIST_PAGE; } } pSession->SendLadderPlayingRoomList( iRet, vRoomList, uiMaxPage ); } bool CRoomRepository::bIsExist( const WCHAR* pwszCharName ) { std::map::iterator itor = m_mCharNameRoomIndex.find( pwszCharName ); if( itor == m_mCharNameRoomIndex.end() ) return false; _ASSERT( m_mRoomIndexRoomPtr.end() != m_mRoomIndexRoomPtr.find( (*itor).second ) ); return true; } CRoom* CRoomRepository::GetRoomPtr( const WCHAR* pwszCharName ) { std::map::iterator itor = m_mCharNameRoomIndex.find( pwszCharName ); if( itor == m_mCharNameRoomIndex.end() ) return NULL; std::map::iterator itor2 = m_mRoomIndexRoomPtr.find( (*itor).second ); if( itor2 == m_mRoomIndexRoomPtr.end() ) return NULL; return (*itor2).second; } CRoom* CRoomRepository::GetRoomPtr( INT64 biRoomIndex ) { std::map::iterator itor2 = m_mRoomIndexRoomPtr.find( biRoomIndex ); if( itor2 == m_mRoomIndexRoomPtr.end() ) return NULL; return (*itor2).second; } int CRoomRepository::GetAvgMatchingTimeSec( MatchType::eCode MatchType ) { return m_pMatchingSystem->GetAvgMatchingTimeSec(MatchType); } void CRoomRepository::_OnDestroyRoom( CRoom* pLadderRoom ) { if( pLadderRoom->GetOpponentRoomIndex() > 0 ) { std::map::iterator itor = m_mRoomIndexRoomPtr.find( pLadderRoom->GetOpponentRoomIndex() ); if( itor != m_mRoomIndexRoomPtr.end() ) { CRoom* pOpponentLadderRoom = (*itor).second; if( pOpponentLadderRoom->GetOpponentRoomIndex() == pLadderRoom->GetRoomIndex() ) { switch( pOpponentLadderRoom->GetRoomState() ) { case RoomState::WaitMatching: case RoomState::Matched: { pOpponentLadderRoom->ChangeRoomState( RoomState::WaitUser ); break; } } pOpponentLadderRoom->ClearOpponentRoomIndex(); } } } if( pLadderRoom->GetRoomState() == RoomState::Playing ) { DeletePlayingList( pLadderRoom ); } #if defined( _WORK ) std::cout << "RoomIndex:" << pLadderRoom->GetRoomIndex() << " ÆÄ±«" << std::endl; #endif // #if defined( _WORK ) SAFE_DELETE( pLadderRoom ); } void CRoomRepository::InsertPlayingList( CRoom* pLadderRoom ) { CRoom* pOpponentRoom = GetRoomPtr( pLadderRoom->GetOpponentRoomIndex() ); if( pOpponentRoom == NULL ) return; if( pLadderRoom->bIsValidOpponentRoom( pOpponentRoom, RoomState::Playing ) == false ) return; std::map>::iterator itor = m_mMatchTypePlayingRoomIndex.find( pLadderRoom->GetMatchType() ); if( itor == m_mMatchTypePlayingRoomIndex.end() ) { std::list Temp; Temp.push_back( pLadderRoom->GetRoomIndex() ); m_mMatchTypePlayingRoomIndex.insert( std::make_pair(pLadderRoom->GetMatchType(),Temp) ); #if defined( _WORK ) std::cout << "RoomIndex:" << pLadderRoom->GetRoomIndex() << " PlayingList µî·Ï" << std::endl; #endif // #if defined( _WORK ) } else { std::list::iterator Litor = std::find( (*itor).second.begin(), (*itor).second.end(), pLadderRoom->GetRoomIndex() ); if( Litor != (*itor).second.end() ) { _ASSERT(0); return; } Litor = std::find( (*itor).second.begin(), (*itor).second.end(), pOpponentRoom->GetRoomIndex() ); if( Litor != (*itor).second.end() ) { #if defined( _WORK ) std::cout << "RoomIndex:" << pOpponentRoom->GetRoomIndex() << " OpponentRoomÀÌ ÀÌ¹Ì PlayingList µî·ÏµÇ¾î ÀÖÀ¸¹Ç·Î Skip" << std::endl; #endif // #if defined( _WORK ) return; } (*itor).second.push_front( pLadderRoom->GetRoomIndex() ); #if defined( _WORK ) std::cout << "RoomIndex:" << pLadderRoom->GetRoomIndex() << " PlayingList µî·Ï" << std::endl; #endif // #if defined( _WORK ) } } void CRoomRepository::DeletePlayingList( CRoom* pLadderRoom ) { std::map>::iterator itor = m_mMatchTypePlayingRoomIndex.find( pLadderRoom->GetMatchType() ); if( itor == m_mMatchTypePlayingRoomIndex.end() ) return; #if defined( _WORK ) size_t PrevSize = (*itor).second.size(); #endif // #if defined( _WORK ) (*itor).second.remove( pLadderRoom->GetRoomIndex() ); #if defined( _WORK ) if( PrevSize > (*itor).second.size() ) { std::cout << "RoomIndex:" << pLadderRoom->GetRoomIndex() << " PlayingList »èÁ¦" << std::endl; } #endif // #if defined( _WORK ) }