DragonNest/Server/DNMasterServer/DNDivisionManager.cpp
Cussrro 47f7895977 Revert "修复编码问题"
This reverts commit 9e69c01767.
2024-12-21 10:04:04 +08:00

7437 lines
No EOL
229 KiB
C++

//note -2hogi
//MasterServer의 기본 Thread모델(처리에 대한것)은 Process Thread에 의한 SingleThread호출 방식 인터날아이들프로세스는 Process Thread에 의한 호출로
//내부 처리루틴에 대한 동기화를 필요치 않는다. 그런것들을 넣어주시고 성능문제발생시 또는 외부쓰레드이용시(예 idleprocess 같은거)에는
//Division객체의 내부 객체의 동기화를 필요로 하게된다.
#include "stdafx.h"
#include "DNDivisionManager.h"
#include "DNGameConnection.h"
#include "DNVillageConnection.h"
#include "DNLoginConnection.h"
#include "DNserviceConnection.h"
#include "DNExtManager.h"
#include "DNUser.h"
//#include "DNParty.h"
#include "DNPvP.h"
#include "IniFile.h"
#include "util.h"
#include "log.h"
#include "DNWaitUserManager.h"
#include "DNLogConnection.h"
#include "DNFarm.h"
#include "TimeSet.h"
#include "DNGuildWarManager.h"
#ifdef PRE_ADD_DOORS
#include "DNDoorsConnection.h"
#endif //#ifdef PRE_ADD_DOORS
#if defined(_KR)
#include "DNNexonAuth.h"
#elif defined(_CH)
#include "DNShandaFCM.h"
#elif defined (_JP) && defined (WIN64)
#include "DNNHNNetCafe.h"
#elif defined(_TW)
#include ".\\TW\\DNGamaniaAuth.h"
#elif defined(_US)
#include "DNNexonPI.h"
#elif defined(_TH)
#include "DNAsiaSoftPCCafe.h"
#endif // _KR _CH _JP _TW
extern TMasterConfig g_Config;
CDivisionManager * g_pDivisionManager = NULL;
CDivisionManager::CDivisionManager()
{
_ASSERT( g_Config.nWorldSetID > 0 );
::memset(m_dwTick, 0, sizeof(m_dwTick));
for (int nIndex = 0 ; LOGINCOUNTMAX > nIndex ; ++nIndex) {
if (0 < nIndex && !g_Config.LoginInfo[nIndex].nPort) {
// 최소 1개의 로그인 서버 세션은 생성하고 연결정보가 없는 나머지 세션들은 넘김
m_pLoginConnectionList[nIndex] = NULL;
continue;
}
m_pLoginConnectionList[nIndex] = new CDNLoginConnection;
DN_ASSERT(NULL != m_pLoginConnectionList[nIndex], "Invalid!");
m_pLoginConnectionList[nIndex]->SetIp(g_Config.LoginInfo[nIndex].szIP);
m_pLoginConnectionList[nIndex]->SetPort(g_Config.LoginInfo[nIndex].nPort);
// P.S.> LO 의 IP / PORT 정보가 없으면 생성 않함 ??? ↔ 예외상황 방지 위해 일단 모두 생성함 ???
}
m_pLoginConnection = m_pLoginConnectionList[0];
DN_ASSERT(NULL != m_pLoginConnection, "Invalid!");
m_GameServerConList.clear();
m_VillageServerConList.clear();
m_AccountDBIDList.clear();
m_SessionIDList.clear();
m_UserNameList.clear();
m_CharacterDBIDList.clear();
// PvP
for( UINT i=1 ; i<=PvPCommon::Common::MaxRoomCount ; ++i )
m_listPvPIndex.push_back( i );
m_bDestroyFarm = false;
m_nFarmGameindex = -1;
m_cPvPLobbyVillageID = 0;
m_unPvPLobbyChannelID = 0;
m_nPvPLobbyMapIndex = 0;
m_dwCheckVillageChannelTick = timeGetTime();
#if defined(PRE_FIX_DELAY_MASTER_CHECKVILLAGECHANNEL)
m_dwCheckVillageChannelStartTick = m_dwCheckVillageChannelTick;
#endif
m_nProcessCount = 0;
#ifdef PRE_MOD_OPERATINGFARM
m_dwFarmDataCreateTick = 0;
#endif //#ifdef PRE_MOD_OPERATINGFARM
#ifdef PRE_ADD_STEAM_USERCOUNT
m_nSteamUserCount = 0;
#endif //#ifdef PRE_ADD_STEAM_USERCOUNT
#if defined( PRE_PVP_GAMBLEROOM )
m_bGambleRoomFlag = false;
m_dwGambleRoomSendTick = 0;
#endif
}
CDivisionManager::~CDivisionManager()
{
ScopeLock<CSyncLock> Lock(m_Sync);
std::vector <CDNGameConnection*>::iterator ig;
for (ig = m_GameServerConList.begin(); ig != m_GameServerConList.end(); ig++)
SAFE_DELETE((*ig));
std::vector <CDNVillageConnection*>::iterator iv;
for (iv = m_VillageServerConList.begin(); iv != m_VillageServerConList.end(); iv++)
SAFE_DELETE((*iv));
std::map <UINT, CDNUser*>::iterator iu;
for (iu = m_AccountDBIDList.begin(); iu != m_AccountDBIDList.end(); iu++)
SAFE_DELETE((*iu).second);
// PvP
for( _TPvPMap::iterator itor=m_mPvP.begin() ; itor!=m_mPvP.end() ; ++itor )
SAFE_DELETE( (*itor).second );
m_mPvP.clear();
std::map <UINT, CDNFarm*>::iterator ifa;
for (ifa = m_mFarmList.begin(); ifa != m_mFarmList.end(); ifa++)
SAFE_DELETE((*ifa).second);
m_mFarmList.clear();
m_GameServerConList.clear();
m_VillageServerConList.clear();
m_AccountDBIDList.clear();
m_SessionIDList.clear();
m_CharacterDBIDList.clear();
m_UserNameList.clear();
for (int nIndex = 0 ; LOGINCOUNTMAX > nIndex ; ++nIndex) {
SAFE_DELETE(m_pLoginConnectionList[nIndex]);
}
m_pLoginConnection = NULL;
}
void CDivisionManager::CheckVillageChannel( DWORD dwCurTick )
{
const int CHECK_PERCENTAGE_VALUE = 70;
#if defined(PRE_FIX_DELAY_MASTER_CHECKVILLAGECHANNEL)
if( dwCurTick - m_dwCheckVillageChannelStartTick <= 1000*60*3 ) //처음 시작후 3분간은 포화상태 체크 안함
return;
#endif
if( dwCurTick - m_dwCheckVillageChannelTick <= 1000*30 )
return;
m_dwCheckVillageChannelTick = dwCurTick;
struct TTempChannel
{
int iChannelID;
int iMeritID;
int iPercentage;
bool bVisibility;
};
std::map<std::pair<int,int>,std::vector<TTempChannel>> mList;
#if defined(PRE_ADD_CHANNELNAME)
std::multimap<std::pair<int,int>,std::wstring> mPassList;
#else
std::map<std::pair<int,int>,int> mPassList;
#endif //#if defined(PRE_ADD_CHANNELNAME)
for( UINT i=0 ; i<m_VillageServerConList.size() ; ++i )
{
CDNVillageConnection* pVillageCon = m_VillageServerConList[i];
if( pVillageCon == NULL || pVillageCon->GetConnectionCompleted() == false )
continue;
const TVillageInfo* pVillageInfo = pVillageCon->GetVillageChannelInfo();
if( pVillageInfo == NULL )
continue;
for( UINT j=0 ; j<pVillageInfo->vOwnedChannelList.size() ; ++j )
{
TTempChannel Temp;
Temp.iChannelID = pVillageInfo->vOwnedChannelList[j].nChannelID;
Temp.iMeritID = pVillageInfo->vOwnedChannelList[j].nMeritBonusID;
Temp.iPercentage = pVillageInfo->vOwnedChannelList[j].GetUserPercentage();
Temp.bVisibility = pVillageInfo->vOwnedChannelList[j].bVisibility;
std::pair<int,int> KeyPair = std::make_pair(pVillageInfo->vOwnedChannelList[j].nMapIdx,Temp.iMeritID);
#if defined(PRE_ADD_CHANNELNAME)
bool bContinueFlag = false;
for (std::multimap<std::pair<int,int>,std::wstring>::iterator iter = mPassList.lower_bound(KeyPair); iter != mPassList.upper_bound(KeyPair); iter++)
{
if( iter != mPassList.end() && _wcsicmp(pVillageInfo->vOwnedChannelList[j].wszLanguageName, iter->second.c_str() ) == 0 )
{
bContinueFlag = true;
break;
}
}
if (bContinueFlag)
continue;
#else
if( mPassList.find( KeyPair ) != mPassList.end() )
continue;
#endif //#if defined(PRE_ADD_CHANNELNAME)
if( Temp.bVisibility == true && Temp.iPercentage < CHECK_PERCENTAGE_VALUE )
{
mList.erase( KeyPair );
#if defined(PRE_ADD_CHANNELNAME)
mPassList.insert( std::make_pair(KeyPair,pVillageInfo->vOwnedChannelList[j].wszLanguageName) );
#else
mPassList.insert( std::make_pair(KeyPair,1) );
#endif
continue;
}
std::map<std::pair<int,int>,std::vector<TTempChannel>>::iterator itor = mList.find( KeyPair );
if( itor == mList.end() )
{
std::vector<TTempChannel> vTemp;
vTemp.push_back( Temp );
mList.insert( std::make_pair(KeyPair,vTemp) );
}
else
{
(*itor).second.push_back( Temp );
}
}
}
for( std::map<std::pair<int,int>,std::vector<TTempChannel>>::iterator itor=mList.begin() ; itor!=mList.end() ; ++itor )
{
for( UINT i=0 ; i<(*itor).second.size() ; ++i )
{
if( (*itor).second[i].bVisibility == false )
{
#if defined( _WORK )
std::cout << "채널 포화상태여서 추가로 ChannelID=" << (*itor).first.first << " 오픈함" << std::endl;
#endif // #if defined( _WORK )
if( ChannelControl( (*itor).second[i].iChannelID, true, 0 ) == true )
SendVillageInfo();
break;
}
}
}
}
#ifdef _WORK
void CDivisionManager::ReloadExt()
{
std::vector <CDNGameConnection*>::iterator igame;
for (igame = m_GameServerConList.begin(); igame != m_GameServerConList.end(); igame++)
(*igame)->SendReloadExt();
std::vector <CDNVillageConnection*>::iterator ivill;
for (ivill = m_VillageServerConList.begin(); ivill != m_VillageServerConList.end(); ivill++)
(*ivill)->SendReloadExt();
}
void CDivisionManager::ReloadAct()
{
std::vector <CDNGameConnection*>::iterator igame;
for (igame = m_GameServerConList.begin(); igame != m_GameServerConList.end(); igame++)
(*igame)->SendReloadAct();
}
#endif //#ifdef _WORK
void CDivisionManager::InternalIdleProcess(ULONG nCurTick)
{
//여기는 내부쓰레드에서 호출입니다(process thread는 내부로 봄) 동기화 관련없이 자유롭게 작성해주세요
static UINT s_nIdleCount = 0;
//CheckIntervalDeletePartyMember(nCurTick);
SendVillageInfo();
CheckProcessFarm();
SendFarmInfo();
#ifndef _WORK
if ((s_nIdleCount%5) == 0)
CheckZombie(nCurTick);
#endif
#if defined(PRE_ADD_GUILDWAR_ONSCHEDULE)
if( g_pGuildWarManager )
g_pGuildWarManager->DoUpdate(nCurTick);
#endif
CheckVillageChannel( nCurTick );
#ifdef PRE_ADD_STEAM_USERCOUNT
if ((s_nIdleCount%120) == 0)
g_Log.Log(LogType::_STEAMUSERCOUNT, L"Users[%d]Steam[%d]\n", (int)m_AccountDBIDList.size(), m_nSteamUserCount);
#endif //#ifdef PRE_ADD_STEAM_USERCOUNT
s_nIdleCount++;
}
void CDivisionManager::ExternalIdleProcess(ULONG nCurTick)
{
//process Thread가 아닌 외부 Thread에서의 호출입니다. 아이들링 작업시 사용하는 객체가 동기가 걸필요 있는지 필히 확인후 작성해주세요 -2hogi
for (int nIndex = 0 ; LOGINCOUNTMAX > nIndex ; ++nIndex) {
CDNLoginConnection *pLoginCon = m_pLoginConnectionList[nIndex];
if (!pLoginCon) {
continue;
}
pLoginCon->Reconnect(nCurTick);
}
if (g_pServiceConnection)
g_pServiceConnection->Reconnect(nCurTick);
if( g_pLogConnection )
g_pLogConnection->Reconnect( nCurTick );
if (LOGINSERVERLISTSORTTERM < GetTickTerm(GetTick(eTickSortLoginServerList), nCurTick)) {
SortLoginConnectionList();
SetTick(eTickSortLoginServerList, nCurTick);
}
}
// InternalIdleProcess 와 같은 Timing 입니다.
// InternalIdleProcess 가 Interval 이 너무 길어 따로 함수 분류하였습니다.
void CDivisionManager::UpdatePvPRoom( const UINT uiCurTick )
{
CTimeSet CurTime;
#if defined( PRE_PVP_GAMBLEROOM )
int nGambleRoomCount = 0;
int nTotalGambleRoomCount = 0;
#endif
for( _TPvPMap::iterator itor=m_mPvP.begin() ; itor!=m_mPvP.end() ; )
{
CDNPvP* pPvPRoom = (*itor).second;
pPvPRoom->Update( uiCurTick );
if( pPvPRoom->GetEventRoomIndex() > 0 && pPvPRoom->GetEventDataPtr()->_tEndTime != -1)
{
if( CurTime.GetTimeT32_LC() >= pPvPRoom->GetEventDataPtr()->_tEndTime )
{
CDNVillageConnection* pVillageCon = GetVillageConnectionByVillageID( pPvPRoom->GetVillageID() );
(*itor).second->bLeaveAll( pVillageCon, PvPCommon::LeaveType::DestroyRoom );
if( pVillageCon )
pVillageCon->SendPvPDestroyRoom( pPvPRoom->GetVillageChannelID(), pPvPRoom->GetIndex() );
delete pPvPRoom;
m_mPvP.erase( itor++ );
continue;
}
}
#if defined( PRE_PVP_GAMBLEROOM )
if( pPvPRoom->GetGambleRoomType() > 0 )
{
if( pPvPRoom->GetRoomState() == PvPCommon::RoomState::None || pPvPRoom->GetRoomState() == PvPCommon::RoomState::Starting )
nGambleRoomCount++;
nTotalGambleRoomCount++;
}
#endif
++itor;
}
#if defined( PRE_PVP_GAMBLEROOM )
if( m_bGambleRoomFlag && nGambleRoomCount <= 0 )
{
if( m_dwGambleRoomSendTick > uiCurTick )
return;
m_dwGambleRoomSendTick = uiCurTick + SENDGAMBLEROOMWAITTICK;
CDNVillageConnection* pVillageConnection = g_pDivisionManager->GetVillageConnectionByVillageID( g_pDivisionManager->GetPvPLobbyVillageID() );
if( pVillageConnection )
{
pVillageConnection->SendGambleRoomCreate( nTotalGambleRoomCount );
}
}
#endif
}
bool CDivisionManager::AddSelectJoin(int nSID, const WCHAR * pwszCharacterName)
{
int nTemp = 0, nTemp2 = 0;
if (GetGameConnectionByManagedID(nSID) == NULL)
return false;
if (IsSelectJoin(pwszCharacterName, nTemp))
{
ScopeLock<CSyncLock> Lock(m_Sync);
std::vector <TSelectJoin>::iterator ii;
for (ii = m_SelectJoinList.begin(); ii != m_SelectJoinList.end(); ii++)
{
if (!__wcsicmp_l((*ii).wszCharacterName, pwszCharacterName))
{
(*ii).nSID = nSID;
return true;
}
}
}
else
{
TSelectJoin Join;
memset(&Join, 0, sizeof(TSelectJoin));
Join.nSID = nSID;
_wcscpy(Join.wszCharacterName, _countof(Join.wszCharacterName), pwszCharacterName, (int)wcslen(pwszCharacterName));
ScopeLock<CSyncLock> Lock(m_Sync);
m_SelectJoinList.push_back(Join);
}
return true;
}
void CDivisionManager::ClearSelectJoin()
{
ScopeLock<CSyncLock> Lock(m_Sync);
m_SelectJoinList.clear();
}
bool CDivisionManager::IsSelectJoin(const WCHAR * pwszCharacterName, int &nSID)
{
ScopeLock<CSyncLock> Lock(m_Sync);
if (m_SelectJoinList.empty()) return false;
std::vector <TSelectJoin>::iterator ii;
for (ii = m_SelectJoinList.begin(); ii != m_SelectJoinList.end(); ii++)
{
if (!__wcsicmp_l((*ii).wszCharacterName, pwszCharacterName))
{
nSID = (*ii).nSID;
return true;
}
}
return false;
}
DWORD CDivisionManager::GetTick(eTick pTick) const
{
DN_ASSERT(CHECK_LIMIT(pTick, eTickCnt), "Invalid!");
return(m_dwTick[pTick]);
}
void CDivisionManager::SetTick(eTick pTick) const
{
DN_ASSERT(CHECK_LIMIT(pTick, eTickCnt), "Invalid!");
m_dwTick[pTick] = ::GetTickCount();
m_dwTick[pTick] = (m_dwTick[pTick])?(m_dwTick[pTick]):(1);
}
void CDivisionManager::SetTick(eTick pTick, DWORD pTick32) const
{
DN_ASSERT(CHECK_LIMIT(pTick, eTickCnt), "Invalid!");
DN_ASSERT(0 != pTick32, "Invalid!");
m_dwTick[pTick] = (pTick32)?(pTick32):(1);
}
void CDivisionManager::ResetTick(eTick pTick) const
{
DN_ASSERT(CHECK_LIMIT(pTick, eTickCnt), "Invalid!");
m_dwTick[pTick] = 0;
}
BOOL CDivisionManager::IsTick(eTick pTick) const
{
DN_ASSERT(CHECK_LIMIT(pTick, eTickCnt), "Invalid!");
return(0 != m_dwTick[pTick]);
}
bool CDivisionManager::DelConnection(CConnection *pCon, eConnectionKey eConType)
{
ScopeLock<CSyncLock> Lock(m_Sync);
if (eConType == CONNECTIONKEY_LOGIN)
{
CDNLoginConnection * pLoginCon = reinterpret_cast<CDNLoginConnection*>(pCon);
DetachUserloginID(pLoginCon->GetServerID());
return true;
}
else if (eConType == CONNECTIONKEY_VILLAGE)
{
CDNVillageConnection * pVillCon = reinterpret_cast<CDNVillageConnection*>(pCon);
// 빌리지쪽 애들 다 끊어버리기
DetachUserByVillageID( pVillCon->GetVillageID() );
// 해당서버 PvP방 모두 정리
for( _TPvPMap::iterator itor=m_mPvP.begin() ; itor!=m_mPvP.end() ; )
{
CDNPvP* pPvPRoom = (*itor).second;
bool bDestroy = false;
if( pPvPRoom->GetVillageID() == pVillCon->GetVillageID() )
bDestroy = pPvPRoom->bDisconnectServer( eConType );
if( bDestroy )
{
delete pPvPRoom;
itor = m_mPvP.erase( itor );
}
else
++itor;
}
bool bCheck = false;
int nVillageID = -1;
std::vector <CDNVillageConnection*>::iterator ii;
for (ii = m_VillageServerConList.begin(); ii != m_VillageServerConList.end(); ii++)
{
if ((*ii) == (CDNVillageConnection*)pCon)
{
CDNVillageConnection * pVillageCon = (*ii);
nVillageID = pVillageCon->GetVillageID();
m_VillageServerConList.erase(ii);
g_Log.Log(LogType::_NORMAL, g_Config.nWorldSetID, 0, 0, 0, L"[VillageID:%d] DelConnection", pVillageCon->GetVillageID());
bCheck = true;
break;
}
}
//빌라지가 끊겨따아~ 로그인이랑 빌리지에게 채널리스트변경을 알리자아~
if (bCheck)
{
SendAllLoginServerVillageInfoDelete(nVillageID);
for (ii = m_VillageServerConList.begin(); ii != m_VillageServerConList.end(); ii++)
(*ii)->SendVillageInfoDelete(nVillageID);
return true;
}
}
else if (eConType == CONNECTIONKEY_GAME)
{
CDNGameConnection * pGCon = reinterpret_cast<CDNGameConnection*>(pCon);
// 게임쪽 애들 다 끊어버리기
DetachUserByGameID( pGCon->GetGameID() );
// 해당서버 PvP방 모두 정리
for( _TPvPMap::iterator itor=m_mPvP.begin() ; itor!=m_mPvP.end() ; )
{
CDNPvP* pPvPRoom = (*itor).second;
bool bDestroy = false;
if( pPvPRoom->GetGameServerID() == pGCon->GetGameID() )
bDestroy = pPvPRoom->bDisconnectServer( eConType );
if( bDestroy )
{
//시스템 길드전 예외처리
if (g_pGuildWarManager && pPvPRoom->GetIsGuildWarSystem())
g_pGuildWarManager->SetDropTournament(pPvPRoom->GetIndex());
CDNVillageConnection* pVillageCon = GetVillageConnectionByVillageID( (*itor).second->GetVillageID() );
if( pVillageCon )
pVillageCon->SendPvPDestroyRoom( (*itor).second->GetVillageChannelID(), (*itor).second->GetIndex() );
if (pPvPRoom->GetEventRoomIndex() > 0)
g_Log.Log(LogType::_PVPROOM, g_Config.nWorldSetID, 0, 0, 0, L"DelConnection-Game [Index:%d][Room:%d][Event:%d] \r\n", pPvPRoom->GetIndex(), pPvPRoom->GetGameServerRoomIndex(), pPvPRoom->GetEventRoomIndex());
delete pPvPRoom;
itor = m_mPvP.erase( itor );
}
else
++itor;
}
std::map <UINT, CDNFarm*>::iterator ifarm;
for (ifarm = m_mFarmList.begin(); ifarm != m_mFarmList.end(); ifarm++)
{
if ((*ifarm).second->GetAssignedServerID() == pGCon->GetGameID())
{
(*ifarm).second->DestroyFarm();
m_bDestroyFarm = true;
m_nFarmGameindex = -1;
}
}
if (m_bDestroyFarm)
g_Log.Log(LogType::_FARM, L"FarmGameConnection Destroy GameCon[%d]\n", pGCon->GetGameID());
std::vector <CDNGameConnection*>::iterator ii;
for (ii = m_GameServerConList.begin(); ii != m_GameServerConList.end(); ii++)
{
if ((*ii) == (CDNGameConnection*)pCon)
{
CDNGameConnection * pGameCon = (*ii);
m_GameServerConList.erase(ii);
g_Log.Log(LogType::_NORMAL, g_Config.nWorldSetID, 0, 0, 0, L"[GameID:%d] DelConnection", pGameCon->GetGameID());
return true;
}
}
}
else if (eConType == CONNECTIONKEY_LOG || eConType == CONNECTIONKEY_SERVICEMANAGER )
{
return true;
}
_DANGER_POINT();
return false;
}
CDNLoginConnection * CDivisionManager::FindLoginConnection(const char* pIp, const int nPort)
{
for (int nIndex = 0 ; LOGINCOUNTMAX > nIndex ; ++nIndex) {
CDNLoginConnection *pLoginCon = m_pLoginConnectionList[nIndex];
if (!pLoginCon) {
continue;
}
if (!strncmp(pLoginCon->GetIp(), pIp, IPLENMAX) && pLoginCon->GetPort() == nPort) {
return pLoginCon;
}
}
return NULL;
}
void CDivisionManager::SortLoginConnectionList() const
{
std::vector<CDNLoginConnection*> List1;
for (int nIndex = 0 ; LOGINCOUNTMAX > nIndex ; ++nIndex) {
CDNLoginConnection *pLoginCon = m_pLoginConnectionList[nIndex];
if (!pLoginCon) {
continue;
}
List1.push_back(pLoginCon);
}
if (List1.empty()) {
return;
}
std::sort(List1.begin(), List1.end(), CDNLoginConnection::CSortLoginServerSession());
std::vector<CDNLoginConnection*> List2;
std::remove_copy_if(List1.begin(), List1.end(), std::back_inserter(List2), CDNLoginConnection::CRemoveCopyIfLoginServerSession());
if (1 < List2.size()) {
std::random_shuffle(List2.begin(), List2.end()); // 주의 !!! - ::srand() 로 랜덤시드 값이 미리 지정되어야 함
}
if (List2.empty()) {
::InterlockedExchangePointer(reinterpret_cast<void**>(&m_pLoginConnection), List1[0]); // m_pLoginConnection 의 주소가 운영체제 타입에 따라 32/64 비트로 정렬 (aligned) 되어 있지 않으면 실패 !!!
}
else {
::InterlockedExchangePointer(reinterpret_cast<void**>(&m_pLoginConnection), List2[0]); // m_pLoginConnection 의 주소가 운영체제 타입에 따라 32/64 비트로 정렬 (aligned) 되어 있지 않으면 실패 !!!
}
DN_ASSERT(NULL != m_pLoginConnection, "Invalid!");
}
CDNGameConnection * CDivisionManager::GameServerConnected(const char * pIP, USHORT nPort)
{
ScopeLock<CSyncLock> Lock(m_Sync);
std::vector <CDNGameConnection*>::iterator ii;
for (ii = m_GameServerConList.begin(); ii != m_GameServerConList.end(); ii++)
{
if ((*ii)->GetPort() == nPort)
{
_DANGER_POINT();
return NULL;
}
}
CDNGameConnection * pCon = new CDNGameConnection;
if (pCon == NULL)
return NULL;
pCon->SetIp(pIP);
pCon->SetPort(nPort);
pCon->SetSessionID(g_IDGenerator.GetGameConnectionID());
pCon->SetGameID(pCon->GetSessionID());
#if !defined(PRE_FIX_LIVE_CONNECT)
m_GameServerConList.push_back(pCon);
#endif //#if !defined(PRE_FIX_LIVE_CONNECT)
return pCon;
}
#if defined(PRE_FIX_LIVE_CONNECT)
void CDivisionManager::AddGameServerConnection(CDNGameConnection* pCon)
{
ScopeLock<CSyncLock> Lock(m_Sync);
m_GameServerConList.push_back(pCon);
}
void CDivisionManager::AddVillageServerConnection(CDNVillageConnection* pCon)
{
ScopeLock<CSyncLock> Lock(m_Sync);
m_VillageServerConList.push_back(pCon);
}
#endif
void CDivisionManager::GameServerRegist(CDNGameConnection * pCon)
{
CDNUser * pUser = NULL;
int nLocation = _LOCATION_NONE;
int nChannelID = -1;
int nMapIdx = -1;
std::map <UINT, CDNUser*>::iterator ii;
for (ii = m_AccountDBIDList.begin(); ii != m_AccountDBIDList.end(); ii++)
{
pUser = (*ii).second;
if (pUser->GetUserState() == STATE_NONE) continue;
nLocation = _LOCATION_NONE;
nChannelID = -1;
nMapIdx = -1;
if (pUser->GetUserState() == STATE_CHECKVILLAGE || pUser->GetUserState() == STATE_CHECKGAME)
nLocation = _LOCATION_MOVE;
else if (pUser->GetUserState() == STATE_VILLAGE)
{
nLocation = _LOCATION_VILLAGE;
nChannelID = pUser->GetChannelID();
}
else if (pUser->GetUserState() == STATE_GAME)
{
nLocation = _LOCATION_GAME;
nMapIdx = pUser->m_nMapIndex;
}
pCon->SendAddUserState((*ii).second->GetCharacterName(), (*ii).second->GetCharacterDBID(), nLocation, -1, nChannelID, nMapIdx );
}
}
CDNVillageConnection * CDivisionManager::VillageServerConnected(const char * pIP, USHORT nPort)
{
ScopeLock<CSyncLock> Lock(m_Sync);
std::vector <CDNVillageConnection*>::iterator ii;
for (ii = m_VillageServerConList.begin(); ii != m_VillageServerConList.end(); ii++)
{
if ((*ii)->GetPort() == nPort)
{
_DANGER_POINT();
return NULL;
}
}
CDNVillageConnection * pCon = new CDNVillageConnection;
if (pCon == NULL)
return NULL;
pCon->SetIp(pIP);
pCon->SetPort(nPort);
pCon->SetSessionID(g_IDGenerator.GetVillageConnectionID());
#if !defined(PRE_FIX_LIVE_CONNECT)
m_VillageServerConList.push_back(pCon);
#endif //#if !defined(PRE_FIX_LIVE_CONNECT)
return pCon;
}
void CDivisionManager::SendWorldUserStateList(CDNVillageConnection * pCon)
{
CDNUser * pUser = NULL;
int nLocation = _LOCATION_NONE;
int nChannelID = -1;
int nMapIdx = -1;
std::map <UINT, CDNUser*>::iterator ii;
for (ii = m_AccountDBIDList.begin(); ii != m_AccountDBIDList.end(); ii++)
{
pUser = (*ii).second;
if (pUser->GetUserState() == STATE_NONE) continue;
nLocation = _LOCATION_NONE;
nChannelID = -1;
nMapIdx = -1;
if (pUser->GetUserState() == STATE_LOGIN)
nLocation = _LOCATION_LOGIN;
else if (pUser->GetUserState() == STATE_CHECKVILLAGE || pUser->GetUserState() == STATE_CHECKGAME)
nLocation = _LOCATION_MOVE;
else if (pUser->GetUserState() == STATE_VILLAGE)
{
nLocation = _LOCATION_VILLAGE;
nChannelID = pUser->GetChannelID();
}
else if (pUser->GetUserState() == STATE_GAME)
{
nLocation = _LOCATION_GAME;
nMapIdx = pUser->m_nMapIndex;
}
pCon->SendAddUserState((*ii).second->GetCharacterName(), (*ii).second->GetCharacterDBID(), nLocation, -1, nChannelID, nMapIdx );
}
}
CDNVillageConnection * CDivisionManager::GetFirstVillageServer()
{
if( m_VillageServerConList.size() > 0 )
{
return m_VillageServerConList[0];
}
return NULL;
}
CDNVillageConnection* CDivisionManager::GetFirstEnableVillageServer()
{
if (m_VillageServerConList.empty()) return NULL;
ScopeLock<CSyncLock> Lock(m_Sync);
std::vector <CDNVillageConnection*>::iterator ii;
for (ii = m_VillageServerConList.begin(); ii != m_VillageServerConList.end(); ii++)
{
if ((*ii)->GetActive() && (*ii)->GetConnectionCompleted())
return (*ii);
}
return NULL;
}
int CDivisionManager::GetGameConnectionCount()
{
ScopeLock<CSyncLock> Lock(m_Sync);
int nCount = 0;
std::vector <CDNGameConnection*>::iterator ii;
for (ii = m_GameServerConList.begin(); ii != m_GameServerConList.end(); ii++)
{
if ((*ii)->GetActive() && (*ii)->GetConnectionCompleted())
nCount++;
}
return nCount;
}
CDNGameConnection * CDivisionManager::GetFreeGameConnection(int * pExpServerID, int nReqRoomType)
{
if (m_GameServerConList.empty()) return NULL;
ScopeLock<CSyncLock> Lock(m_Sync);
UINT nRoomCnt = 0;
CDNGameConnection * pCon = NULL;
static unsigned int nCnt = 0;
int nTemp = 0;
bool bCheck;
int nCheckLevel;
while (1)
{
bCheck = true;
nCheckLevel = -1;
pCon = m_GameServerConList[nCnt++%m_GameServerConList.size()];
#ifdef _FINAL_BUILD
//파이날빌드에서는 농장서버는 농장만 할당되도록 한다.
if (m_nFarmGameindex != -1 && pCon->GetGameID() == m_nFarmGameindex && m_GameServerConList.size() > 1)
continue;
#endif
if (pCon == NULL) continue;
if ((nReqRoomType == REQINFO_TYPE_SINGLE || nReqRoomType == REQINFO_TYPE_PARTY || nReqRoomType == REQINFO_TYPE_FARM) && \
(pCon->GetAffinityType() != _GAMESERVER_AFFINITYTYPE_NORMAL && pCon->GetAffinityType() != _GAMESERVER_AFFINITYTYPE_HYBRYD))
{
bCheck = false;
nCheckLevel = 1;
}
else if ((nReqRoomType == REQINFO_TYPE_PVP || nReqRoomType == REQINFO_TYPE_PVP_BREAKINTO || nReqRoomType == REQINFO_TYPE_LADDER ) && (pCon->GetAffinityType() != _GAMESERVER_AFFINITYTYPE_PVP && pCon->GetAffinityType() != _GAMESERVER_AFFINITYTYPE_HYBRYD))
{
bCheck = false;
nCheckLevel = 3;
}
if (pCon->GetConnectionCompleted() == false || pCon->GetZeroPopulation())
bCheck = false;
if(bCheck && pCon && pCon->GetHasMargin())
break;
//오픈초기에 특정 게임컨넥션에만 몰리는 경우가 있어서 로그추가
if (m_GameServerConList.size() > 1 && nReqRoomType != REQINFO_TYPE_FARM)
g_Log.Log(LogType::_ERROR, L"PassFreeConReason SID[%d] ReqType[%d] Zero[%s] Margin[%s] CL[%d] CC[%s]\n", pCon->GetManagedID(), nReqRoomType, pCon->GetZeroPopulation() == true ? L"True" : L"False", pCon->GetHasMargin() == true ? L"True" : L"False", nCheckLevel, pCon->GetConnectionCompleted() ? L"True" : L"False");
if(nTemp++ == 100)
{
if (bCheck && pCon->GetZeroPopulation())
{
//check가 true상태에서 100번 확인이 끝나 그냥 검사부분이 무시되어지고 포인터가 넘어갈 수 있어 로그 추가
g_Log.Log(LogType::_ZEROPOPULATION, L"GetFreeGameConnection if(nTemp++ == 100) SID[%d] Zero[%s] Margin[%s]\n", pCon->GetManagedID(), pCon->GetZeroPopulation() == true ? L"True" : L"False", pCon->GetHasMargin() == true ? L"True" : L"False");
return NULL;
}
break;
}
}
if( pCon )
{
pCon->SetLastReqEnterGameTick();
}
return pCon;
}
CDNGameConnection * CDivisionManager::GetGameConnectionByGameID(int nGameID)
{
if (m_GameServerConList.empty()) return NULL;
ScopeLock<CSyncLock> Lock(m_Sync);
std::vector <CDNGameConnection*>::iterator ii;
for (ii = m_GameServerConList.begin(); ii != m_GameServerConList.end(); ii++)
{
if ((*ii)->GetGameID() == nGameID && (*ii)->GetConnectionCompleted())
return (*ii);
}
return NULL;
}
CDNGameConnection * CDivisionManager::GetGameConnectionByManagedID(int nSID )
{
if (m_GameServerConList.empty()) return NULL;
ScopeLock<CSyncLock> Lock(m_Sync);
std::vector <CDNGameConnection*>::iterator ii;
for (ii = m_GameServerConList.begin(); ii != m_GameServerConList.end(); ii++)
{
if ((*ii)->GetConnectionCompleted() && (*ii)->GetManagedID() == nSID)
return (*ii);
}
return NULL;
}
CDNVillageConnection * CDivisionManager::GetVillageConnectionByVillageID(int nVillageID)
{
if (m_VillageServerConList.empty()) return NULL;
ScopeLock<CSyncLock> Lock(m_Sync);
std::vector <CDNVillageConnection*>::iterator ii;
for (ii = m_VillageServerConList.begin(); ii != m_VillageServerConList.end(); ii++)
{
if ((*ii)->GetVillageID() == nVillageID && (*ii)->GetConnectionCompleted())
return (*ii);
}
return NULL;
}
#ifdef PRE_MOD_OPERATINGFARM
bool CDivisionManager::IsFarmGameConnectionAvailable(DWORD dwCurTick)
{
if (g_Config.nFarmServerID > 0 && IsFarmConnectionWatingTime(dwCurTick))
{
ScopeLock<CSyncLock> Lock(m_Sync);
std::vector <CDNGameConnection*>::iterator ii;
for (ii = m_GameServerConList.begin(); ii != m_GameServerConList.end(); ii++)
{
if ((*ii)->GetActive() && (*ii)->GetConnectionCompleted() && (*ii)->GetAffinityType() == _GAMESERVER_AFFINITYTYPE_FARM)
return true;
}
return false;
}
else
{
return GetGameConnectionCount() <= 0 ? false : true;
}
}
CDNGameConnection * CDivisionManager::GetFarmGameConnection(int * pExpServerID)
{
//GetFreeGameConnection안쪽 만지기가 살짝 무서워서 새로 땀 ㅋ
ScopeLock<CSyncLock> Lock(m_Sync);
std::vector <CDNGameConnection*>::iterator ii;
for (ii = m_GameServerConList.begin(); ii != m_GameServerConList.end(); ii++)
{
if ((*ii)->GetActive() && (*ii)->GetConnectionCompleted() && ((*ii)->GetAffinityType() == _GAMESERVER_AFFINITYTYPE_FARM || (*ii)->GetManagedID() == g_Config.nFarmServerID))
return (*ii);
}
return NULL;
}
#endif //#ifdef PRE_MOD_OPERATINGFARM
#if defined( PRE_FIX_WORLDCOMBINEPARTY )
CDNGameConnection * CDivisionManager::GetWorldCombineGameConnection()
{
CDNGameConnection * pCon = NULL;
for( int i=0;i<m_GameServerConList.size();i++)
{
pCon = m_GameServerConList[i];
if( pCon->GetWorldCombineGameServer() )
return pCon;
}
return NULL;
}
#endif
void CDivisionManager::SendLoginServer(const int iMainCmd, const int iSubCmd, const char *cBuf, const unsigned short uLen)
{
GetLoginConnection()->AddSendData(iMainCmd, iSubCmd, const_cast<char*>(cBuf), uLen);
}
void CDivisionManager::SendAllLoginServer(const int iMainCmd, const int iSubCmd, const char *cBuf, const unsigned short uLen)
{
for (int nIndex = 0 ; LOGINCOUNTMAX > nIndex ; ++nIndex) {
CDNLoginConnection * pLoginCon = m_pLoginConnectionList[nIndex];
if (!pLoginCon || !pLoginCon->GetActive()) {
continue;
}
pLoginCon->AddSendData(iMainCmd, iSubCmd, const_cast<char*>(cBuf), uLen);
}
}
void CDivisionManager::SendAllVillageServer(const int iMainCmd, const int iSubCmd, const char *cBuf, const unsigned short uLen)
{
ScopeLock<CSyncLock> Lock(m_Sync);
std::vector <CDNVillageConnection*>::iterator itor = m_VillageServerConList.begin();
for (; itor != m_VillageServerConList.end() ; ++itor) {
CDNVillageConnection* pVillageConnection = (*itor);
if (pVillageConnection)
pVillageConnection->AddSendData(iMainCmd, iSubCmd, const_cast<char*>(cBuf), uLen);
}
}
void CDivisionManager::SendAllGameServer(const int iMainCmd, const int iSubCmd, const char *cBuf, const unsigned short uLen)
{
ScopeLock<CSyncLock> Lock(m_Sync);
std::vector <CDNGameConnection*>::iterator itor = m_GameServerConList.begin();
for (; itor != m_GameServerConList.end(); ++itor) {
CDNGameConnection* pGameConnection = (*itor);
if (pGameConnection)
pGameConnection->AddSendData(iMainCmd, iSubCmd, const_cast<char*>(cBuf), uLen);
}
}
CDNLoginConnection* CDivisionManager::GetFirstEnableLoginServer()
{
for (int nIndex = 0 ; LOGINCOUNTMAX > nIndex ; ++nIndex) {
CDNLoginConnection * pLoginCon = m_pLoginConnectionList[nIndex];
if (!pLoginCon || !pLoginCon->GetActive()) {
continue;
}
return pLoginCon;
}
return NULL;
}
void CDivisionManager::SendAllLoginServerDetachUser(UINT nAccountDBID)
{
MALODetachUser packet;
memset(&packet, 0, sizeof(MALODetachUser));
packet.nAccountDBID = nAccountDBID;
SendAllLoginServer(MALO_DETACHUSER, 0, (char*)&packet, sizeof(packet));
}
void CDivisionManager::SendAllLoginServerVillageInfo(UINT nUserCnt, UINT nMaxUserCount, std::vector<TVillageInfo> * vList)
{
std::vector <TVillageInfo>::iterator ii;
for (ii = vList->begin(); ii != vList->end(); ii++)
{
MALOVillageInfo packet;
memset(&packet, 0, sizeof(packet));
packet.nVillageID = (*ii).cVillageID;
packet.nWorldUserCount = nUserCnt;
packet.nWorldMaxUserCount = nMaxUserCount;
for (int j = 0; j < (int)(*ii).vOwnedChannelList.size(); j++)
{
packet.Info[packet.cCount].nChannelID = (*ii).vOwnedChannelList[j].nChannelID;
packet.Info[packet.cCount].nChannelIdx = (*ii).vOwnedChannelList[j].nChannelIdx;
packet.Info[packet.cCount].nMapIdx = (*ii).vOwnedChannelList[j].nMapIdx;
packet.Info[packet.cCount].nCurrentUserCount = (*ii).vOwnedChannelList[j].nCurrentUser;
packet.Info[packet.cCount].nMaxUserCount = (*ii).vOwnedChannelList[j].nChannelMaxUser;
packet.Info[packet.cCount].nChannelAttribute = (*ii).vOwnedChannelList[j].nAttribute;
packet.Info[packet.cCount].nMeritBonusID = (*ii).vOwnedChannelList[j].nMeritBonusID;
if (packet.Info[packet.cCount].nMeritBonusID > 0)
{
const TMeritInfo * pInfo = g_pExtManager->GetMeritInfo(packet.Info[packet.cCount].nMeritBonusID);
if (pInfo)
{
packet.Info[packet.cCount].cMinLevel = pInfo->nMinLevel;
packet.Info[packet.cCount].cMaxLevel = pInfo->nMaxLevel;\
}
else
_DANGER_POINT();
}
packet.Info[packet.cCount].bVisibility = (*ii).vOwnedChannelList[j].bVisibility;
_strcpy(packet.Info[packet.cCount].szIP, _countof(packet.Info[packet.cCount].szIP), (*ii).szIP, (int)strlen((*ii).szIP));
packet.Info[packet.cCount].nPort = (*ii).nPort;
packet.Info[packet.cCount].nLimitLevel = (*ii).vOwnedChannelList[j].nLimitLevel;
packet.Info[packet.cCount].bShow = (*ii).vOwnedChannelList[j].bShow;
packet.Info[packet.cCount].nDependentMapID = (*ii).vOwnedChannelList[j].nDependentMapID;
#if defined(PRE_ADD_CHANNELNAME)
_wcscpy(packet.Info[packet.cCount].wszLanguageName, _countof(packet.Info[packet.cCount].wszLanguageName), (*ii).vOwnedChannelList[j].wszLanguageName, (int)wcslen((*ii).vOwnedChannelList[j].wszLanguageName));
#endif //#if defined(PRE_ADD_CHANNELNAME)
packet.cCount++;
}
SendAllLoginServer(MALO_VILLAGEINFO, 0, (char*)&packet, sizeof(MALOVillageInfo) - sizeof(packet.Info) + (sizeof(sChannelInfo) * packet.cCount));
}
}
void CDivisionManager::SendAllLoginServerVillageInfoDelete(int nVillageID)
{
MALOVillageInfoDelete packet;
memset(&packet, 0, sizeof(packet));
packet.nVillageID = nVillageID;
SendAllLoginServer(MALO_VILLAGEINFODEL, 0, (char*)&packet, sizeof(packet));
}
bool CDivisionManager::GetVillageServerInfo(std::vector <TVillageInfo> * vList)
{
if (m_VillageServerConList.empty()) return false;
ScopeLock<CSyncLock> Lock(m_Sync);
TVillageInfo Info;
std::vector <CDNVillageConnection*>::iterator ii;
for (ii = m_VillageServerConList.begin(); ii != m_VillageServerConList.end(); ii++)
{
if ((*ii)->GetConnectionCompleted() == false)
continue;
TVillageInfo * pInfo = (*ii)->GetVillageChannelInfo();
if (pInfo != NULL)
{
Info.nManagedID = pInfo->nManagedID;
Info.cVillageID = pInfo->cVillageID;
Info.nPort = pInfo->nPort;
_strcpy(Info.szIP, _countof(Info.szIP), pInfo->szIP, (int)strlen(pInfo->szIP));
Info.vOwnedChannelList = pInfo->vOwnedChannelList;
vList->push_back(Info);
}
}
return true;
}
bool CDivisionManager::GetVillageServerInfo(int nVillageID, TVillageInfo * pVillageInfo, const char * pszIP, short nPort)
{
if (!pVillageInfo) return false;
const TServerInfo * pInfo = g_pExtManager->GetServerInfoByWorldSetID(g_Config.nWorldSetID);
if (pInfo != NULL)
{
for (int i = 0; i < (int)pInfo->vOwnedVillageList.size(); i++)
{
if (pInfo->vOwnedVillageList[i].cVillageID == nVillageID)
{
//같은게 이미 접속되어 있는지 한번 확인하자
if (GetVillageConnectionByVillageID(nVillageID) == NULL)
{
pVillageInfo->cVillageID = pInfo->vOwnedVillageList[i].cVillageID;
#if defined (_FINAL_BUILD) //파이날빌드까지 묶는이유는 21번때문에 ㅎㅎㅎㅎㅎ
strcpy(pVillageInfo->szIP, pszIP);
pVillageInfo->nPort = nPort;
#else
strcpy(pVillageInfo->szIP, pInfo->vOwnedVillageList[i].szIP);
pVillageInfo->nPort = pInfo->vOwnedVillageList[i].nPort;
#endif
pVillageInfo->vOwnedChannelList = pInfo->vOwnedVillageList[i].vOwnedChannelList;
return true;
}
else
return false;
}
}
}
_DANGER_POINT();
return false;
}
const TChannelInfo* CDivisionManager::GetChannelInfo( const int nVillageID, const int nChannelID )
{
TVillageInfo * pInfo = NULL;
std::vector <TChannelInfo>::iterator ih;
CDNVillageConnection * pCon = GetVillageConnectionByVillageID(nVillageID);
if (pCon)
{
pInfo = pCon->GetVillageChannelInfo();
for (ih = pInfo->vOwnedChannelList.begin(); ih != pInfo->vOwnedChannelList.end(); ih++)
if ((*ih).nChannelID == nChannelID)
return &(*ih);
}
return NULL;
}
const TChannelInfo * CDivisionManager::GetChannelInfo(int nChannelID)
{
//sync버전입니다. 중복해서 싱크를 잡지 않도록 주의 요망!!!!
TVillageInfo * pInfo = NULL;
std::vector <CDNVillageConnection*>::iterator ii;
std::vector <TChannelInfo>::iterator ih;
ScopeLock<CSyncLock> Lock(m_Sync);
for (ii = m_VillageServerConList.begin(); ii != m_VillageServerConList.end(); ii++)
{
if ((*ii)->GetConnectionCompleted() == false) continue;
pInfo = (*ii)->GetVillageChannelInfo();
for (ih = pInfo->vOwnedChannelList.begin(); ih != pInfo->vOwnedChannelList.end(); ih++)
{
if ((*ih).nChannelID == nChannelID)
return &(*ih);
}
}
return NULL;
}
bool CDivisionManager::ChannelControl(int nChannelID, bool bVisibility, int nChannelPopulation)
{
ScopeLock<CSyncLock> Lock(m_Sync);
std::vector <CDNVillageConnection*>::iterator ii;
for (ii = m_VillageServerConList.begin(); ii != m_VillageServerConList.end(); ii++)
{
TVillageInfo * pInfo = (*ii)->GetVillageChannelInfo();
if (pInfo)
{
std::vector <TChannelInfo>::iterator ih;
for (ih = pInfo->vOwnedChannelList.begin(); ih != pInfo->vOwnedChannelList.end(); ih++)
{
if ((*ih).nChannelID == nChannelID)
{
if (nChannelPopulation > 0)
(*ih).nChannelMaxUser = nChannelPopulation;
(*ih).bVisibility = bVisibility;
return true;
}
}
}
}
return false;
}
bool CDivisionManager::PopulationControl(int nServerType, int nManagedID, bool bZeroPopulation)
{
ScopeLock<CSyncLock> Lock(m_Sync);
if (nServerType == MANAGED_TYPE_VILLAGE)
{
std::vector <CDNVillageConnection*>::iterator iv;
for (iv = m_VillageServerConList.begin(); iv != m_VillageServerConList.end(); iv++)
{
if ((*iv)->GetManagedID() > 0 && (*iv)->GetManagedID() == nManagedID)
{
TVillageInfo * pInfo = (*iv)->GetVillageChannelInfo();
if (pInfo)
{
std::vector <TChannelInfo>::iterator io;
for (io = pInfo->vOwnedChannelList.begin(); io != pInfo->vOwnedChannelList.end(); io++)
(*io).bVisibility = false;
return true;
}
break;
}
}
}
else if (nServerType == MANAGED_TYPE_GAME)
{
std::vector <CDNGameConnection*>::iterator ig;
for (ig = m_GameServerConList.begin(); ig != m_GameServerConList.end(); ig++)
{
if ((*ig)->GetManagedID() == nManagedID)
{
(*ig)->SetZeroPopulation(bZeroPopulation);
(*ig)->SendPopulationZero(bZeroPopulation);
return true;
}
}
}
return false;
}
void CDivisionManager::SetGameConAffinityType(int nManagedID, BYTE cAffinityType)
{
if (cAffinityType > 2) return; //타입이 넘어가믄 안데
if (m_GameServerConList.empty()) return;
ScopeLock<CSyncLock> Lock(m_Sync);
std::vector <CDNGameConnection*>::iterator ii;
for (ii = m_GameServerConList.begin(); ii != m_GameServerConList.end(); ii++)
{
if ((*ii)->GetManagedID() > 0 && (*ii)->GetManagedID() == nManagedID)
{
(*ii)->SetAffinityType(cAffinityType);
return;
}
}
}
void CDivisionManager::UpdateUserRestraint(UINT nAccountDBID)
{
ScopeLock<CSyncLock> Lock(m_Sync);
CDNUser * pUser = GetUserByAccountDBID(nAccountDBID);
if (pUser)
{
if (pUser->GetUserState() == STATE_CHECKVILLAGE || pUser->GetUserState() == STATE_VILLAGE)
{
CDNVillageConnection * pVillCon = GetVillageConnectionByVillageID(pUser->GetVillageID());
if (pVillCon)
pVillCon->SendUserRestraint(nAccountDBID);
}
else if (pUser->GetUserState() == STATE_CHECKGAME || pUser->GetUserState() == STATE_GAME)
{
CDNGameConnection * pGameCon = GetGameConnectionByGameID(pUser->GetGameID());
if (pGameCon)
pGameCon->SendUserRestraint(nAccountDBID);
}
}
}
bool CDivisionManager::GetGameInfoByID(int nGameID, int nGameServerID, char * pIP, USHORT * pPort, USHORT * pTcpPort)
{
if (m_GameServerConList.empty()) return false;
ScopeLock<CSyncLock> Lock(m_Sync);
std::vector <CDNGameConnection*>::iterator ii;
for (ii = m_GameServerConList.begin(); ii != m_GameServerConList.end(); ii++)
{
if ((*ii)->GetGameID() == nGameID && (*ii)->GetConnectionCompleted())
{
if ((*ii)->GetGameServerInfoByID(nGameServerID, pPort, pIP, pTcpPort) == true)
return true;
}
}
return false;
}
bool CDivisionManager::GetVillageInfo(int nMapIdx, int nOriginChannelId, int &nChannelId, BYTE &cVillageID, char * pIP, USHORT &pPort)
{
if (m_VillageServerConList.empty()) return false;
const TChannelInfo * pChInfo = GetChannelInfo(nOriginChannelId);
if (pChInfo == NULL) return false;
ScopeLock<CSyncLock> Lock(m_Sync);
TVillageInfo * pInfo = NULL;
std::vector <CDNVillageConnection*>::iterator ii;
std::vector <TChannelInfo>::iterator ih;
if (pChInfo->nMapIdx == nMapIdx)
{
//원래 있던 곳으로 돌아가는 것
for (ii = m_VillageServerConList.begin(); ii != m_VillageServerConList.end(); ii++)
{
if ((*ii)->GetConnectionCompleted() == false) continue;
pInfo = (*ii)->GetVillageChannelInfo();
for (ih = pInfo->vOwnedChannelList.begin(); ih != pInfo->vOwnedChannelList.end(); ih++)
{
if ((*ih).nMapIdx == nMapIdx && (*ih).nChannelID == nOriginChannelId && (*ih).nChannelMaxUser > (*ih).nCurrentUser && (*ih).bVisibility)
{
nChannelId = (*ih).nChannelID;
strcpy(pIP, (*ii)->GetVillageChannelInfo()->szIP);
pPort = (*ii)->GetVillageChannelInfo()->nPort;
cVillageID = (*ii)->GetVillageID();
return true;
}
}
}
//원래 채널이 가득차서 못들어 가는 경우이다. 충족요건을 찾는다.
for (ii = m_VillageServerConList.begin(); ii != m_VillageServerConList.end(); ii++)
{
if ((*ii)->GetConnectionCompleted() == false) continue;
pInfo = (*ii)->GetVillageChannelInfo();
for (ih = pInfo->vOwnedChannelList.begin(); ih != pInfo->vOwnedChannelList.end(); ih++)
{
if ((*ih).nMapIdx == nMapIdx && (*ih).nChannelMaxUser >= (*ih).nCurrentUser && (*ih).bVisibility)
{
if (pChInfo->nAttribute == GlobalEnum::CHANNEL_ATT_MERITBONUS)
{
if ((*ih).nAttribute == pChInfo->nAttribute && (*ih).nMeritBonusID == pChInfo->nMeritBonusID)
{
nChannelId = (*ih).nChannelID;
strcpy(pIP, (*ii)->GetVillageChannelInfo()->szIP);
pPort = (*ii)->GetVillageChannelInfo()->nPort;
cVillageID = (*ii)->GetVillageID();
return true;
}
}
else if ((*ih).nAttribute == pChInfo->nAttribute)
{
nChannelId = (*ih).nChannelID;
strcpy(pIP, (*ii)->GetVillageChannelInfo()->szIP);
pPort = (*ii)->GetVillageChannelInfo()->nPort;
cVillageID = (*ii)->GetVillageID();
return true;
}
}
}
}
}
else if (pChInfo->nAttribute == GlobalEnum::CHANNEL_ATT_MERITBONUS)
{
//전에 있던 채널이 메리트가 있던 곳이 었으면 메리트 조건으로 찾아본다
const TMeritInfo * pMerit = g_pExtManager->GetMeritInfo(pChInfo->nMeritBonusID);
if (pMerit)
{
int nLevel = (pMerit->nMaxLevel + pMerit->nMinLevel) / 2;
int nLastLevel = 1000;
CDNVillageConnection * pPickedCon = NULL;
TChannelInfo * pPickedChInfo = NULL;
for (ii = m_VillageServerConList.begin(); ii != m_VillageServerConList.end(); ii++)
{
if ((*ii)->GetConnectionCompleted() == false) continue;
pInfo = (*ii)->GetVillageChannelInfo();
for (ih = pInfo->vOwnedChannelList.begin(); ih != pInfo->vOwnedChannelList.end(); ih++)
{
if ((*ih).nAttribute == GlobalEnum::CHANNEL_ATT_MERITBONUS && (*ih).nMapIdx == nMapIdx && (*ih).nChannelMaxUser > (*ih).nCurrentUser && (*ih).bVisibility)
{
pMerit = g_pExtManager->GetMeritInfo((*ih).nMeritBonusID);
if (pMerit)
{
int nAvrLv = (pMerit->nMinLevel + pMerit->nMaxLevel) / 2;
int nGap = nAvrLv > nLevel ? nAvrLv - nLevel : nLevel - nAvrLv;
if (nLastLevel > nGap)
{
nLastLevel = nGap;
pPickedCon = (*ii);
pPickedChInfo = &(*ih);
}
}
}
}
}
if (pPickedCon && pPickedChInfo)
{
nChannelId = pPickedChInfo->nChannelID;
strcpy(pIP, pPickedCon->GetVillageChannelInfo()->szIP);
pPort = pPickedCon->GetVillageChannelInfo()->nPort;
cVillageID = pPickedCon->GetVillageID();
return true;
}
}
}
//이도 저도 못찾았습니다. 적당히 남는데 넣어 줍니다.
for (ii = m_VillageServerConList.begin(); ii != m_VillageServerConList.end(); ii++)
{
if ((*ii)->GetConnectionCompleted() == false) continue;
pInfo = (*ii)->GetVillageChannelInfo();
for (ih = pInfo->vOwnedChannelList.begin(); ih != pInfo->vOwnedChannelList.end(); ih++)
{
if ((*ih).nMapIdx == nMapIdx && (*ih).nChannelMaxUser > (*ih).nCurrentUser && (*ih).bVisibility)
{
nChannelId = (*ih).nChannelID;
strcpy(pIP, (*ii)->GetVillageChannelInfo()->szIP);
pPort = (*ii)->GetVillageChannelInfo()->nPort;
cVillageID = (*ii)->GetVillageID();
return true;
}
}
}
return false;
}
void CDivisionManager::CheckPvPLobbyChannel( CDNVillageConnection* pVillageCon )
{
for( UINT i=0 ; i<pVillageCon->GetVillageChannelInfo()->vOwnedChannelList.size() ; ++i )
{
if( pVillageCon->GetVillageChannelInfo()->vOwnedChannelList[i].nAttribute&GlobalEnum::CHANNEL_ATT_PVPLOBBY )
{
m_cPvPLobbyVillageID = pVillageCon->GetVillageID();
m_unPvPLobbyChannelID = pVillageCon->GetVillageChannelInfo()->vOwnedChannelList[i].nChannelID;
m_nPvPLobbyMapIndex = pVillageCon->GetVillageChannelInfo()->vOwnedChannelList[i].nMapIdx;
break;
}
}
}
void CDivisionManager::SendWaitProcess(int nServerID, MALOWaitUserProcess * pProcess)
{
if (pProcess == NULL)
{
_DANGER_POINT();
return;
}
ScopeLock<CSyncLock> Lock(m_Sync);
for (int nIndex = 0 ; LOGINCOUNTMAX > nIndex ; ++nIndex) {
CDNLoginConnection *pLoginCon = m_pLoginConnectionList[nIndex];
if (!pLoginCon) continue;
if (pLoginCon->GetServerID() == nServerID)
{
pLoginCon->SendWaitProcess(pProcess);
return;
}
}
}
//UserState
void CDivisionManager::AddUserState(const WCHAR * pName, INT64 biChracterDBID)
{
if (pName == NULL) return;
if (wcslen(pName) <= 0 || pName[0] == '\0') return;
ScopeLock<CSyncLock> Lock(m_Sync);
std::vector <CDNVillageConnection*>::iterator ii;
for (ii = m_VillageServerConList.begin(); ii != m_VillageServerConList.end(); ii++)
(*ii)->SendAddUserState(pName, biChracterDBID);
std::vector <CDNGameConnection*>::iterator ig;
for (ig = m_GameServerConList.begin(); ig != m_GameServerConList.end(); ig++)
(*ig)->SendAddUserState(pName, biChracterDBID);
}
void CDivisionManager::DelUserState(const WCHAR * pName, INT64 biChracterDBID)
{
if (pName == NULL) return;
if (wcslen(pName) <= 0) return;
ScopeLock<CSyncLock> Lock(m_Sync);
std::vector <CDNVillageConnection*>::iterator ii;
for (ii = m_VillageServerConList.begin(); ii != m_VillageServerConList.end(); ii++)
(*ii)->SendDelUserState(pName, biChracterDBID);
std::vector <CDNGameConnection*>::iterator ig;
for (ig = m_GameServerConList.begin(); ig != m_GameServerConList.end(); ig++)
(*ig)->SendDelUserState(pName, biChracterDBID);
}
void CDivisionManager::UpdateUserState(const WCHAR * pName, INT64 biChracterDBID, int nLocationState, int nCommunityState, int nChannelID, int nMapIdx, CDNGameConnection * pCon)
{
if (pName == NULL) return;
if (wcslen(pName) <= 0 || pName[0] == '\0') return;
//loginserver 제외된 master에 연결된 모든 서버에 전달
ScopeLock<CSyncLock> Lock(m_Sync);
std::vector <CDNVillageConnection*>::iterator ii;
for (ii = m_VillageServerConList.begin(); ii != m_VillageServerConList.end(); ii++)
(*ii)->SendUpdateUserState(pName, biChracterDBID, nLocationState, nCommunityState, nChannelID, nMapIdx);
std::vector <CDNGameConnection*>::iterator ig;
for (ig = m_GameServerConList.begin(); ig != m_GameServerConList.end(); ig++)
if (!(pCon && pCon == (*ig)))
(*ig)->SendUpdateUserState(pName, biChracterDBID, nLocationState, nCommunityState, nChannelID, nMapIdx);
}
UINT CDivisionManager::GetCurUserCount()
{
ScopeLock <CSyncLock> sync(m_Sync);
return (UINT)m_AccountDBIDList.size();
}
#if defined(PRE_MOD_SELECT_CHAR)
void CDivisionManager::_AddUserList(CDNUser *pUser)
{
m_AccountDBIDList[pUser->GetAccountDBID()] = pUser;
m_SessionIDList[pUser->GetSessionID()] = pUser;
m_CharacterDBIDList[pUser->GetCharacterDBID()] = pUser;
m_UserNameList[pUser->GetCharacterName()] = pUser;
}
int CDivisionManager::AddUser(LOMAAddUser *pPacket, int nServerID)
{
if (IsExistUser(pPacket->nAccountDBID))
return ERROR_GENERIC_DUPLICATEUSER;
if (pPacket->cAccountLevel <= 0) //일반유저가 아니라면 대기열과 상관없이 진입가능
{
if(!pPacket->bForce && (g_pWaitUserManager->GetWorldMaxUser() <= m_AccountDBIDList.size() || g_pWaitUserManager->GetWaitUserCount() > 0))
return ERROR_GENERIC_WORLDFULLY_CAPACITY;
}
CDNUser *pUser = new CDNUser;
if (!pUser){
_DANGER_POINT();
return ERROR_GENERIC_UNKNOWNERROR;
}
if (!pUser->InitUser(pPacket, nServerID))
{
SAFE_DELETE(pUser);
return ERROR_GENERIC_UNKNOWNERROR;
}
AddUserState(pPacket->wszCharacterName, pPacket->biCharacterDBID); //유저스테이트추가합니다 (모든서버 로긴제외)
UpdateUserState(pPacket->wszCharacterName, pPacket->biCharacterDBID, _LOCATION_MOVE, _COMMUNITY_NONE);
_AddUserList(pUser);
#if !defined( STRESS_TEST )
g_Log.Log(LogType::_NORMAL, pUser, L"[AddUser:%d] ADBID:%u, CDBID:%I64d, SID:%u (%s:%s) Adult:%d\r\n",
m_SessionIDList.size(), pPacket->nAccountDBID, pPacket->biCharacterDBID, pPacket->nSessionID, pPacket->wszAccountName, pPacket->wszCharacterName, pPacket->bAdult);
#endif
return ERROR_NONE;
}
bool CDivisionManager::AddUser(GAMAAddUserList *pPacket, int nGameID, bool bIsForceAdd/* = false*/)
{
if (IsExistUser(pPacket->nAccountDBID))
return false;
CDNUser *pUser = new CDNUser;
if (!pUser){
_DANGER_POINT();
return false;
}
if (!pUser->InitUser(pPacket))
return false;
AddUserState(pPacket->wszCharacterName, pPacket->biCharacterDBID); //유저스테이트추가합니다 (모든서버 로긴제외)
if (bIsForceAdd == false)
{
#if defined( STRESS_TEST )
_AddUserList(pUser);
return true;
#endif // #if defined( STRESS_TEST )
_ASSERT(0);
SAFE_DELETE(pUser);
return false;
}
else
{
if (nGameID > 0)
{
pUser->SetGameInfo(nGameID, pPacket->nThreadIdx, true);
pUser->m_VillageCheckPartyID = pPacket->PartyID;
UpdateUserState(pPacket->wszCharacterName, pPacket->biCharacterDBID, _LOCATION_GAME, _COMMUNITY_NONE, -1, pUser->m_nMapIndex);
}
}
_AddUserList(pUser);
#if !defined( STRESS_TEST )
g_Log.Log(LogType::_NORMAL, pUser, L"[AddUser:%d] ADBID:%u, CDBID:%I64d, SID:%u (%s:%s) Adult:%d\r\n",
m_SessionIDList.size(), pPacket->nAccountDBID, pPacket->biCharacterDBID, pPacket->nSessionID, pPacket->wszAccountName, pPacket->wszCharacterName, pPacket->bAdult);
#endif
return true;
}
bool CDivisionManager::AddUser(VIMAAddUserList *pPacket, int nVillageID, bool bIsForceAdd/* = false*/)
{
if (IsExistUser(pPacket->nAccountDBID))
return false;
CDNUser *pUser = new CDNUser;
if (!pUser){
_DANGER_POINT();
return false;
}
if (!pUser->InitUser(pPacket))
return false;
AddUserState(pPacket->wszCharacterName, pPacket->biCharacterDBID); //유저스테이트추가합니다 (모든서버 로긴제외)
if (bIsForceAdd == false)
{
#if defined( STRESS_TEST )
_AddUserList(pUser);
return true;
#endif // #if defined( STRESS_TEST )
_ASSERT(0);
SAFE_DELETE(pUser);
return false;
}
else
{
if (nVillageID > 0)
{
pUser->SetVillageInfo(nVillageID, pPacket->wChannelID, true);
const TChannelInfo * pChannelInfo = GetChannelInfo(pPacket->wChannelID);
if (pChannelInfo)
UpdateUserState(pPacket->wszCharacterName, pPacket->biCharacterDBID, _LOCATION_VILLAGE, _COMMUNITY_NONE, pChannelInfo->nChannelIdx, pChannelInfo->nMapIdx);
}
}
_AddUserList(pUser);
#if !defined( STRESS_TEST )
g_Log.Log(LogType::_NORMAL, pUser, L"[AddUser:%d] ADBID:%u, CDBID:%I64d, SID:%u (%s:%s) Adult:%d\r\n",
m_SessionIDList.size(), pPacket->nAccountDBID, pPacket->biCharacterDBID, pPacket->nSessionID, pPacket->wszAccountName, pPacket->wszCharacterName, pPacket->bAdult);
#endif
return true;
}
#else // #if defined(PRE_MOD_SELECT_CHAR)
int CDivisionManager::AddUser(int nServerID, UINT nAccountDBID, const BYTE * pMachineID, DWORD dwGRC, const char * pszIP, char cSelectedLanguage, BYTE cAccountLevel, bool bForce/*=false*/ )
{
if (IsExistUser(nAccountDBID)) return ERROR_GENERIC_DUPLICATEUSER;
if (cAccountLevel <= 0) //일반유저가 아니라면 대기열과 상관없이 진입가능
{
if( !bForce && (g_pWaitUserManager->GetWorldMaxUser() <= m_AccountDBIDList.size() || g_pWaitUserManager->GetWaitUserCount() > 0))
return ERROR_GENERIC_WORLDFULLY_CAPACITY;
}
CDNUser * pUser = new CDNUser;
if (!pUser){
_DANGER_POINT();
return ERROR_GENERIC_UNKNOWNERROR;
}
#ifdef PRE_MOD_RESTRICT_IDENTITY_IP
pUser->PreInit(nServerID, nAccountDBID, cAccountLevel, pszIP);
#else //#ifdef PRE_MOD_RESTRICT_IDENTITY_IP
pUser->PreInit(nServerID, nAccountDBID, cAccountLevel, NULL);
#endif //#ifdef PRE_MOD_RESTRICT_IDENTITY_IP
#ifdef PRE_ADD_MULTILANGUAGE
pUser->m_eSelectedLanguage = static_cast<MultiLanguage::SupportLanguage::eSupportLanguage>(cSelectedLanguage);
#endif //#ifdef PRE_ADD_MULTILANGUAGE
#if defined (_KR)
if (pMachineID) memcpy(pUser->m_szMID, pMachineID, sizeof(pUser->m_szMID));
pUser->m_dwGRC = dwGRC;
#endif
m_AccountDBIDList[nAccountDBID] = pUser;
g_Log.Log(LogType::_NORMAL, pUser, L"[AddUserList:%d] ADBID(%d)\n", (UINT)m_AccountDBIDList.size(), nAccountDBID);
return ERROR_NONE;
}
bool CDivisionManager::SetUserInfo(LOMAUserInfo *pUserInfo, int nGameID, int nGameThreadIdx, BYTE * pMachineID, DWORD &dwGRC)
{
CDNUser * pUser = GetUserByAccountDBID(pUserInfo->nAccountDBID);
if (pUser == NULL)
{
_DANGER_POINT();
return false;
}
pUser->Init(pUserInfo->nAccountDBID, pUserInfo->nSessionID, pUserInfo->biCharacterDBID, pUserInfo->wszCharacterName, pUserInfo->wszAccountName, pUserInfo->nChannelID, pUserInfo->bAdult, pUserInfo->szIP, pUserInfo->szVirtualIp);
pUser->SetPCGrade(pUserInfo->cPCBangGrade);
#if defined(_US)
pUser->m_nNexonUserNo = pUserInfo->nNexonUserNo;
#endif // _US
#if defined (_KR)
memcpy(pMachineID, pUser->m_szMID, sizeof(pUser->m_szMID));
dwGRC = pUser->m_dwGRC;
#endif
bool bMoveServerCheck = false;
if (pUserInfo->cVillageID > 0)
bMoveServerCheck = pUser->SetCheckVillageInfo(pUserInfo->cVillageID, pUserInfo->nChannelID);
else if (nGameID > 0)
bMoveServerCheck = pUser->SetCheckGameInfo(nGameID, nGameThreadIdx);
if (bMoveServerCheck == false)
return false;
AddUserState(pUserInfo->wszCharacterName, pUserInfo->biCharacterDBID); //유저스테이트추가합니다 (모든서버 로긴제외)
UpdateUserState(pUserInfo->wszCharacterName, pUserInfo->biCharacterDBID, _LOCATION_MOVE, _COMMUNITY_NONE);
m_SessionIDList[pUserInfo->nSessionID] = pUser;
m_UserNameList[pUser->GetCharacterName()] = pUser;
m_CharacterDBIDList[pUser->GetCharacterDBID()] = pUser;
#if defined(_CH) && defined(_FINAL_BUILD)
pUser->FCMIDOnline(); // 피로도 online
#endif // _CH
#if defined(_ID)
_strcpy(pUser->m_szMacAddress, _countof(pUser->m_szMacAddress), pUserInfo->szMacAddress, (int)strlen( pUserInfo->szMacAddress));
_strcpy(pUser->m_szKey, _countof(pUser->m_szKey), pUserInfo->szKey, (int)strlen( pUserInfo->szKey));
pUser->m_dwKreonCN = pUserInfo->dwKreonCN;
#endif //#if defined(_ID)
#if defined(PRE_ADD_DWC)
pUser->SetCharacterAccountLevel(pUserInfo->cCharacterAccountLevel);
#endif
#if !defined( STRESS_TEST )
g_Log.Log(LogType::_NORMAL, g_Config.nWorldSetID, pUserInfo->nAccountDBID, pUserInfo->biCharacterDBID, pUserInfo->nSessionID,
L"[AddUser:%d] ADBID:%u, CDBID:%I64d, SID:%u (%s:%s) Adult:%d\r\n", m_SessionIDList.size(), pUserInfo->nAccountDBID, pUserInfo->biCharacterDBID, pUserInfo->nSessionID, pUserInfo->wszAccountName, pUserInfo->wszCharacterName, pUserInfo->bAdult);
#endif
return true;
}
bool CDivisionManager::AddUser(int nVillageID, int nChannelID, int nGameID, int nGameThreadIdx, UINT nAccountDBID, UINT nSessionID, INT64 biCharacterDBID, WCHAR *pwszCharacterName, WCHAR *pwszAccountName,
#if defined(PRE_ADD_DWC)
BYTE cAccountLevel,
#endif
bool bAdult, char *pszIp, char *pszVirtualIp, TPARTYID PartyID, const BYTE * pMachineID, DWORD dwGRC, BYTE cPcBangGrade, char cSelectedLanguage, bool bIsForceAdd)
{
if (IsExistUser(nAccountDBID)) return false;
CDNUser * pUser = new CDNUser;
if (!pUser){
_DANGER_POINT();
return false;
}
pUser->Init(nAccountDBID, nSessionID, biCharacterDBID, pwszCharacterName, pwszAccountName, nChannelID, bAdult, pszIp, pszVirtualIp);
#if defined (_KR)
if (pMachineID) memcpy(pUser->m_szMID, pMachineID, sizeof(pUser->m_szMID));
pUser->m_dwGRC = dwGRC;
#endif
pUser->SetPCGrade(cPcBangGrade);
#ifdef PRE_ADD_MULTILANGUAGE
pUser->m_eSelectedLanguage = static_cast<MultiLanguage::SupportLanguage::eSupportLanguage>(cSelectedLanguage);
#endif //#ifdef PRE_ADD_MULTILANGUAGE
AddUserState(pwszCharacterName, biCharacterDBID); //유저스테이트추가합니다 (모든서버 로긴제외)
if (bIsForceAdd == false)
{
#if defined( STRESS_TEST )
m_AccountDBIDList[nAccountDBID] = pUser;
m_SessionIDList[nSessionID] = pUser;
m_CharacterDBIDList[biCharacterDBID] = pUser;
m_UserNameList[pUser->GetCharacterName()] = pUser;
return true;
#endif // #if defined( STRESS_TEST )
_ASSERT(0);
SAFE_DELETE( pUser );
return false;
}
else
{
if (nVillageID > 0)
{
pUser->SetVillageInfo(nVillageID, nChannelID, true);
const TChannelInfo * pChannelInfo = GetChannelInfo(nChannelID);
if (pChannelInfo)
UpdateUserState(pwszCharacterName, biCharacterDBID, _LOCATION_VILLAGE, _COMMUNITY_NONE, pChannelInfo->nChannelIdx, pChannelInfo->nMapIdx);
}
else if (nGameID > 0)
{
pUser->SetGameInfo(nGameID, nGameThreadIdx, true);
pUser->m_VillageCheckPartyID = PartyID;
UpdateUserState(pwszCharacterName, biCharacterDBID, _LOCATION_GAME, _COMMUNITY_NONE, -1, pUser->m_nMapIndex);
}
}
m_AccountDBIDList[nAccountDBID] = pUser;
m_SessionIDList[nSessionID] = pUser;
m_CharacterDBIDList[biCharacterDBID] = pUser;
m_UserNameList[pUser->GetCharacterName()] = pUser;
#if defined(_CH) && defined(_FINAL_BUILD)
pUser->FCMIDOnline(); // 피로도 online
#endif // _CH
#if !defined( STRESS_TEST )
g_Log.Log(LogType::_NORMAL, g_Config.nWorldSetID, nAccountDBID, biCharacterDBID, nSessionID, L"[AddUser:%d] ADBID:%u, CDBID:%I64d, SID:%u (%s:%s) Adult:%d\r\n", m_SessionIDList.size(), nAccountDBID, biCharacterDBID, nSessionID, pwszAccountName, pwszCharacterName, bAdult);
#endif
return true;
}
#endif // #if defined(PRE_MOD_SELECT_CHAR)
#if defined (_JP) && defined (WIN64)
bool CDivisionManager::SetNHNNetCafeInfo(UINT nAccountDBID, bool bNetCafe, const char * pszNetCafeCode, const char * pszProdectCode)
{
CDNUser * pUser = GetUserByAccountDBID(nAccountDBID);
if (pUser)
{
pUser->SetPCBang(bNetCafe);
memcpy_s(pUser->m_szNHNNetCafeCode, sizeof(pUser->m_szNHNNetCafeCode), pszNetCafeCode, NHNNETCAFECODEMAX);
memcpy_s(pUser->m_szNHNProdectCode, sizeof(pUser->m_szNHNProdectCode), pszProdectCode, NHNNETCAFECODEMAX);
return true;
}
return false;
}
#endif
bool CDivisionManager::DelUser(UINT nAccountDBID, bool bIsReconnectLogin, UINT nSessionID)
{
#if defined( STRESS_TEST )
return true;
#endif
std::map <UINT, CDNUser*>::iterator ii = m_AccountDBIDList.find(nAccountDBID);
if (ii != m_AccountDBIDList.end())
{
CDNUser * pUser = (*ii).second;
if( nSessionID > 0 && nSessionID != pUser->GetSessionID()) // SessionID 체크
{
g_Log.Log(LogType::_NORMAL, pUser, L"DelUser SessionID not Match!! SessionID:%u, DelSessionID:%u\r\n", pUser->GetSessionID(), nSessionID );
return false;
}
// PvP 처리
LeavePvPRoom( nAccountDBID, false );
LeaveLadderSystem( nAccountDBID );
#if defined(_KR) && defined(_FINAL_BUILD) // pc bang
g_pNexonAuth->SendLogout(pUser);
#elif defined(_US) && defined(_FINAL_BUILD)
g_pNexonPI->RequestLogoff(pUser->m_nNexonUserNo, pUser->GetIp());
#elif defined(_CH) && defined(_FINAL_BUILD)
pUser->FCMIDOffline(); // 피로도 offline
#elif defined (_JP) && defined(_FINAL_BUILD) && defined (WIN64)
g_pNHNNetCafe->NetCafe_UserLogOut(pUser->GetAccountNameA());
#elif defined (_TW) && defined(_FINAL_BUILD)
if( !bIsReconnectLogin && strlen(pUser->GetAccountNameA()) != 0 ) // 캐릭터 선택창으로 돌아가는 경우는 LogOut 날리지 않기.
{
ScopeLock<CSyncLock> Lock(pUser->m_SendLogOutLock);
if( !pUser->m_bSendLogOut )
{
g_pGamaniaAuthLogOut->SendLogout(pUser->GetAccountNameA(), pUser->GetIp());
pUser->m_bSendLogOut = true;
g_Log.Log(LogType::_FILELOG, L"[GASH] LogOut DelUser %s, %d, State:%d\r\n", pUser->GetAccountName(), pUser->GetSessionID(), pUser->GetUserState() );
}
}
#elif defined(_TH) && defined(_FINAL_BUILD)
if( pUser )
g_pAsiaSoftPCCafe->SendCheckIPBonus(pUser->GetAccountNameA(), pUser->GetIp(), 2, pUser->GetAccountDBID());
#endif // _KR _CH _JP _TW
#ifdef PRE_ADD_STEAM_USERCOUNT
if (pUser && pUser->m_bSteamUser)
DecreaseSteamUser();
#endif //#ifdef PRE_ADD_STEAM_USERCOUNT
eUserState State = pUser->GetUserState();
if (State != STATE_NONE)
{
DelUserState(pUser->GetCharacterName(), pUser->GetCharacterDBID());
}
EraseUserListExceptAccountDBList(pUser);
m_AccountDBIDList.erase(ii);
if (bIsReconnectLogin == false)
{
g_pWaitUserManager->UpdateCurCount((UINT)m_AccountDBIDList.size());
}
return true;
}
#if !defined( STRESS_TEST )
_DANGER_POINT();
#endif
return false;
}
bool CDivisionManager::IsExistUser(UINT nAccountDBID)
{
if (m_AccountDBIDList.empty()) return false;
std::map <UINT, CDNUser*>::iterator ii = m_AccountDBIDList.find(nAccountDBID);
if (ii != m_AccountDBIDList.end())
{
//test
ULONG CreateTick = (*ii).second->m_nCreateTick;
ULONG nCUrTick = timeGetTime();
return true;
}
return false;
}
CDNUser * CDivisionManager::GetUserByAccountDBID(UINT nAccountDBID)
{
if (m_AccountDBIDList.empty()) return NULL;
std::map <UINT, CDNUser*>::iterator ii = m_AccountDBIDList.find(nAccountDBID);
if (ii != m_AccountDBIDList.end())
return (*ii).second;
//g_Log.Log(LogType::_ERROR, g_Config.nWorldSetID, nAccountDBID, 0, 0, L"GetUserByAccountDBID Failed ADBID[%d]\n", nAccountDBID);
return NULL;
}
CDNUser * CDivisionManager::GetUserBySessionID(UINT nSessionID)
{
if (m_SessionIDList.empty()) return NULL;
std::map <UINT, CDNUser*>::iterator ii = m_SessionIDList.find(nSessionID);
if (ii != m_SessionIDList.end())
return (*ii).second;
return NULL;
}
CDNUser * CDivisionManager::GetUserByCharacterDBID( INT64 biCharacterDBID )
{
if (m_CharacterDBIDList.empty()) return NULL;
std::map <INT64, CDNUser*>::iterator ii = m_CharacterDBIDList.find(biCharacterDBID);
if (ii != m_CharacterDBIDList.end())
return (*ii).second;
return NULL;
}
CDNUser * CDivisionManager::GetUserByName(const WCHAR * pName)
{
if (m_UserNameList.empty()) return NULL;
std::map <std::wstring, CDNUser*>::iterator ii = m_UserNameList.find(pName);
if (ii != m_UserNameList.end())
return (*ii).second;
return NULL;
}
CDNUser *CDivisionManager::GetUserByAccountName(const WCHAR *pAccountName)
{
if (m_SessionIDList.empty()) return NULL;
std::map <UINT, CDNUser*>::iterator iter;
for (iter = m_SessionIDList.begin(); iter != m_SessionIDList.end(); ++iter){
if (__wcsicmp_l(iter->second->GetAccountName(), pAccountName) == 0)
return iter->second;
}
return NULL;
}
#if defined(_KR)
CDNUser *CDivisionManager::GetUserByNexonSessionNo(INT64 biSessionNo)
{
if (m_SessionIDList.empty()) return NULL;
std::map <UINT, CDNUser*>::iterator iter;
for (iter = m_SessionIDList.begin(); iter != m_SessionIDList.end(); ++iter){
if (iter->second->m_biNexonSessionNo == biSessionNo)
return iter->second;
}
return NULL;
}
#endif // #if defined(_KR)
void CDivisionManager::DetachUserloginID(int nServerID)
{
if (m_AccountDBIDList.empty()) return;
UINT nSessionID = 0;
WCHAR wszCharName[NAMELENMAX] = { 0, };
map <UINT, CDNUser*>::iterator iter;
CDNUser *pUser = NULL;
for (iter = m_AccountDBIDList.begin(); iter != m_AccountDBIDList.end(); ){
if ((iter->second->GetUserState() == STATE_LOGIN || iter->second->GetUserState() == STATE_NONE) && (iter->second->GetLoginServerID() == nServerID)){
pUser = iter->second;
#if defined(_KR) && defined(_FINAL_BUILD) // pc bang
g_pNexonAuth->SendLogout(pUser);
#elif defined(_CH) && defined(_FINAL_BUILD)
pUser->FCMIDOffline(); // 피로도 offline
#elif defined (_JP) && defined(_FINAL_BUILD) && defined (WIN64)
g_pNHNNetCafe->NetCafe_UserLogOut(pUser->GetAccountNameA());
#elif defined(_TH) && defined(_FINAL_BUILD)
if( pUser )
g_pAsiaSoftPCCafe->SendCheckIPBonus(pUser->GetAccountNameA(), pUser->GetIp(), 2, pUser->GetAccountDBID());
#endif // _KR _CH _JP
#ifdef PRE_ADD_STEAM_USERCOUNT
if (pUser && pUser->m_bSteamUser)
DecreaseSteamUser();
#endif //#ifdef PRE_ADD_STEAM_USERCOUNT
DelUserState(pUser->GetCharacterName(), pUser->GetCharacterDBID());
EraseUserListExceptAccountDBList(pUser);
m_AccountDBIDList.erase(iter++);
}
else
++iter;
}
}
void CDivisionManager::DetachUserByVillageID(BYTE cVillageID)
{
if (m_AccountDBIDList.empty()) return;
UINT nSessionID = 0;
WCHAR wszCharName[NAMELENMAX] = { 0, };
map <UINT, CDNUser*>::iterator iter;
CDNUser *pUser = NULL;
for (iter = m_AccountDBIDList.begin(); iter != m_AccountDBIDList.end(); ){
if ((iter->second->GetUserState() == STATE_VILLAGE || iter->second->GetUserState() == STATE_CHECKVILLAGE) && (iter->second->GetVillageID() == cVillageID)){
pUser = iter->second;
#if defined(_KR) && defined(_FINAL_BUILD) // pc bang
g_pNexonAuth->SendLogout(pUser);
#elif defined(_CH) && defined(_FINAL_BUILD)
pUser->FCMIDOffline(); // 피로도 offline
#elif defined (_JP) && defined(_FINAL_BUILD) && defined (WIN64)
g_pNHNNetCafe->NetCafe_UserLogOut(pUser->GetAccountNameA());
#elif defined (_TW) && defined(_FINAL_BUILD)
if( pUser->GetAccountDBID() != 0 && strlen(pUser->GetAccountNameA()) !=0 )
{
ScopeLock<CSyncLock> Lock(pUser->m_SendLogOutLock);
if( !pUser->m_bSendLogOut )
{
g_pGamaniaAuthLogOut->SendLogout(pUser->GetAccountNameA(), pUser->GetIp());
pUser->m_bSendLogOut = true;
g_Log.Log(LogType::_FILELOG, L"[GASH] LogOut DetachUserByVillageID %s, %d\r\n", pUser->GetAccountName(), pUser->GetSessionID() );
}
}
#elif defined(_TH) && defined(_FINAL_BUILD)
if( pUser )
g_pAsiaSoftPCCafe->SendCheckIPBonus(pUser->GetAccountNameA(), pUser->GetIp(), 2, pUser->GetAccountDBID());
#endif // _KR _CH _JP _TW
#ifdef PRE_ADD_STEAM_USERCOUNT
if (pUser && pUser->m_bSteamUser)
DecreaseSteamUser();
#endif //#ifdef PRE_ADD_STEAM_USERCOUNT
DelUserState(pUser->GetCharacterName(), pUser->GetCharacterDBID());
EraseUserListExceptAccountDBList(pUser);
m_AccountDBIDList.erase(iter++);
}
else
++iter;
}
}
void CDivisionManager::DetachUserByGameID(USHORT wGameID)
{
if (m_AccountDBIDList.empty()) return;
UINT nSessionID = 0;
WCHAR wszCharName[NAMELENMAX] = { 0, };
map <UINT, CDNUser*>::iterator iter;
CDNUser *pUser = NULL;
for (iter = m_AccountDBIDList.begin(); iter != m_AccountDBIDList.end(); ){
if ((iter->second->GetUserState() == STATE_GAME || iter->second->GetUserState() == STATE_CHECKGAME) && (iter->second->GetGameID() == wGameID)){
pUser = iter->second;
#if defined(_KR) && defined(_FINAL_BUILD) // pc bang
g_pNexonAuth->SendLogout(pUser);
#elif defined(_CH) && defined(_FINAL_BUILD)
pUser->FCMIDOffline(); // 피로도 offline
#elif defined (_JP) && defined(_FINAL_BUILD) && defined (WIN64)
g_pNHNNetCafe->NetCafe_UserLogOut(pUser->GetAccountNameA());
#elif defined (_TW) && defined(_FINAL_BUILD)
if( pUser->GetAccountDBID() != 0 && strlen(pUser->GetAccountNameA()) !=0 )
{
ScopeLock<CSyncLock> Lock(pUser->m_SendLogOutLock);
if( !pUser->m_bSendLogOut )
{
g_pGamaniaAuthLogOut->SendLogout(pUser->GetAccountNameA(), pUser->GetIp());
pUser->m_bSendLogOut = true;
g_Log.Log(LogType::_FILELOG, L"[GASH] LogOut DetachUserByGameID %s, %d\r\n", pUser->GetAccountName(), pUser->GetSessionID() );
}
}
#elif defined(_TH) && defined(_FINAL_BUILD)
if( pUser )
g_pAsiaSoftPCCafe->SendCheckIPBonus(pUser->GetAccountNameA(), pUser->GetIp(), 2, pUser->GetAccountDBID());
#endif // _KR _CH _JP _TW
#ifdef PRE_ADD_STEAM_USERCOUNT
if (pUser && pUser->m_bSteamUser)
DecreaseSteamUser();
#endif //#ifdef PRE_ADD_STEAM_USERCOUNT
DelUserState(pUser->GetCharacterName(), pUser->GetCharacterDBID());
EraseUserListExceptAccountDBList(pUser);
m_AccountDBIDList.erase(iter++);
}
else
++iter;
}
}
void CDivisionManager::EraseUserListExceptAccountDBList(CDNUser *pUser)
{
LeavePvPRoom( pUser->GetAccountDBID(), false );
map<UINT, CDNUser*>::iterator ii = m_SessionIDList.find(pUser->GetSessionID());
if (ii != m_SessionIDList.end())
m_SessionIDList.erase(ii);
std::map <std::wstring, CDNUser*>::iterator iter = m_UserNameList.find(pUser->GetCharacterName());
if (iter != m_UserNameList.end())
m_UserNameList.erase(iter);
map<INT64, CDNUser*>::iterator itor = m_CharacterDBIDList.find( pUser->GetCharacterDBID() );
if( itor != m_CharacterDBIDList.end() )
m_CharacterDBIDList.erase( itor );
g_Log.Log(LogType::_NORMAL, pUser, L"[EraseUserList:%d] A(%d, %s) C(%I64d, %s)\r\n", m_SessionIDList.size(), pUser->GetAccountDBID(), pUser->GetAccountName(), pUser->GetCharacterDBID(), pUser->GetCharacterName());
SAFE_DELETE(pUser);
}
void CDivisionManager::ReplaceCharacterName(CDNUser* pUser, WCHAR* wszCharacterName)
{
std::map <std::wstring, CDNUser*>::iterator iter = m_UserNameList.find(pUser->GetCharacterName());
if (iter != m_UserNameList.end())
{
m_UserNameList.erase(iter);
pUser->SetCharacterName (wszCharacterName);
m_UserNameList[pUser->GetCharacterName()] = pUser;
}
}
#ifdef PRE_MOD_RESTRICT_IDENTITY_IP
bool CDivisionManager::DetachUserByIP(const char * pszIP)
{
if (pszIP == NULL)
return false;
g_Log.Log(LogType::_RESTRICTIP, L"DetachUserByIP Detect IP[%S]\n", pszIP);
std::vector <UINT> vList;
std::map <UINT, CDNUser*>::iterator iu;
for (iu = m_AccountDBIDList.begin(); iu != m_AccountDBIDList.end(); iu++)
{
if (!stricmp((*iu).second->GetIp(), pszIP))
vList.push_back((*iu).second->GetAccountDBID());
}
for (std::vector <UINT>::iterator vlistItor = vList.begin(); vlistItor != vList.end(); vlistItor++)
{
SendDetachUser((*vlistItor));
}
return true;
}
#endif //#ifdef PRE_MOD_RESTRICT_IDENTITY_IP
#ifdef PRE_ADD_STEAM_USERCOUNT
void CDivisionManager::IncreaseSteamUser()
{
m_nSteamUserCount++;
}
void CDivisionManager::DecreaseSteamUser()
{
m_nSteamUserCount--;
}
#endif //#ifdef PRE_ADD_STEAM_USERCOUNT
bool CDivisionManager::VillageCheckUser(CDNVillageConnection * pCon, UINT nSessionID)
{
CDNUser * pUser = GetUserBySessionID(nSessionID);
if (pUser != NULL)
{
if (pCon->GetVillageID() != pUser->GetVillageID() || pUser->GetUserState() != STATE_CHECKVILLAGE || pUser->GetChannelID() <= 0)
{
g_Log.Log(LogType::_NORMAL, L"VillageCheckUser StateFail [%d] VID[%d : %d] UserState[%d] UserChannelID[%d]\n", nSessionID, pCon->GetVillageID(), pUser->GetVillageID(), pUser->GetUserState(), pUser->GetChannelID());
}
pCon->SendCheckUser(pUser, 0, ERROR_NONE);
return true;
}
pCon->SendCheckUser(NULL, nSessionID, ERROR_GENERIC_USER_NOT_FOUND);
g_Log.Log(LogType::_NORMAL, L"VillageCheckUser Fail UserNotFound[%d]\n", nSessionID);
return false;
}
void CDivisionManager::CheckZombie(ULONG nCurTick)
{
if (m_AccountDBIDList.empty()) return;
std::map <UINT, CDNUser*>::iterator ii;
for (ii = m_AccountDBIDList.begin(); ii != m_AccountDBIDList.end();)
{
CDNUser * pUser = (*ii).second;
if (pUser->GetCheckStateTick() > 0 && \
(pUser->GetUserState() == STATE_CHECKGAME || pUser->GetUserState() == STATE_CHECKVILLAGE || \
pUser->GetUserState() == STATE_NONE || pUser->GetUserState() == STATE_CHECKRECONNECTLOGIN) &&
((pUser->GetCheckStateTick() + CHECK_ZOMBIE_DISCONNECT_TICK) < nCurTick))
{
//어디에 남아있을 지 모르므로 일단 전부 날려준다.
CDNVillageConnection * pVilCon = GetVillageConnectionByVillageID(pUser->GetVillageID());
if (pVilCon){
pVilCon->SendDetachUser(pUser->GetAccountDBID());
g_Log.Log(LogType::_NORMAL, pUser, L"[ADBID:%u CDBID:%I64d SID:%u] SendDetachUser(CheckZombie):%d (VillageID:%d)\r\n", pUser->GetAccountDBID(), pUser->GetCharacterDBID(), pUser->GetSessionID(), pUser->GetUserState(), pUser->GetVillageID());
}
CDNGameConnection * pGameCon = GetGameConnectionByGameID(pUser->GetGameID());
if (pGameCon){
pGameCon->SendDetachUser(pUser->GetAccountDBID());
g_Log.Log(LogType::_NORMAL, pUser, L"[ADBID:%u CDBID:%I64d SID:%u] SendDetachUser(CheckZombie):%d (GameID:%d)\r\n", pUser->GetAccountDBID(), pUser->GetCharacterDBID(), pUser->GetSessionID(), pUser->GetUserState(), pUser->GetGameID());
}
#if defined(_KR) && defined(_FINAL_BUILD) // pc bang
g_pNexonAuth->SendLogout(pUser);
#elif defined(_CH) && defined(_FINAL_BUILD)
pUser->FCMIDOffline(); // 피로도 offline
#elif defined (_JP) && defined(_FINAL_BUILD) && defined (WIN64)
g_pNHNNetCafe->NetCafe_UserLogOut(pUser->GetAccountNameA());
#elif defined (_TW) && defined(_FINAL_BUILD)
if( pUser->GetAccountDBID() != 0 && strlen(pUser->GetAccountNameA()) !=0 )
{
ScopeLock<CSyncLock> Lock(pUser->m_SendLogOutLock);
if( !pUser->m_bSendLogOut )
{
g_pGamaniaAuthLogOut->SendLogout(pUser->GetAccountNameA(), pUser->GetIp());
pUser->m_bSendLogOut = true;
g_Log.Log(LogType::_FILELOG, L"[GASH] LogOut CheckZombie %s, %d\r\n", pUser->GetAccountName(), pUser->GetSessionID() );
}
}
#elif defined(_TH) && defined(_FINAL_BUILD)
if( pUser )
g_pAsiaSoftPCCafe->SendCheckIPBonus(pUser->GetAccountNameA(), pUser->GetIp(), 2, pUser->GetAccountDBID());
#endif // _KR _CH _JP _TW
#ifdef PRE_ADD_STEAM_USERCOUNT
if (pUser && pUser->m_bSteamUser)
DecreaseSteamUser();
#endif //#ifdef PRE_ADD_STEAM_USERCOUNT
LeavePvPRoom( pUser->GetAccountDBID(), false );
DelUserState(pUser->GetCharacterName(), pUser->GetCharacterDBID());
EraseUserListExceptAccountDBList(pUser);
ii = m_AccountDBIDList.erase(ii);
}
else
ii++;
}
}
int CDivisionManager::_CheckVillageToPvPVillage( CDNVillageConnection* pVillageCon, CDNUser* pUser, char cReqType, const BYTE cNextVillageID, const int nNextVillageChannelID )
{
const TChannelInfo* pChannelInfo = GetChannelInfo( cNextVillageID, nNextVillageChannelID );
if( !pChannelInfo )
return ERROR_GENERIC_VILLAGECON_NOT_FOUND;
// 이동할 맵이 PvPVillage 인지 검사
#if defined(PRE_ADD_DWC)
if( pChannelInfo->nAttribute&GlobalEnum::CHANNEL_ATT_PVP || pChannelInfo->nAttribute&GlobalEnum::CHANNEL_ATT_DWC )
#else
if( pChannelInfo->nAttribute&GlobalEnum::CHANNEL_ATT_PVP )
#endif
{
// 파티상태라면 에러
if (cReqType == REQINFO_TYPE_PARTY)
return ERROR_PVP_CANTMOVECHANNEL_PARTYSTATE;
}
return ERROR_NONE;
}
void CDivisionManager::_CheckPvPVillageToPvPLobby( VIMAVillageToVillage* pPacket, CDNUser* pUser, const BYTE cNextVillageID, const int nNextChannelIndex )
{
// 현재채널이 PvP마을인지 검사
const TChannelInfo* pChannelInfo = GetChannelInfo( pUser->GetVillageID(), pUser->GetChannelID() );
if( !pChannelInfo )
return;
#if defined(PRE_ADD_DWC)
if( !(pChannelInfo->nAttribute&GlobalEnum::CHANNEL_ATT_PVP) && !(pChannelInfo->nAttribute&GlobalEnum::CHANNEL_ATT_DWC) )
#else
if( !(pChannelInfo->nAttribute&GlobalEnum::CHANNEL_ATT_PVP) )
#endif
return;
// 타겟채널이 PvP로비인지 검사
const TChannelInfo* pNextChannelInfo = GetChannelInfo( cNextVillageID, nNextChannelIndex );
if( !pNextChannelInfo )
return;
if( !(pNextChannelInfo->nAttribute&GlobalEnum::CHANNEL_ATT_PVPLOBBY) )
return;
// 현재 PvP마을 정보 기억
pUser->SetPvPVillageInfo();
}
void CDivisionManager::_CheckVillageToPvPLobby( VIMAVillageToVillage* pPacket, CDNUser* pUser, const BYTE cNextVillageID, const int nNextChannelIndex )
{
// 타겟채널이 PvP로비인지 검사
const TChannelInfo* pNextChannelInfo = GetChannelInfo( cNextVillageID, nNextChannelIndex );
if( !pNextChannelInfo )
return;
if( !(pNextChannelInfo->nAttribute&GlobalEnum::CHANNEL_ATT_PVPLOBBY) )
return;
// 현재 PvP마을 정보 기억
pUser->SetPvPVillageInfo();
}
void CDivisionManager::MovePvPLobbyToVillage( CDNVillageConnection* pCon, VIMAPVP_MOVELOBBYTOVILLAGE* pPacket )
{
if( !pCon )
{
_DANGER_POINT();
return;
}
CDNUser* pUser = GetUserByAccountDBID( pPacket->uiAccountDBID );
if( !pUser )
{
_DANGER_POINT();
return;
}
// 현재 유저가 로비상태에 있는지 검사
if( !pUser->bIsPvPLobby() )
{
_DANGER_POINT();
return;
}
// PvP방에 있는지 검사
if( pUser->GetPvPIndex() > 0 )
{
_DANGER_POINT();
return;
}
const TChannelInfo* pChannelInfo = GetChannelInfo( pUser->GetPvPVillageID(), pUser->GetPvPVillageChannelID() );
if( !pChannelInfo )
{
_DANGER_POINT();
return;
}
char szIP[IPLENMAX] = { 0, };
USHORT nPort = 0;
int nNextChannelIdx = 0;
BYTE cNextVillageID = 0;
if( GetVillageInfo( pChannelInfo->nMapIdx, pChannelInfo->nChannelID, nNextChannelIdx, cNextVillageID, szIP, nPort) == false )
{
_DANGER_POINT();
return;
}
int nNextGateIdx = PvPCommon::Common::PvPVillageStartPositionGateNo;
int nNextMapIdx = pChannelInfo->nMapIdx;
if( VillageToVillage(pCon, pUser->GetAccountDBID(), cNextVillageID, nNextChannelIdx, 0) )
pCon->SendTargetVillageInfo(pUser->GetAccountDBID(), cNextVillageID, nNextChannelIdx, nNextMapIdx, nNextGateIdx, szIP, nPort, ERROR_NONE);
else
pCon->SendTargetVillageInfo(pUser->GetAccountDBID(), cNextVillageID, nNextChannelIdx, nNextMapIdx, nNextGateIdx, szIP, nPort, ERROR_GENERIC_VILLAGECON_NOT_FOUND);
}
void CDivisionManager::MoveVillageToVillage(CDNVillageConnection * pCon, VIMAVillageToVillage * pPacket)
{
char szIP[IPLENMAX] = { 0, };
unsigned short nPort = 0;
BYTE cNextVillageID = 0;
int nNextChannelID = 0;
int nNextGateIdx = -1;
int nNextMapIdx = -1;
if (pCon == NULL)
{
_DANGER_POINT();
return;
}
UINT nAccountDBID = 0;
switch (pPacket->cReqType)
{
case REQINFO_TYPE_SINGLE:
case REQINFO_TYPE_SINGLE_SAMEDEST:
case REQINFO_TYPE_PVP:
case REQINFO_TYPE_PVP_BREAKINTO:
{
#if defined( PRE_PARTY_DB )
nAccountDBID = static_cast<UINT>(pPacket->biID);
#else
nAccountDBID = pPacket->nID;
#endif // #if defined( PRE_PARTY_DB )
break;
}
case REQINFO_TYPE_PARTY: nAccountDBID = pPacket->PartyData.nLeaderAccountDBID; break;
default: _ASSERT(0);
}
CDNUser * pUser = GetUserByAccountDBID(nAccountDBID);
if (pUser == NULL)
{
_DANGER_POINT();
return;
}
int nOriginChannel = pUser->GetChannelID();
if (pPacket->nMoveChannel > 0) //채널이동일경우
{
if (GetVillageInfo(pPacket->nMapIndex, pPacket->nMoveChannel, nNextChannelID, cNextVillageID, szIP, nPort) == false)
{
_DANGER_POINT();
return;
}
int nCheckRet = _CheckVillageToPvPVillage( pCon, pUser, pPacket->cReqType, cNextVillageID, nNextChannelID );
if( nCheckRet != ERROR_NONE )
{
pCon->SendTargetVillageInfo( pUser->GetAccountDBID(), cNextVillageID, nNextChannelID, nNextMapIdx, nNextGateIdx, szIP, nPort, nCheckRet );
return;
}
nNextGateIdx = pPacket->nEnteredGateIndex;
nNextMapIdx = pPacket->nMapIndex;
_CheckVillageToPvPLobby(pPacket, pUser, cNextVillageID, nNextChannelID);
}
else if (pPacket->nEnteredGateIndex > 0) // 마을에서 마을로 이동할때
{
nNextGateIdx = g_pExtManager->GetGateNoByGateNo( pPacket->nMapIndex, pPacket->nEnteredGateIndex );
nNextMapIdx = g_pExtManager->GetMapIndexByGateNo( pPacket->nMapIndex, pPacket->nEnteredGateIndex );
if (GetVillageInfo(nNextMapIdx, nOriginChannel, nNextChannelID, cNextVillageID, szIP, nPort) == false)
{
_DANGER_POINT();
return;
}
_CheckPvPVillageToPvPLobby( pPacket, pUser, cNextVillageID, nNextChannelID );
}
else // 치트용
{
if (GetVillageInfo(pPacket->nMapIndex, nOriginChannel, nNextChannelID, cNextVillageID, szIP, nPort) == false)
{
_DANGER_POINT();
return;
}
nNextMapIdx = pPacket->nMapIndex;
}
if (pPacket->cReqType == REQINFO_TYPE_PARTY)
{
#if defined( PRE_PARTY_DB )
for (int i = 0; i < pPacket->PartyData.PartyData.iCurMemberCount; i++)
#else
for (int i = 0; i < pPacket->PartyData.cMemberCount; i++)
#endif
{
#if defined( PRE_PARTY_DB )
if (VillageToVillage(pCon, pPacket->PartyData.MemberInfo[i].nAccountDBID, cNextVillageID, nNextChannelID, pPacket->biID) == false)
#else
if (VillageToVillage(pCon, pPacket->PartyData.MemberInfo[i].nAccountDBID, cNextVillageID, nNextChannelID, pPacket->nID) == false)
#endif // #if defined( PRE_PARTY_DB )
{
_DANGER_POINT();
SendDetachUser(pPacket->PartyData.MemberInfo[i].nAccountDBID);
}
}
if (cNextVillageID != pCon->GetVillageID()) //물리적으로 다른 마을로 이동이다. 그쪽에 파티를 푸쉬해준다
{
CDNVillageConnection * pVillageCon = GetVillageConnectionByVillageID(cNextVillageID);
if (pVillageCon)
{
#if defined( PRE_PARTY_DB )
pVillageCon->SendPushParty(nAccountDBID, pPacket->biID, nNextChannelID, pUser->m_nRandomSeed, &pPacket->PartyData);
#else
pVillageCon->SendPushParty(nAccountDBID, pPacket->nID, nNextChannelID, pUser->m_nRandomSeed, &pPacket->PartyData);
#endif // #if defined( PRE_PARTY_DB )
pCon->SendTargetVillageInfo(pUser->GetAccountDBID(), cNextVillageID, nNextChannelID, nNextMapIdx, nNextGateIdx, szIP, nPort, ERROR_NONE);
}
else
pCon->SendTargetVillageInfo(pUser->GetAccountDBID(), cNextVillageID, nNextChannelID, nNextMapIdx, nNextGateIdx, szIP, nPort, ERROR_GENERIC_UNKNOWNERROR);
}
else
pCon->SendTargetVillageInfo(pUser->GetAccountDBID(), cNextVillageID, nNextChannelID, nNextMapIdx, nNextGateIdx, szIP, nPort, ERROR_NONE);
}
else
{
if (VillageToVillage(pCon, pUser->GetAccountDBID(), cNextVillageID, nNextChannelID, 0))
{
pCon->SendTargetVillageInfo(pUser->GetAccountDBID(), cNextVillageID, nNextChannelID, nNextMapIdx, nNextGateIdx, szIP, nPort, ERROR_NONE, pPacket->cReqType == REQINFO_TYPE_SINGLE_SAMEDEST ? true : false, pPacket->nItemSerial);
}
else
{
_DANGER_POINT();
SendDetachUser(pUser->GetAccountDBID());
}
}
}
void CDivisionManager::MoveGameToVillage(CDNGameConnection * pCon, GAMARequestNextVillageInfo * pPacket)
{
CDNUser * pUser = NULL;
UINT nAccountDBID = 0;
char szIP[IPLENMAX] = { 0, };
USHORT nPort = 0;
BYTE cVillageID = 0;
int nChannelID = 0;
switch (pPacket->cReqGameIDType)
{
case REQINFO_TYPE_SINGLE:
{
nAccountDBID = static_cast<UINT>(pPacket->InstanceID);
break;
}
case REQINFO_TYPE_PVP:
case REQINFO_TYPE_PVP_BREAKINTO:
case REQINFO_TYPE_PARTY: nAccountDBID = pPacket->PartyData.nLeaderAccountDBID; break;
default: _ASSERT(0);
}
pUser = GetUserByAccountDBID(nAccountDBID);
if (pUser == NULL || pCon == NULL)
{
_DANGER_POINT();
if (pCon)
pCon->SendNextVillageServerInfo(nAccountDBID, pPacket->nMapIndex, 0, 0, szIP, nPort, ERROR_GENERIC_VILLAGECON_NOT_FOUND);
return;
}
int nOriginChannel = pUser->GetChannelID();
if (pPacket->cReturnVillage == 1)
{
if (GetVillageInfo(pPacket->nMapIndex, nOriginChannel,nChannelID, cVillageID, szIP, nPort) == false)
{
_DANGER_POINT();
pCon->SendNextVillageServerInfo(nAccountDBID, pPacket->nMapIndex, 0, 0, szIP, nPort, ERROR_GENERIC_VILLAGECON_NOT_FOUND);
return;
}
if (pPacket->cReqGameIDType == REQINFO_TYPE_PARTY)
{
#if defined( PRE_PARTY_DB )
for (int i = 0; i < pPacket->PartyData.PartyData.iCurMemberCount; i++)
#else
for (int i = 0; i < pPacket->PartyData.cMemberCount; i++)
#endif
{
if (GameToVillage(pCon, pPacket->PartyData.MemberInfo[i].nAccountDBID, cVillageID, nChannelID) == false)
{
_DANGER_POINT();
SendDetachUser(pPacket->PartyData.MemberInfo[i].nAccountDBID); //스테이트미스매치
}
}
CDNVillageConnection * pVillageCon = GetVillageConnectionByVillageID(cVillageID);
if (pVillageCon)
{
pVillageCon->SendPushParty(nAccountDBID, pPacket->InstanceID, nChannelID, pUser->m_nRandomSeed, &pPacket->PartyData);
pCon->SendNextVillageServerInfo(nAccountDBID, pPacket->nMapIndex, 0, 0, szIP, nPort, ERROR_NONE);
}
else
pCon->SendNextVillageServerInfo(nAccountDBID, pPacket->nMapIndex, 0, 0, szIP, nPort, ERROR_GENERIC_UNKNOWNERROR);
}
else
{
if (GameToVillage(pCon, nAccountDBID, cVillageID, nChannelID))
{
pCon->SendNextVillageServerInfo(nAccountDBID, pPacket->nMapIndex, 0, 0, szIP, nPort, ERROR_NONE, pPacket->nItemSerial);
}
else
{
_DANGER_POINT();
SendDetachUser(nAccountDBID);
}
}
}
else
{
int nNextGateIdx = 0, nNextMapIdx = 0;
if (pPacket->nEnteredGateIndex > 0){ // mapindex, gate다 있는경우
nNextGateIdx = g_pExtManager->GetGateNoByGateNo( pPacket->nMapIndex, pPacket->nEnteredGateIndex );
nNextMapIdx = g_pExtManager->GetMapIndexByGateNo( pPacket->nMapIndex, pPacket->nEnteredGateIndex );
}
else{ // gateno를 모르는 경우
nNextGateIdx = -1;
nNextMapIdx = pPacket->nMapIndex;
}
switch( g_pExtManager->GetMapType( nNextMapIdx ) )
{
case GlobalEnum::MAP_VILLAGE:
{
char szIP[IPLENMAX] = { 0, };
unsigned short nPort = 0;
BYTE cNextVillageID = 0;
int nNextChannelID = 0;
//항상 채널은 재분배될 수 있습니다.
if (GetVillageInfo(nNextMapIdx, nOriginChannel, nNextChannelID, cNextVillageID, szIP, nPort) == false) {
pCon->SendNextVillageServerInfo(nAccountDBID, pPacket->nMapIndex, nNextMapIdx, nNextGateIdx, szIP, nPort, ERROR_GENERIC_VILLAGECON_NOT_FOUND);
break;
}
if (pPacket->cReqGameIDType == REQINFO_TYPE_PARTY)
{
#if defined( PRE_PARTY_DB )
for (int i = 0; i < pPacket->PartyData.PartyData.iCurMemberCount; i++)
#else
for (int i = 0; i < pPacket->PartyData.cMemberCount; i++)
#endif
{
if (GameToVillage(pCon, pPacket->PartyData.MemberInfo[i].nAccountDBID, cNextVillageID, nNextChannelID) == false)
{
_DANGER_POINT();
SendDetachUser(pPacket->PartyData.MemberInfo[i].nAccountDBID);
}
}
CDNVillageConnection * pVillageCon = GetVillageConnectionByVillageID(cNextVillageID);
if (pVillageCon)
{
pVillageCon->SendPushParty(nAccountDBID, pPacket->InstanceID, nNextChannelID, pUser->m_nRandomSeed, &pPacket->PartyData);
pCon->SendNextVillageServerInfo(nAccountDBID, pPacket->nMapIndex, nNextMapIdx, nNextGateIdx, szIP, nPort, ERROR_NONE);
}
else
pCon->SendNextVillageServerInfo(nAccountDBID, pPacket->nMapIndex, 0, 0, szIP, nPort, ERROR_GENERIC_UNKNOWNERROR);
}
else
{
if (GameToVillage(pCon, nAccountDBID, cNextVillageID, nNextChannelID))
pCon->SendNextVillageServerInfo(nAccountDBID, pPacket->nMapIndex, nNextMapIdx, nNextGateIdx, szIP, nPort, ERROR_NONE);
else
SendDetachUser(nAccountDBID);
}
break;
}
default:
_DANGER_POINT();
}
}
}
bool CDivisionManager::VillageToVillage(CDNVillageConnection * pCon, UINT nAccountDBID, int nVillageID, int nChannelID, TPARTYID PartyID)
{
CDNUser * pUser = GetUserByAccountDBID(nAccountDBID);
if (pUser && pUser->SetCheckVillageInfo(nVillageID, nChannelID))
{
pUser->m_VillageCheckPartyID = PartyID;
return true;
}
return false;
}
bool CDivisionManager::GameToVillage(CDNGameConnection * pCon, UINT nAccountDBID, int nVillageID, int nChannelID)
{
CDNUser * pUser = GetUserByAccountDBID(nAccountDBID);
if (pUser && pUser->SetCheckVillageInfo(nVillageID, nChannelID))
return true;
return false;
}
bool CDivisionManager::VillageToGame(CDNVillageConnection * pCon, UINT nAccountDBID, int nGameID, int nRoomID, int nServerIdx)
{
CDNUser * pUser = GetUserByAccountDBID(nAccountDBID);
if (pUser && pUser->SetCheckGameInfo(nGameID, nServerIdx))
{
pUser->m_nRoomID = nRoomID;
return true;
}
return false;
}
bool CDivisionManager::EnterVillage(UINT nAccountDBID, int nVillageID, int nChannelID)
{
CDNUser * pUser = GetUserByAccountDBID(nAccountDBID);
if (pUser)
{//최종검증한번하고 트레이스한다
if (pUser->GetVillageID() != nVillageID || pUser->GetChannelID() != nChannelID)
{
_DANGER_POINT(); //꼬였다! 일
return false;
}
const TChannelInfo * pChannelInfo = GetChannelInfo(nChannelID);
if (pChannelInfo)
{
if (pUser->SetVillageInfo(nVillageID, nChannelID, false) == false)
return false;
UpdateUserState(pUser->GetCharacterName(), pUser->GetCharacterDBID(), _LOCATION_VILLAGE, _COMMUNITY_NONE, pChannelInfo->nChannelIdx, pChannelInfo->nMapIdx); //스테이트업데이트 즐기고
#if !defined (_KR)
SendPCBangResult(pUser);
#endif
}
else
{
_DANGER_POINT();
return false;
}
#if defined(_CH) && defined(_FINAL_BUILD)
CDNVillageConnection *pVillageCon = pUser->GetCurrentVillageConnection();
if (pVillageCon)
pVillageCon->SendFCMState(pUser->GetAccountDBID(), pUser->GetFCMOnlineMin(), false);
#endif
return true;
}
_DANGER_POINT();
return false;
}
bool CDivisionManager::EnterGame(UINT nAccountDBID, int nGameID, int nRoomID, int nServerIdx)
{
CDNUser * pUser = GetUserByAccountDBID(nAccountDBID);
if (pUser)
{//최종검증한번하고 트레이스한다
if (pUser->GetGameID() != nGameID || pUser->m_nRoomID != nRoomID || pUser->GetGameServerIdx() != nServerIdx)
{
_DANGER_POINT(); //꼬였다!
return false;
}
if (pUser->SetGameInfo(nGameID, nServerIdx, false) == false)
return false;
// 캐스팅을 해줘서 원하는 함수 콜이 이루어지게 함
UpdateUserState(pUser->GetCharacterName(), pUser->GetCharacterDBID(), _LOCATION_GAME, _COMMUNITY_NONE, -1, pUser->m_nMapIndex );
#if defined(_CH) && defined(_FINAL_BUILD)
CDNGameConnection *pGameCon = pUser->GetCurrentGameConnection();
if (pGameCon)
pGameCon->SendFCMState(pUser->GetAccountDBID(), pUser->GetFCMOnlineMin(), false);
#endif // #if defined(_CH)
#if !defined (_KR)
SendPCBangResult(pUser);
#endif // #if !defined (_KR)
return true;
}
return false;
}
bool CDivisionManager::ReconnectLogin(UINT nAccountDBID)
{
CDNUser * pUser = GetUserByAccountDBID(nAccountDBID);
if (pUser)
{
//게임서버 또는 빌리지서버의 파이날 유저가 호출되면서 발생합니다.(캐릭터선택창으로 이동시
pUser->SetCheckReconnectLogin();
return true;
}
return false;
}
CDNPvP* CDivisionManager::GetPvPRoomByIdx( UINT uiIndex )
{
_TPvPMap::iterator itor = m_mPvP.find(uiIndex);
if( itor == m_mPvP.end() )
return NULL;
return (*itor).second;
}
bool CDivisionManager::SendInviteGuildMember(MAInviteGuildMember* pPacket)
{
// 길드초대할 유저를 찾는다
CDNUser * pUser = GetUserByName(pPacket->wszToCharacterName);
if( pUser )
{
switch( pUser->GetUserState() )
{
case STATE_VILLAGE:
{
// 해당 빌리지 서버에 있는 유저일 경우 길드초대 알림
CDNVillageConnection* pVillageCon = GetVillageConnectionByVillageID (pUser->GetVillageID());
if( pVillageCon )
{
pVillageCon->SendInviteGuildMember(pPacket);
return true;
}
}
break;
default:
break;
}
}
else // 유저존재 하지 않으므로 에러처리
return false;
return false;
}
#if defined (PRE_ADD_BESTFRIEND)
bool CDivisionManager::SendSearchBestFriend(MASearchBestFriend* pPacket)
{
CDNUser * pUser = NULL;
if (!pPacket->bAck)
pUser = GetUserByName(pPacket->wszName);
else
pUser = GetUserByAccountDBID(pPacket->nAccountDBID);
if( pUser )
{
switch( pUser->GetUserState() )
{
case STATE_VILLAGE:
{
CDNVillageConnection* pVillageCon = GetVillageConnectionByVillageID (pUser->GetVillageID());
if( pVillageCon )
{
pVillageCon->SendSearchBestFriend(pPacket);
return true;
}
}
break;
default:
break;
}
}
else
return false;
return false;
}
bool CDivisionManager::SendRegistBestFriend(MARegistBestFriend* pPacket)
{
CDNUser * pUser = GetUserByName(pPacket->wszToName);
if( pUser )
{
switch( pUser->GetUserState() )
{
case STATE_VILLAGE:
{
CDNVillageConnection* pVillageCon = GetVillageConnectionByVillageID (pUser->GetVillageID());
if( pVillageCon )
{
pVillageCon->SendRegistBestFriend(pPacket);
return true;
}
}
break;
default:
break;
}
}
else
return false;
return false;
}
void CDivisionManager::SendRegistBestFriendResult(MARegistBestFriendResult* pPacket)
{
CDNUser * pUser = g_pDivisionManager->GetUserByAccountDBID(pPacket->nAccountDBID);
if( pUser )
{
switch( pUser->GetUserState() )
{
case STATE_VILLAGE:
{
CDNVillageConnection* pVillageCon = g_pDivisionManager->GetVillageConnectionByVillageID( pUser->GetVillageID() );
if( pVillageCon )
pVillageCon->SendRegistBestFriendResult(pPacket);
}
break;
case STATE_GAME:
{
// 게임서버에 존재할 경우 에러처리
}
break;
}
}
}
void CDivisionManager::SendCompleteBestFriend(MACompleteBestFriend* pPacket)
{
CDNUser * pUser = g_pDivisionManager->GetUserByAccountDBID(pPacket->nToAccountDBID);
if( pUser )
{
switch( pUser->GetUserState() )
{
case STATE_VILLAGE:
{
CDNVillageConnection* pVillageCon = g_pDivisionManager->GetVillageConnectionByVillageID( pUser->GetVillageID() );
if( pVillageCon )
pVillageCon->SendCompleteBestFriend(pPacket);
}
break;
case STATE_GAME:
{
// 게임서버에 존재할 경우 에러처리
}
break;
}
}
}
void CDivisionManager::SendEditBestFriendMemo(MAEditBestFriendMemo* pPacket)
{
CDNUser * pUser = g_pDivisionManager->GetUserByCharacterDBID(pPacket->biToCharacterDBID);
if( pUser )
{
switch( pUser->GetUserState() )
{
case STATE_VILLAGE:
{
CDNVillageConnection* pVillageCon = g_pDivisionManager->GetVillageConnectionByVillageID( pUser->GetVillageID() );
if( pVillageCon )
{
pPacket->nToAccountDBID = pUser->GetAccountDBID();
pVillageCon->SendEditBestFriendMemo(pPacket);
}
}
break;
case STATE_GAME:
{
// 게임서버에 존재할 경우 에러처리
}
break;
}
}
}
void CDivisionManager::SendCancelBestFriend(MACancelBestFriend* pPacket)
{
CDNUser * pUser = g_pDivisionManager->GetUserByName(pPacket->wszToName);
if( pUser )
{
switch( pUser->GetUserState() )
{
case STATE_VILLAGE:
{
CDNVillageConnection* pVillageCon = g_pDivisionManager->GetVillageConnectionByVillageID( pUser->GetVillageID() );
if( pVillageCon )
pVillageCon->SendCancelBestFriend(pPacket);
}
break;
case STATE_GAME:
{
CDNGameConnection* pGameCon = g_pDivisionManager->GetGameConnectionByGameID( pUser->GetGameID() );
if( pGameCon )
{
pPacket->nAccountDBID = pUser->GetAccountDBID();
pGameCon->SendCancelBestFriend( pPacket );
}
break;
}
break;
}
}
}
void CDivisionManager::SendCloseBestFriend(MACloseBestFriend* pPacket)
{
CDNUser * pUser = g_pDivisionManager->GetUserByName(pPacket->wszToName);
if( pUser )
{
switch( pUser->GetUserState() )
{
case STATE_VILLAGE:
{
CDNVillageConnection* pVillageCon = g_pDivisionManager->GetVillageConnectionByVillageID( pUser->GetVillageID() );
if( pVillageCon )
pVillageCon->SendCloseBestFriend(pPacket);
}
break;
case STATE_GAME:
{
CDNGameConnection* pGameCon = g_pDivisionManager->GetGameConnectionByGameID( pUser->GetGameID() );
if( pGameCon )
{
pPacket->nAccountDBID = pUser->GetAccountDBID();
pGameCon->SendCloseBestFriend( pPacket );
}
break;
}
break;
}
}
}
void CDivisionManager::SendLevelBestFriend(MALevelUpBestFriend* pPacket)
{
CDNUser * pUser = g_pDivisionManager->GetUserByName(pPacket->wszName);
if( pUser )
{
switch( pUser->GetUserState() )
{
case STATE_VILLAGE:
{
CDNVillageConnection* pVillageCon = g_pDivisionManager->GetVillageConnectionByVillageID( pUser->GetVillageID() );
if( pVillageCon )
pVillageCon->SendLevelBestFriend(pPacket);
}
break;
case STATE_GAME:
{
CDNGameConnection* pGameCon = g_pDivisionManager->GetGameConnectionByGameID( pUser->GetGameID() );
if( pGameCon )
{
pPacket->nAccountDBID = pUser->GetAccountDBID();
pGameCon->SendLevelBestFriend( pPacket );
}
break;
}
break;
}
}
}
#endif // #if defined (PRE_ADD_BESTFRIEND)
void CDivisionManager::SendInviteGuildMemberResult(VIMAInviteGuildMemberResult* pPacket)
{
// 길드원 초대 요청한 유저를 찾는다.
CDNUser * pUser = g_pDivisionManager->GetUserByAccountDBID(pPacket->nInviterDBID);
if( pUser )
{
switch( pUser->GetUserState() )
{
case STATE_VILLAGE:
{
CDNVillageConnection* pVillageCon = g_pDivisionManager->GetVillageConnectionByVillageID( pUser->GetVillageID() );
if( pVillageCon )
pVillageCon->SendInviteGuildMemberResult(pPacket->nInviterDBID, pPacket->nRetCode, pPacket->bAck, pPacket->wszInvitedName);
}
break;
case STATE_GAME:
{
// 게임서버에 존재할 경우 에러처리
}
break;
}
}
}
void CDivisionManager::SendGuildWareInfo(MAGuildWareInfo* pPacket)
{
// 전체 VI 에 송신
vector<CDNVillageConnection*>::iterator itor;
for (itor = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itor ; ++itor)
{
if (0 != (*itor)->GetManagedID() && pPacket->nManagedID == (*itor)->GetManagedID())
continue;
(*itor)->SendGuildWareInfo(pPacket);
}
}
void CDivisionManager::SendGuildWareInfoResult(MAGuildWareInfoResult* pPacket)
{
// 요청한 VI서버에 반송
vector<CDNVillageConnection*>::iterator itor;
for (itor = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itor ; ++itor)
{
if (0 != (*itor)->GetManagedID() && pPacket->nFromManagedID == (*itor)->GetManagedID())
{
(*itor)->SendGuildWareInfoResult(pPacket);
return;
}
}
}
void CDivisionManager::SendGuildMemberLevelUp(MAGuildMemberLevelUp* pPacket)
{
// 전체 VI 에 송신
vector<CDNVillageConnection*>::iterator itorv;
for (itorv = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itorv ; ++itorv) {
if (0 != (*itorv)->GetManagedID() && pPacket->nManagedID == (*itorv)->GetManagedID()) {
continue;
}
(*itorv)->SendGuildMemberLevelUp(pPacket);
}
// 전체 GA 에 송신
vector<CDNGameConnection*>::iterator itorg;
for (itorg = m_GameServerConList.begin() ; m_GameServerConList.end() != itorg ; ++itorg) {
if (0 != (*itorg)->GetManagedID() && pPacket->nManagedID == (*itorg)->GetManagedID()) {
continue;
}
(*itorg)->SendGuildMemberLevelUp(pPacket);
}
}
void CDivisionManager::SendRefreshGuildItem(MARefreshGuildItem* pPacket)
{
// 전체 VI 에 송신
vector<CDNVillageConnection*>::iterator itor;
for (itor = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itor ; ++itor)
{
if (0 != (*itor)->GetManagedID() && pPacket->nManagedID == (*itor)->GetManagedID())
continue;
(*itor)->SendRefreshGuildItem(pPacket);
}
}
void CDivisionManager::SendRefreshGuildCoin(MARefreshGuildCoin* pPacket)
{
// 전체 VI 에 송신
vector<CDNVillageConnection*>::iterator itor;
for (itor = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itor ; ++itor)
{
if (0 != (*itor)->GetManagedID() && pPacket->nManagedID == (*itor)->GetManagedID())
continue;
(*itor)->SendRefreshGuildCoin(pPacket);
}
}
void CDivisionManager::SendExtendGuildWareSize(MAExtendGuildWare* pPacket)
{
// 전체 VI 에 송신
vector<CDNVillageConnection*>::iterator itor;
for (itor = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itor ; ++itor)
{
if (0 != (*itor)->GetManagedID() && pPacket->nManagedID == (*itor)->GetManagedID())
continue;
(*itor)->SendExtendGuildWareSize(pPacket);
}
}
void CDivisionManager::SendDismissGuild(MADismissGuild* pPacket)
{
// 전체 VI 에 송신
vector<CDNVillageConnection*>::iterator iterv;
for (iterv = m_VillageServerConList.begin() ; m_VillageServerConList.end() != iterv ; ++iterv) {
if (0 != (*iterv)->GetManagedID() && pPacket->nManagedID == (*iterv)->GetManagedID()) {
continue;
}
(*iterv)->SendDismissGuild(pPacket);
}
// 전체 GA 에 송신
vector<CDNGameConnection*>::iterator iterg;
for (iterg = m_GameServerConList.begin() ; m_GameServerConList.end() != iterg ; ++iterg) {
if (0 != (*iterg)->GetManagedID() && pPacket->nManagedID == (*iterg)->GetManagedID()) {
continue;
}
(*iterg)->SendDismissGuild(pPacket);
}
}
void CDivisionManager::SendAddGuildMember(MAAddGuildMember* pPacket)
{
// 전체 VI 에 송신
vector<CDNVillageConnection*>::iterator itorv;
for (itorv = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itorv ; ++itorv) {
if (0 != (*itorv)->GetManagedID() && pPacket->nManagedID == (*itorv)->GetManagedID()) {
continue;
}
(*itorv)->SendAddGuildMember(pPacket);
}
// 전체 GA 에 송신
vector<CDNGameConnection*>::iterator itorg;
for (itorg = m_GameServerConList.begin() ; m_GameServerConList.end() != itorg ; ++itorg) {
if (0 != (*itorg)->GetManagedID() && pPacket->nManagedID == (*itorg)->GetManagedID()) {
continue;
}
(*itorg)->SendAddGuildMember(pPacket);
}
}
void CDivisionManager::SendDelGuildMember(MADelGuildMember* pPacket)
{
// 전체 VI 에 송신
vector<CDNVillageConnection*>::iterator itorv;
for (itorv = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itorv ; ++itorv) {
if (0 != (*itorv)->GetManagedID() && pPacket->nManagedID == (*itorv)->GetManagedID()) {
continue;
}
(*itorv)->SendDelGuildMember(pPacket);
}
// 전체 GA 에 송신
vector<CDNGameConnection*>::iterator itorg;
for (itorg = m_GameServerConList.begin() ; m_GameServerConList.end() != itorg ; ++itorg) {
if (0 != (*itorg)->GetManagedID() && pPacket->nManagedID == (*itorg)->GetManagedID()) {
continue;
}
(*itorg)->SendDelGuildMember(pPacket);
}
}
void CDivisionManager::SendChangeGuildInfo(MAChangeGuildInfo* pPacket)
{
// 전체 VI 에 송신
vector<CDNVillageConnection*>::iterator itorv;
for (itorv = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itorv ; ++itorv) {
if (0 != (*itorv)->GetManagedID() && pPacket->nManagedID == (*itorv)->GetManagedID()) {
continue;
}
(*itorv)->SendChangeGuildInfo(pPacket);
}
// 전체 GA 에 송신
vector<CDNGameConnection*>::iterator itorg;
for (itorg = m_GameServerConList.begin() ; m_GameServerConList.end() != itorg ; ++itorg) {
if (0 != (*itorg)->GetManagedID() && pPacket->nManagedID == (*itorg)->GetManagedID()) {
continue;
}
(*itorg)->SendChangeGuildInfo(pPacket);
}
}
void CDivisionManager::SendChangeGuildMemberInfo(MAChangeGuildMemberInfo* pPacket)
{
// 전체 VI 에 송신
vector<CDNVillageConnection*>::iterator itorv;
for (itorv = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itorv ; ++itorv) {
if (0 != (*itorv)->GetManagedID() && pPacket->nManagedID == (*itorv)->GetManagedID()) {
continue;
}
(*itorv)->SendChangeGuildMemberInfo(pPacket);
}
// 전체 GA 에 송신
vector<CDNGameConnection*>::iterator itorg;
for (itorg = m_GameServerConList.begin() ; m_GameServerConList.end() != itorg ; ++itorg) {
if (0 != (*itorg)->GetManagedID() && pPacket->nManagedID == (*itorg)->GetManagedID()) {
continue;
}
(*itorg)->SendChangeGuildMemberInfo(pPacket);
}
}
void CDivisionManager::SendGuildChat(MAGuildChat* pPacket)
{
#ifdef PRE_ADD_DOORS_GUILDCHAT_DISCONNECT
if (g_pDoorsConnection && g_pDoorsConnection->GetActive())
{
CDNUser * pUser = GetUserByAccountDBID(pPacket->nAccountDBID);
if (pUser)
g_pDoorsConnection->SendGuildChatToDoors(pUser, pPacket->GuildUID.nDBID, pPacket->wszChatMsg, pPacket->nLen);
}
#endif //#ifdef PRE_ADD_DOORS_GUILDCHAT_DISCONNECT
// 전체 VI 에 송신
vector<CDNVillageConnection*>::iterator itorv;
for (itorv = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itorv ; ++itorv) {
(*itorv)->SendGuildChat(pPacket);
}
// 전체 GA 에 송신
vector<CDNGameConnection*>::iterator itorg;
for (itorg = m_GameServerConList.begin() ; m_GameServerConList.end() != itorg ; ++itorg) {
(*itorg)->SendGuildChat(pPacket);
}
}
void CDivisionManager::SendChangeGuildName(MAGuildChangeName* pPacket)
{
// 전체 VI 에 송신
vector<CDNVillageConnection*>::iterator itorv;
for (itorv = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itorv ; ++itorv) {
(*itorv)->SendChangeGuildName(pPacket);
}
// 전체 GA 에 송신
vector<CDNGameConnection*>::iterator itorg;
for (itorg = m_GameServerConList.begin() ; m_GameServerConList.end() != itorg ; ++itorg) {
(*itorg)->SendChangeGuildName(pPacket);
}
}
void CDivisionManager::SendChangeGuildMark(MAGuildChangeMark* pPacket)
{
// 전체 VI 에 송신
vector<CDNVillageConnection*>::iterator itorv;
for (itorv = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itorv ; ++itorv)
(*itorv)->SendChangeGuildMark(pPacket);
// 전체 GA 에 송신
vector<CDNGameConnection*>::iterator itorg;
for (itorg = m_GameServerConList.begin() ; m_GameServerConList.end() != itorg ; ++itorg)
(*itorg)->SendChangeGuildMark(pPacket);
}
void CDivisionManager::SendUpdateGuildExp(MAUpdateGuildExp* pPacket)
{
// 전체 VI 에 송신
vector<CDNVillageConnection*>::iterator itorv;
for (itorv = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itorv ; ++itorv)
(*itorv)->SendUpdateGuildExp(pPacket);
// 전체 GA 에 송신
vector<CDNGameConnection*>::iterator itorg;
for (itorg = m_GameServerConList.begin() ; m_GameServerConList.end() != itorg ; ++itorg)
(*itorg)->SendUpdateGuildExp(pPacket);
}
void CDivisionManager::SendEnrollGuildWar(MAEnrollGuildWar* pPacket)
{
// 전체 VI 에 송신
vector<CDNVillageConnection*>::iterator itorv;
for (itorv = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itorv ; ++itorv)
{
if (0 != (*itorv)->GetManagedID() && pPacket->nManagedID == (*itorv)->GetManagedID())
continue;
(*itorv)->SendEnrollGuildWar(pPacket);
}
// 전체 GA 에 송신
vector<CDNGameConnection*>::iterator itorg;
for (itorg = m_GameServerConList.begin() ; m_GameServerConList.end() != itorg ; ++itorg)
{
if (0 != (*itorg)->GetManagedID() && pPacket->nManagedID == (*itorg)->GetManagedID())
continue;
(*itorg)->SendEnrollGuildWar(pPacket);
}
}
void CDivisionManager::SendChangeGuildWarStep(MAChangeGuildWarStep* pPacket)
{
// 전체 VI 에 송신
vector<CDNVillageConnection*>::iterator itorv;
for (itorv = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itorv ; ++itorv)
{
(*itorv)->SendChangeGuildWarStep(pPacket);
}
// 전체 GA 에 송신
vector<CDNGameConnection*>::iterator itorg;
for (itorg = m_GameServerConList.begin() ; m_GameServerConList.end() != itorg ; ++itorg)
{
(*itorg)->SendChangeGuildWarStep(pPacket);
}
}
void CDivisionManager::SendSetGuildWarPoint(MASetGuildWarPoint* pPacket)
{
// 전체 VI 에 송신
vector<CDNVillageConnection*>::iterator itorv;
for (itorv = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itorv ; ++itorv)
{
(*itorv)->SendSetGuildWarPoint(pPacket);
}
// 전체 GA 에 송신
vector<CDNGameConnection*>::iterator itorg;
for (itorg = m_GameServerConList.begin() ; m_GameServerConList.end() != itorg ; ++itorg)
{
(*itorg)->SendSetGuildWarPoint(pPacket);
}
}
void CDivisionManager::SendSetGuildWarPreWinGuild(MAGuildWarPreWinGuild* pPacket)
{
// 전체 VI 에 송신
vector<CDNVillageConnection*>::iterator itorv;
for (itorv = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itorv ; ++itorv)
{
(*itorv)->SendSetGuildWarPreWinGuild(pPacket);
}
// 전체 GA 에 송신
vector<CDNGameConnection*>::iterator itorg;
for (itorg = m_GameServerConList.begin() ; m_GameServerConList.end() != itorg ; ++itorg)
{
(*itorg)->SendSetGuildWarPreWinGuild(pPacket);
}
}
#if defined(PRE_FIX_75807)
void CDivisionManager::SendSetGuildWarPreWinGuildGameServer(MAGuildWarPreWinGuild* pPacket)
{
// 전체 GA 에 송신
vector<CDNGameConnection*>::iterator itorg;
for (itorg = m_GameServerConList.begin() ; m_GameServerConList.end() != itorg ; ++itorg)
{
(*itorg)->SendSetGuildWarPreWinGuild(pPacket);
}
}
#endif //#if defined(PRE_FIX_75807)
void CDivisionManager::SendAddGuildWarPoint(MAAddGuildWarPoint* pPacket)
{
// 전체 VI 에 송신, GA는 필요없음.
vector<CDNVillageConnection*>::iterator itor;
for (itor = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itor ; ++itor)
{
(*itor)->SendAddGuildWarPoint(pPacket);
}
}
void CDivisionManager::SendGetGuildWarTrialStats()
{
// 전체 VI 에 송신, GA는 필요없음.
vector<CDNVillageConnection*>::iterator itor;
for (itor = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itor ; ++itor)
{
(*itor)->SendGetGuildWarTrialStats();
}
}
void CDivisionManager::SendSetGuildWarTournamentInfo(SGuildTournamentInfo* pGuildTournamentInfo)
{
// 전체 VI 에 송신, GA는 필요없음.
vector<CDNVillageConnection*>::iterator itor;
for (itor = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itor ; ++itor)
{
(*itor)->SendSetGuildWarTournamentInfo(pGuildTournamentInfo);
}
}
void CDivisionManager::SendSetGuildwarFinalProcess(char cGuildFinalPart, __time64_t tBeginTime)
{
// 전체 VI 에 송신
vector<CDNVillageConnection*>::iterator itorv;
for (itorv = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itorv ; ++itorv)
{
(*itorv)->SendSetGuildwarFinalProcess(cGuildFinalPart, tBeginTime);
}
// 전체 GA 에 송신
vector<CDNGameConnection*>::iterator itorg;
for (itorg = m_GameServerConList.begin() ; m_GameServerConList.end() != itorg ; ++itorg)
{
(*itorg)->SendSetGuildwarFinalProcess(cGuildFinalPart, tBeginTime);
}
}
void CDivisionManager::SendGuildWarInfoToVillage(CDNVillageConnection* pCon)
{
char cStepIndex = g_pGuildWarManager->GetStepIndex();
#if defined(PRE_FIX_75807)
// 본선이 아니거나 차수가 진행중이 아니고 지난대회 우승팀이 있으면 보냄
if( (cStepIndex != GUILDWAR_STEP_REWARD || !g_pGuildWarManager->GetFinalStart()) && g_pGuildWarManager->GetPreWinGuild().IsSet() )
{
if( g_pGuildWarManager->GetFinalWinGuildReward() )
{
MAGuildWarPreWinGuild GuildWarPreWinGuild;
GuildWarPreWinGuild.GuildUID = g_pGuildWarManager->GetPreWinGuild();
GuildWarPreWinGuild.bPreWin = true;
pCon->SendSetGuildWarPreWinGuild(&GuildWarPreWinGuild);
if( g_pGuildWarManager->GetPreWinSKillCoolTime() > 0 )
{
MAGuildWarPreWinSkillCoolTime GuildWarPreWinSkillCoolTime = {0,};
GuildWarPreWinSkillCoolTime.dwSkillCoolTime = g_pGuildWarManager->GetPreWinSKillCoolTime();
pCon->SendSetGuildWarPreWinSkillCoolTime(&GuildWarPreWinSkillCoolTime);
}
}
}
#endif //#if defined(PRE_FIX_75807)
if( g_pGuildWarManager->GetGuildWarSettingStep() == REQ_ALL_COMPLETE )
{
// 전체 스케쥴 보내주기
MASetGuildWarEventTime SetGuildWarEventTime;
memset(&SetGuildWarEventTime, 0, sizeof(SetGuildWarEventTime));
memcpy(SetGuildWarEventTime.sGuildWarTime, g_pGuildWarManager->GetGuildWarSchedule(), sizeof(SetGuildWarEventTime.sGuildWarTime));
memcpy(SetGuildWarEventTime.sFinalPartTime, g_pGuildWarManager->GetGuildWarFinalSchedule(), sizeof(SetGuildWarEventTime.sFinalPartTime));
SetGuildWarEventTime.bFinalProgress = g_pGuildWarManager->GetFinalProgress();
pCon->SendSetGuildWarSchedule(&SetGuildWarEventTime);
}
if( cStepIndex == GUILDWAR_STEP_NONE
|| !(g_pGuildWarManager->GetWarEvent(cStepIndex))->IsValidPeriod() )
return;
MAChangeGuildWarStep ChangeGuildWarStep;
memset(&ChangeGuildWarStep, 0, sizeof(ChangeGuildWarStep));
ChangeGuildWarStep.wScheduleID = g_pGuildWarManager->GetScheduleID();
ChangeGuildWarStep.cEventType = GUILDWAR_EVENT_START;
ChangeGuildWarStep.cEventStep = cStepIndex;
ChangeGuildWarStep.wWinersWeightRate = g_pGuildWarManager->GetWinersWeightRate();
pCon->SendChangeGuildWarStep(&ChangeGuildWarStep);
// 예선전이거나 보상기간이면 각 팀 점수보내주기..
if( cStepIndex == GUILDWAR_STEP_TRIAL || cStepIndex == GUILDWAR_STEP_REWARD)
{
MASetGuildWarPoint SetGuildWarPoint = {0,};
SetGuildWarPoint.nBlueTeamPoint = g_pGuildWarManager->GetBlueTeamPoint();
SetGuildWarPoint.nRedTeamPoint = g_pGuildWarManager->GetRedTeamPoint();
pCon->SendSetGuildWarPoint(&SetGuildWarPoint);
if( cStepIndex == GUILDWAR_STEP_TRIAL )
{
//24위 까지 정보 보내주기..
pCon->SendSetGuildWarPointRunning((MASetGuildWarPointRunningTotal*)g_pGuildWarManager->GetGuildWarPointTrialRanking());
}
}
// 본선이고 예선집계가 가능하면 대진표 정보랑 집계하라고 보냄
if( cStepIndex == GUILDWAR_STEP_REWARD )
{
if( g_pGuildWarManager->IsTrialStats() )
{
pCon->SendSetGuildWarTournamentInfo(g_pGuildWarManager->GetGuildTournamentInfo());
pCon->SendGetGuildWarTrialStats();
}
pCon->SendSetGuildwarFinalProcess(g_pGuildWarManager->GetCurFinalPart(), g_pGuildWarManager->GetCurFinalPartBeginTime());
}
#if defined(PRE_FIX_75807)
#else
// 본선이 아니거나 차수가 진행중이 아니고 지난대회 우승팀이 있으면 보냄
if( (cStepIndex != GUILDWAR_STEP_REWARD || !g_pGuildWarManager->GetFinalStart()) && g_pGuildWarManager->GetPreWinGuild().IsSet() )
{
if( g_pGuildWarManager->GetFinalWinGuildReward() )
{
MAGuildWarPreWinGuild GuildWarPreWinGuild;
GuildWarPreWinGuild.GuildUID = g_pGuildWarManager->GetPreWinGuild();
GuildWarPreWinGuild.bPreWin = true;
pCon->SendSetGuildWarPreWinGuild(&GuildWarPreWinGuild);
if( g_pGuildWarManager->GetPreWinSKillCoolTime() > 0 )
{
MAGuildWarPreWinSkillCoolTime GuildWarPreWinSkillCoolTime = {0,};
GuildWarPreWinSkillCoolTime.dwSkillCoolTime = g_pGuildWarManager->GetPreWinSKillCoolTime();
pCon->SendSetGuildWarPreWinSkillCoolTime(&GuildWarPreWinSkillCoolTime);
}
}
}
#endif //#if defined(PRE_FIX_75807)
BYTE cSecretTeam = g_pGuildWarManager->GetSecretTeam();
if (cSecretTeam > 0)
{
MASetGuildWarSecretMission SecretMission;
SecretMission.cTeamCode = cSecretTeam;
SecretMission.nRandomSeed = g_pGuildWarManager->GetSecretRandomSeed();
pCon->SendSetGuildWarSecretMission(&SecretMission);
}
}
void CDivisionManager::SendGuildWarInfoToGame(CDNGameConnection* pCon)
{
char cStepIndex = g_pGuildWarManager->GetStepIndex();
#if defined(PRE_FIX_75807)
// 본선이 아니거나 차수가 진행중이 아니고 지난대회 우승팀이 있으면 보냄
if( (cStepIndex != GUILDWAR_STEP_REWARD || !g_pGuildWarManager->GetFinalStart() ) && g_pGuildWarManager->GetPreWinGuild().IsSet() )
{
if( g_pGuildWarManager->GetFinalWinGuildReward() ) // 보상이 지급되었는지 확인하고
{
MAGuildWarPreWinGuild GuildWarPreWinGuild;
GuildWarPreWinGuild.GuildUID = g_pGuildWarManager->GetPreWinGuild();
GuildWarPreWinGuild.bPreWin = true;
pCon->SendSetGuildWarPreWinGuild(&GuildWarPreWinGuild);
}
}
#endif //#if defined(PRE_FIX_75807)
if( cStepIndex == GUILDWAR_STEP_NONE
|| !(g_pGuildWarManager->GetWarEvent(cStepIndex))->IsValidPeriod() )
return;
if( g_pGuildWarManager->GetGuildWarSettingStep() == REQ_ALL_COMPLETE )
{
// 전체 스케쥴 보내주기
MASetGuildWarEventTime SetGuildWarEventTime;
memset(&SetGuildWarEventTime, 0, sizeof(SetGuildWarEventTime));
memcpy(SetGuildWarEventTime.sGuildWarTime, g_pGuildWarManager->GetGuildWarSchedule(), sizeof(SetGuildWarEventTime.sGuildWarTime));
memcpy(SetGuildWarEventTime.sFinalPartTime, g_pGuildWarManager->GetGuildWarFinalSchedule(), sizeof(SetGuildWarEventTime.sFinalPartTime));
SetGuildWarEventTime.bFinalProgress = g_pGuildWarManager->GetFinalProgress();
pCon->SendSetGuildWarSchedule(&SetGuildWarEventTime);
}
MAChangeGuildWarStep ChangeGuildWarStep;
memset(&ChangeGuildWarStep, 0, sizeof(ChangeGuildWarStep));
ChangeGuildWarStep.wScheduleID = g_pGuildWarManager->GetScheduleID();
ChangeGuildWarStep.cEventType = GUILDWAR_EVENT_START;
ChangeGuildWarStep.cEventStep = cStepIndex;
ChangeGuildWarStep.wWinersWeightRate = g_pGuildWarManager->GetWinersWeightRate();
pCon->SendChangeGuildWarStep(&ChangeGuildWarStep);
// 본선이면 본선정보 보내줌.
if( cStepIndex == GUILDWAR_STEP_REWARD )
{
pCon->SendSetGuildwarFinalProcess(g_pGuildWarManager->GetCurFinalPart(), g_pGuildWarManager->GetCurFinalPartBeginTime());
}
#if defined(PRE_FIX_75807)
#else
// 본선이 아니거나 차수가 진행중이 아니고 지난대회 우승팀이 있으면 보냄
if( (cStepIndex != GUILDWAR_STEP_REWARD || !g_pGuildWarManager->GetFinalStart() ) && g_pGuildWarManager->GetPreWinGuild().IsSet() )
{
if( g_pGuildWarManager->GetFinalWinGuildReward() ) // 보상이 지급되었는지 확인하고
{
MAGuildWarPreWinGuild GuildWarPreWinGuild;
GuildWarPreWinGuild.GuildUID = g_pGuildWarManager->GetPreWinGuild();
GuildWarPreWinGuild.bPreWin = true;
pCon->SendSetGuildWarPreWinGuild(&GuildWarPreWinGuild);
}
}
#endif //#if defined(PRE_FIX_75807)
BYTE cSecretTeam = g_pGuildWarManager->GetSecretTeam();
if (cSecretTeam > 0)
{
MASetGuildWarSecretMission SecretMission;
SecretMission.cTeamCode = cSecretTeam;
SecretMission.nRandomSeed = g_pGuildWarManager->GetSecretRandomSeed();
pCon->SendSetGuildWarSecretMission(&SecretMission);
}
}
void CDivisionManager::SendSetGuildWarSecretMission(MASetGuildWarSecretMission * pPacket)
{
// 전체 VI 에 송신
vector<CDNVillageConnection*>::iterator itorv;
for (itorv = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itorv ; ++itorv)
{
(*itorv)->SendSetGuildWarSecretMission(pPacket);
}
// 전체 GA 에 송신
vector<CDNGameConnection*>::iterator itorg;
for (itorg = m_GameServerConList.begin() ; m_GameServerConList.end() != itorg ; ++itorg)
{
(*itorg)->SendSetGuildWarSecretMission(pPacket);
}
}
void CDivisionManager::SendSetGuildWarFinalResult(MAVISetGuildWarFinalResult* pPacket)
{
// 전체 VI 에 송신
vector<CDNVillageConnection*>::iterator itorg;
for (itorg = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itorg ; ++itorg)
{
(*itorg)->SendSetGuildWarFinalResult(pPacket);
}
}
void CDivisionManager::SendSetGuildWarPreWinSkillCoolTime(MAGuildWarPreWinSkillCoolTime* pPacket)
{
vector<CDNVillageConnection*>::iterator itor;
for (itor = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itor ; ++itor)
{
if (0 != (*itor)->GetManagedID() && pPacket->nManagedID == (*itor)->GetManagedID())
continue;
(*itor)->SendSetGuildWarPreWinSkillCoolTime(pPacket);
}
}
void CDivisionManager::SendSetGuildWarSchedule(MASetGuildWarEventTime* pPacket)
{
// 전체 VI 에 송신
vector<CDNVillageConnection*>::iterator itor;
for (itor = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itor ; ++itor)
{
(*itor)->SendSetGuildWarSchedule(pPacket);
}
// 전체 GA 에 송신
vector<CDNGameConnection*>::iterator itorg;
for (itorg = m_GameServerConList.begin() ; m_GameServerConList.end() != itorg ; ++itorg)
{
(*itorg)->SendSetGuildWarSchedule(pPacket);
}
}
void CDivisionManager::SendSetGuildWarTournamentWin(MASetGuildWarTournamentWin* pPacket)
{
// 전체 VI 에 송신
vector<CDNVillageConnection*>::iterator itorv;
for (itorv = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itorv ; ++itorv)
{
(*itorv)->SendSetGuildWarTournamentWin(pPacket);
}
// 전체 GA 에 송신
vector<CDNGameConnection*>::iterator itorg;
for (itorg = m_GameServerConList.begin() ; m_GameServerConList.end() != itorg ; ++itorg)
{
(*itorg)->SendSetGuildWarTournamentWin(pPacket);
}
}
void CDivisionManager::SendResetGuildWarBuyedItemCount()
{
for each (CDNVillageConnection* pConnection in m_VillageServerConList)
{
pConnection->SendResetGuildWarBuyedItemCount();
}
}
void CDivisionManager::SendGuildWarAllStop()
{
// 전체 GA 에 송신
vector<CDNGameConnection*>::iterator itorg;
for (itorg = m_GameServerConList.begin() ; m_GameServerConList.end() != itorg ; ++itorg)
{
(*itorg)->SendGuildWarAllStop();
}
}
void CDivisionManager::SendGuildRecruitMember(MAGuildRecruitMember* pPacket)
{
// 길드초대할 유저를 찾는다
CDNUser * pUser = GetUserByCharacterDBID(pPacket->biCharacterDBID);
if( pUser )
{
pPacket->uiAccountDBID = pUser->GetAccountDBID();
switch( pUser->GetUserState() )
{
case STATE_VILLAGE:
{
// 해당 빌리지 서버에 있는 유저일 경우 길드가입 알림
CDNVillageConnection* pVillageCon = GetVillageConnectionByVillageID (pUser->GetVillageID());
if( pVillageCon )
{
pVillageCon->SendGuildRecruitMember(pPacket);
return;
}
}
break;
case STATE_GAME:
{
// 해당 게임 서버에 있는 유저일 경우 길드가입 알림
CDNGameConnection* pGameCon = GetGameConnectionByGameID (pUser->GetGameID());
if( pGameCon )
{
pGameCon->SendGuildRecruitMember(pPacket);
return;
}
}
break;
default:
break;
}
}
else
return;
return;
}
void CDivisionManager::SendAddGuildRewardItem(MAGuildRewardItem* pPacket)
{
// 전체 VI 에 송신
vector<CDNVillageConnection*>::iterator itorv;
for (itorv = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itorv ; ++itorv)
{
if (0 != (*itorv)->GetManagedID() && pPacket->nManagedID == (*itorv)->GetManagedID())
continue;
(*itorv)->SendAddGuildRewardItem(pPacket);
}
// 전체 GA 에 송신
vector<CDNGameConnection*>::iterator itorg;
for (itorg = m_GameServerConList.begin() ; m_GameServerConList.end() != itorg ; ++itorg)
{
if (0 != (*itorg)->GetManagedID() && pPacket->nManagedID == (*itorg)->GetManagedID())
continue;
(*itorg)->SendAddGuildRewardItem(pPacket);
}
}
void CDivisionManager::SendExtendGuildSize(MAExtendGuildSize* pPacket)
{
// 전체 VI 에 송신
vector<CDNVillageConnection*>::iterator itorv;
for (itorv = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itorv ; ++itorv)
{
if (0 != (*itorv)->GetManagedID() && pPacket->nManagedID == (*itorv)->GetManagedID())
continue;
(*itorv)->SendExtendGuildSize(pPacket);
}
// 전체 GA 에 송신
vector<CDNGameConnection*>::iterator itorg;
for (itorg = m_GameServerConList.begin() ; m_GameServerConList.end() != itorg ; ++itorg)
{
if (0 != (*itorg)->GetManagedID() && pPacket->nManagedID == (*itorg)->GetManagedID())
continue;
(*itorg)->SendExtendGuildSize(pPacket);
}
}
void CDivisionManager::SendSetGuildWarTrialRanking(MASetGuildWarPointRunningTotal* pPacket)
{
// 전체 VI 에 송신
vector<CDNVillageConnection*>::iterator itorv;
for (itorv = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itorv ; ++itorv)
{
(*itorv)->SendSetGuildWarPointRunning(pPacket);
}
}
void CDivisionManager::SendGuildWarRefreshGuildPoint(MAGuildWarRefreshGuildPoint* pPacket)
{
// 일단 전체 VI 에만 송신..게임쪽은 필요없을듯..
vector<CDNVillageConnection*>::iterator itorv;
for (itorv = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itorv ; ++itorv)
{
(*itorv)->SendGuildWarRefreshGuildPoint(pPacket);
}
}
void CDivisionManager::SendUpdateGuildWare(int nGuildID)
{
// 전체 VI 에 송신
vector<CDNVillageConnection*>::iterator itorv;
for (itorv = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itorv ; ++itorv)
{
(*itorv)->SendUpdateGuildWare(nGuildID);
}
//// 전체 GA 에 송신
//vector<CDNGameConnection*>::iterator itorg;
//for (itorg = m_GameServerConList.begin() ; m_GameServerConList.end() != itorg ; ++itorg)
//{
// (*itorg)->SendUpdateGuildWare(nGuildID);
//}
}
void CDivisionManager::SendChangeCharacterName(MAChangeCharacterName* pPacket)
{
CDNUser *pSender = GetUserByAccountDBID(pPacket->uiAccountDBID);
if (pSender)
ReplaceCharacterName(pSender, pPacket->wszCharacterName);
#if defined (PRE_ADD_BESTFRIEND)
CDNUser *pBestFriend = GetUserByCharacterDBID(pPacket->biBFCharacterDBID);
if (pBestFriend)
pPacket->uiBFAccountDBID = pBestFriend->GetAccountDBID();
#endif // #if defined (PRE_ADD_BESTFRIEND)
// 전체 VI 에 송신
vector<CDNVillageConnection*>::iterator itorv;
for (itorv = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itorv ; ++itorv)
{
if (0 != (*itorv)->GetManagedID() && pPacket->nManagedID == (*itorv)->GetManagedID())
continue;
(*itorv)->SendChangeCharacterName(pPacket);
}
// 전체 GA 에 송신
vector<CDNGameConnection*>::iterator itorg;
for (itorg = m_GameServerConList.begin() ; m_GameServerConList.end() != itorg ; ++itorg)
{
if (0 != (*itorg)->GetManagedID() && pPacket->nManagedID == (*itorg)->GetManagedID())
continue;
(*itorg)->SendChangeCharacterName(pPacket);
}
}
void CDivisionManager::SendFriendAddNotice(UINT nAddedAccountDBID, const WCHAR * pAddName)
{
CDNUser * pUser = GetUserByAccountDBID(nAddedAccountDBID);
if (pUser)
{
//이동 중일 경우와 오프라인은 무시 한다.
if (pUser->GetUserState() == STATE_GAME || pUser->GetUserState() == STATE_VILLAGE)
{
ScopeLock<CSyncLock> Lock(m_Sync);
if (pUser->GetUserState() == STATE_GAME)
{
CDNGameConnection * pGameCon = GetGameConnectionByGameID(pUser->GetGameID());
if (pGameCon)
pGameCon->SendFriendAddNotice(pUser->GetAccountDBID(), pAddName);
}
else if (pUser->GetUserState() == STATE_VILLAGE)
{
CDNVillageConnection * pVillageCon = GetVillageConnectionByVillageID(pUser->GetVillageID());
if (pVillageCon)
pVillageCon->SendFriendAddNotice(pUser->GetAccountDBID(), pAddName);
}
}
}
}
bool CDivisionManager::RequestGameRoom( BYTE cReqGameIDType, UINT uiIndex, int nRandomSeed, int nMapIndex, char cGateNo, char cStageConstructionLevel, bool bDirectConnect, bool bTutorial, int nServerID /* 튜토리얼일 경우만 LO ID 입력 */)
{
//튜토리얼과 PvP만이걸로
int nGameServerID = 0;
CDNGameConnection* pGameCon = GetFreeGameConnection(&nGameServerID, cReqGameIDType);
if( !pGameCon )
return false;
if( cReqGameIDType == REQINFO_TYPE_SINGLE )
{
CDNUser* pUser = GetUserByAccountDBID(uiIndex);
if( pUser )
{
if (pUser->SetCheckGameInfo( pGameCon->GetGameID(), -1 ) == false)
return false;
pUser->m_nRandomSeed = nRandomSeed;
pUser->m_nMapIndex = nMapIndex;
pUser->m_cGateNo = cGateNo;
if (bTutorial) { // login에서 보낸거
pGameCon->SendReqTutorialRoomID(pUser, nServerID);
}
else
{
#if defined( STRESS_TEST )
pGameCon->SendReqRoomID( GameTaskType::Normal, pUser, cStageConstructionLevel, 0, true );
return true;
#endif
_DANGER_POINT();
return false;
}
return true;
}
}
else if( cReqGameIDType == REQINFO_TYPE_PVP || cReqGameIDType == REQINFO_TYPE_PVP_BREAKINTO)
{
CDNPvP* pPvPRoom = GetPvPRoomByIdx( uiIndex );
if( pPvPRoom )
{
pPvPRoom->SetAllGameID( pGameCon->GetGameID(), nRandomSeed, nMapIndex, cGateNo );
if (pGameCon->SendReqRoomID( pPvPRoom, bDirectConnect ) == false)
return false;
return true;
}
_DANGER_POINT();
}
else
_DANGER_POINT();
return false;
}
bool CDivisionManager::RequestGameRoom(VIMAReqGameID * pPacket)
{
int nGameServerID = 0;
#if defined( PRE_FIX_WORLDCOMBINEPARTY )
CDNGameConnection* pGameCon = NULL;
if( Party::bIsWorldCombineParty(pPacket->PartyData.PartyData.Type) )
{
pGameCon = GetWorldCombineGameConnection();
}
else
pGameCon = GetFreeGameConnection(&nGameServerID, pPacket->cReqGameIDType);
#else // #if defined( PRE_FIX_WORLDCOMBINEPARTY )
CDNGameConnection* pGameCon = GetFreeGameConnection(&nGameServerID, pPacket->cReqGameIDType);
#endif // #if defined( PRE_FIX_WORLDCOMBINEPARTY )
if( !pGameCon )
return false;
if( pPacket->cReqGameIDType == REQINFO_TYPE_SINGLE )
{
CDNUser* pUser = GetUserByAccountDBID(static_cast<UINT>(pPacket->InstanceID));
if( pUser )
{
//강제할당처리 검사
int nSID = 0;
if (IsSelectJoin(pUser->GetCharacterName(), nSID))
{
pGameCon = GetGameConnectionByManagedID(nSID);
if( !pGameCon )
return false;
}
if (pUser->SetCheckGameInfo( pGameCon->GetGameID(), -1 ) == false)
return false;
pUser->m_nRandomSeed = pPacket->nRandomSeed;
pUser->m_nMapIndex = pPacket->nMapIndex;
pUser->m_cGateNo = pPacket->cGateNo;
pUser->m_cGateSelect = pPacket->cGateSelect;
const TChannelInfo * pInfo = GetChannelInfo(pUser->GetVillageID(), pUser->GetChannelID());
if (pInfo)
{
bool bRet = pGameCon->SendReqRoomID( pPacket->GameTaskType, pUser, pPacket->StageDifficulty, pInfo->nMeritBonusID, pPacket->bDirectConnect );
if( !bRet )
{
g_Log.Log( LogType::_GAMECONNECTLOG, pUser, L"SendReqRoomID() Failed!!\n" );
}
return bRet;
}
else
{
#if defined( STRESS_TEST )
pGameCon->SendReqRoomID( GameTaskType::Normal, pUser, 0, 0, true );
return true;
#endif
_DANGER_POINT();
return false;
}
}
_DANGER_POINT();
}
else if( pPacket->cReqGameIDType == REQINFO_TYPE_PARTY || pPacket->cReqGameIDType == REQINFO_TYPE_PARTY_BREAKINTO )
{
CDNUser * pUser = NULL;
#if defined( PRE_PARTY_DB )
for (int i = 0; i < pPacket->PartyData.PartyData.iCurMemberCount; i++)
#else
for (int i = 0; i < pPacket->PartyData.cMemberCount; i++)
#endif
{
pUser = GetUserByAccountDBID(pPacket->PartyData.MemberInfo[i].nAccountDBID);
if (pUser)
{
if (pUser->SetCheckGameInfo( pGameCon->GetGameID(), -1 ) == false)
continue;
pUser->m_VillageCheckPartyID = pPacket->InstanceID;
pUser->m_nRandomSeed = pPacket->nRandomSeed;
pUser->m_nMapIndex = pPacket->nMapIndex;
pUser->m_cGateNo = pPacket->cGateNo;
pUser->m_cGateSelect = pPacket->cGateSelect;
}
else
_DANGER_POINT();
}
#if defined( PRE_WORLDCOMBINE_PARTY )
if( Party::bIsWorldCombineParty(pPacket->PartyData.PartyData.Type) )
{
const TChannelInfo * pInfo = GetChannelInfo( m_cPvPLobbyVillageID, m_unPvPLobbyChannelID );
if (pInfo)
pGameCon->SendReqRoomID(pPacket, pInfo->nMeritBonusID);
else
{
_DANGER_POINT();
return false;
}
}
else
{
if (pUser == NULL)
{
_DANGER_POINT();
return false;
}
const TChannelInfo * pInfo = GetChannelInfo(pUser->GetVillageID(), pUser->GetChannelID());
if (pInfo)
pGameCon->SendReqRoomID(pPacket, pInfo->nMeritBonusID);
else
{
_DANGER_POINT();
return false;
}
}
#else
if (pUser == NULL)
{
_DANGER_POINT();
return false;
}
const TChannelInfo * pInfo = GetChannelInfo(pUser->GetVillageID(), pUser->GetChannelID());
if (pInfo)
pGameCon->SendReqRoomID(pPacket, pInfo->nMeritBonusID);
else
{
_DANGER_POINT();
return false;
}
#endif
return true;
}
else if( pPacket->cReqGameIDType == REQINFO_TYPE_PVP )
{
CDNPvP* pPvPRoom = GetPvPRoomByIdx( static_cast<UINT>(pPacket->InstanceID) );
if( pPvPRoom )
{
pPvPRoom->SetAllGameID( pGameCon->GetGameID(), pPacket->nRandomSeed, pPacket->nMapIndex, pPacket->cGateNo );
pGameCon->SendReqRoomID( pPvPRoom, pPacket->bDirectConnect );
return true;
}
_DANGER_POINT();
}
else if (pPacket->cReqGameIDType == REQINFO_TYPE_FARM)
{
CDNUser * pFarmUser = GetUserByAccountDBID(static_cast<UINT>(pPacket->InstanceID));
if (pFarmUser == NULL)
{
_DANGER_POINT(); //이럼 안데시어요.
return false;
}
//농장의 생성은 유저의 요청에서는 없다!
bool bAlreadyCreated = false;
CDNFarm * pFarm = GetFarm(pPacket->nFarmDBID);
if (pFarm)
{
if (pFarm->GetFarmStatus() == FARMSTATUS_PLAY)
{
int nFarmGameServerID = -1;
int nFarmGameServerThreadIdx = -1;
UINT nFarmRoomID;
pFarm->GetAssignedServerInfo(nFarmGameServerID, nFarmGameServerThreadIdx, nFarmRoomID);
pGameCon = GetGameConnectionByGameID(nFarmGameServerID);
if (pGameCon)
{
pGameCon->SendBreakintoRoom( nFarmRoomID, pFarmUser, BreakInto::Type::None );
return true;
}
}
else
{
if (pFarm->GetFarmStatus() != FARMSTATUS_DESTROY)
{
if (pFarm->VerifyWaitAndPush(const_cast<const VIMAReqGameID*>(pPacket)))
return true;
else
_DANGER_POINT(); //이런경우는 나오면 안덴다.
}
return false;
}
}
_DANGER_POINT(); //헐... 이러면 생성도중 또는 등등의 상황에 서버가 죽었을 경우이다.
return false;
}
else
_DANGER_POINT();
return false;
}
bool CDivisionManager::RequestGameRoom( VIMALadderReqGameID* pPacket )
{
int nGameServerID = 0;
CDNGameConnection* pGameCon = GetFreeGameConnection(&nGameServerID, REQINFO_TYPE_LADDER );
if( !pGameCon )
return false;
// AllUser 검사
for( int i=0 ; i<pPacket->LadderData.cMemberCount ; ++i )
{
CDNUser* pUser = GetUserByAccountDBID( pPacket->LadderData.MemberInfoArr[i].uiAccountDBID );
if( pUser == NULL )
{
_DANGER_POINT();
return false;
}
}
for( int i=0 ; i<pPacket->LadderData.cMemberCount ; ++i )
{
CDNUser* pUser = GetUserByAccountDBID( pPacket->LadderData.MemberInfoArr[i].uiAccountDBID );
if (pUser->SetCheckGameInfo( pGameCon->GetGameID(), -1 ) == false)
continue;
pUser->m_nRandomSeed = pPacket->iRandomSeed;
pUser->m_nMapIndex = pPacket->iMapIndex;
}
pGameCon->SendLadderReqRoomID( pPacket );
return true;
}
#if defined( PRE_WORLDCOMBINE_PVP )
bool CDivisionManager::RequestGameRoom( VIMACreateWorldPvPRoom* pPacket, BYTE cVillageID )
{
int nGameServerID = 0;
CDNGameConnection* pGameCon = GetWorldCombineGameConnection();
if( !pGameCon )
return false;
pGameCon->SendWorldPvPReqRoomID( pPacket, cVillageID );
return true;
}
#endif
#if defined( PRE_ADD_FARM_DOWNSCALE )
bool CDivisionManager::RequestFarmGameRoom(UINT nFarmDBID, int nMapID, int nMaxUser, bool bStart, int &nServerID, int iAttr )
#elif defined( PRE_ADD_VIP_FARM )
bool CDivisionManager::RequestFarmGameRoom(UINT nFarmDBID, int nMapID, int nMaxUser, bool bStart, int &nServerID, Farm::Attr::eType Attr )
#else
bool CDivisionManager::RequestFarmGameRoom(UINT nFarmDBID, int nMapID, int nMaxUser, bool bStart, int &nServerID)
#endif // #if defined( PRE_ADD_FARM_DOWNSCALE )
{
CDNGameConnection* pGameCon = NULL;
if (m_nFarmGameindex == -1)
{
#ifdef PRE_MOD_OPERATINGFARM
if (IsFarmConnectionWatingTime(timeGetTime()) && g_Config.nFarmServerID > 0)
pGameCon = GetFarmGameConnection(&nServerID);
else
pGameCon = GetFreeGameConnection(&nServerID, REQINFO_TYPE_FARM);
#else //#ifdef PRE_MOD_OPERATINGFARM
pGameCon = GetFreeGameConnection(&nServerID, REQINFO_TYPE_FARM);
#endif //#ifdef PRE_MOD_OPERATINGFARM
}
else
pGameCon = GetGameConnectionByGameID(m_nFarmGameindex);
if( !pGameCon )
{
if (m_nFarmGameindex != -1)
m_nFarmGameindex = -1;
return false;
}
m_nFarmGameindex = nServerID = pGameCon->GetGameID();
#if defined( PRE_ADD_FARM_DOWNSCALE )
return pGameCon->SendReqFarmRoomID(nFarmDBID, nMapID, nMaxUser, bStart, iAttr );
#elif defined( PRE_ADD_VIP_FARM )
return pGameCon->SendReqFarmRoomID(nFarmDBID, nMapID, nMaxUser, bStart, Attr );
#else
return pGameCon->SendReqFarmRoomID(nFarmDBID, nMapID, nMaxUser, bStart);
#endif // #if defined( PRE_ADD_FARM_DOWNSCALE )
}
void CDivisionManager::ExceptionPvPRoom(GAMASetRoomID* pMsg, USHORT& unVillageChannelID)
{
if (pMsg->cReqGameIDType != REQINFO_TYPE_PVP)
return;
CDNPvP* pPvPRoom = GetPvPRoomByIdx( static_cast<UINT>(pMsg->InstanceID) );
if (pPvPRoom)
{
unVillageChannelID = pPvPRoom->GetVillageChannelID();
UINT uiRoomState = pPvPRoom->GetRoomState();
UINT uiNewRoomState = uiRoomState&PvPCommon::RoomState::Password;
pPvPRoom->SetRoomState( uiNewRoomState );
g_Log.Log(LogType::_PVPROOM, g_Config.nWorldSetID, 0, 0, 0, L"ExceptionRoom [Index:%d][Room:%d][Event:%d] \r\n", pPvPRoom->GetIndex(), pPvPRoom->GetGameServerRoomIndex(), pPvPRoom->GetEventRoomIndex());
}
else
g_Log.Log(LogType::_PVPROOM, g_Config.nWorldSetID, 0, 0, 0, L"ExceptionRoom can't find PvPRoom [ID:%d] \r\n", pMsg->InstanceID);
}
bool CDivisionManager::SetGameRoom( CDNGameConnection* pGameCon, GAMASetRoomID* pMsg )
{
CDNVillageConnection* pVillageCon = GetVillageConnectionByVillageID(pMsg->cVillageID);
if( pVillageCon )
{
if (pMsg->iRoomID <= 0)
{
USHORT unVillageChannelID = 0;
ExceptionPvPRoom(pMsg, unVillageChannelID);
//게임서버에서 방생성 실패했삼!
#if defined( PRE_WORLDCOMBINE_PARTY )
#if defined( PRE_WORLDCOMBINE_PVP )
pVillageCon->SendSetGameID( pMsg->GameTaskType, pMsg->cReqGameIDType, pMsg->InstanceID, 0, 0, 0, pMsg->cServerIdx, pGameCon->GetGameID(), pMsg->iRoomID, unVillageChannelID, pMsg->cVillageID, -1, pMsg->Type, pMsg->eWorldReqType );
#else // #if defined( PRE_WORLDCOMBINE_PVP )
pVillageCon->SendSetGameID( pMsg->GameTaskType, pMsg->cReqGameIDType, pMsg->InstanceID, 0, 0, 0, pMsg->cServerIdx, pGameCon->GetGameID(), pMsg->iRoomID, unVillageChannelID, pMsg->cVillageID, -1, pMsg->Type );
#endif // #if defined( PRE_WORLDCOMBINE_PVP )
#else // #if defined( PRE_WORLDCOMBINE_PARTY )
pVillageCon->SendSetGameID( pMsg->GameTaskType, pMsg->cReqGameIDType, pMsg->InstanceID, 0, 0, 0, pMsg->cServerIdx, pGameCon->GetGameID(), pMsg->iRoomID, unVillageChannelID, pMsg->cVillageID, -1 );
#endif // #if defined( PRE_WORLDCOMBINE_PARTY )
return false;
}
if( pMsg->cReqGameIDType == REQINFO_TYPE_PARTY || pMsg->cReqGameIDType == REQINFO_TYPE_LADDER )
{
for( int i=0 ; i<_countof(pMsg->nRoomMember) ; ++i )
{
if( pMsg->nRoomMember[i] <= 0 )
continue;
if( VillageToGame( pVillageCon, pMsg->nRoomMember[i], pGameCon->GetGameID(), pMsg->iRoomID, pMsg->cServerIdx ) == false )
_DANGER_POINT(); //어어어어어 이거봐라...
}
char szIP[IPLENMAX] = {0,};
USHORT nPort, nTcpPort;
nPort = nTcpPort = 0;
if( GetGameInfoByID( pMsg->cGameID, pMsg->cServerIdx, szIP, &nPort, &nTcpPort ) == true )
{
if( pMsg->cReqGameIDType == REQINFO_TYPE_PARTY )
{
#if defined( PRE_WORLDCOMBINE_PARTY )
pVillageCon->SendSetGameID( pMsg->GameTaskType, pMsg->cReqGameIDType, pMsg->InstanceID, _inet_addr(szIP), nPort, nTcpPort, pMsg->cServerIdx, pGameCon->GetGameID(), pMsg->iRoomID, 0, pMsg->cVillageID, ERROR_NONE, pMsg->Type );
#else
pVillageCon->SendSetGameID( pMsg->GameTaskType, pMsg->cReqGameIDType, pMsg->InstanceID, _inet_addr(szIP), nPort, nTcpPort, pMsg->cServerIdx, pGameCon->GetGameID(), pMsg->iRoomID, 0, pMsg->cVillageID, ERROR_NONE );
#endif
}
else // REQINFO_TYPE_LADDER
{
const TPvPGameModeTable* pPvPGameModeTable = g_pExtManager->GetPvPGameModeTableByMatchType( pMsg->MatchType );
if( pPvPGameModeTable )
{
pGameCon->SendPvPLadderGameMode( pMsg, pPvPGameModeTable );
pVillageCon->SendLadderSetGameID( _inet_addr(szIP), nPort, nTcpPort, pMsg->cServerIdx, pGameCon->GetGameID(), pMsg->iRoomID, 0, pMsg->cVillageID, ERROR_NONE, pMsg, pPvPGameModeTable->nItemID );
}
else
{
GAMASetRoomID TempPacket;
memset( &TempPacket, 0, sizeof(TempPacket) );
for( int i=0 ; i<_countof(pMsg->nRoomMember) ; ++i )
{
if( pMsg->nRoomMember[i] <= 0 )
continue;
TempPacket.nRoomMember[i] = pMsg->nRoomMember[i];
}
pVillageCon->SendLadderSetGameID( 0, 0, 0, 0, 0, 0, 0, 0, -1, &TempPacket );
}
}
return true;
}
}
else if( pMsg->cReqGameIDType == REQINFO_TYPE_PVP )
{
#if defined( PRE_WORLDCOMBINE_PVP )
if( pMsg->eWorldReqType > WorldPvPMissionRoom::Common::NoneType )
{
return true;
}
#endif
CDNPvP* pPvPRoom = GetPvPRoomByIdx( static_cast<UINT>(pMsg->InstanceID) );
if( pPvPRoom )
{
if (pPvPRoom->GetEventRoomIndex() > 0)
g_Log.Log(LogType::_PVPROOM, g_Config.nWorldSetID, 0, 0, 0, L"SetGameRoom [Index:%d][Room:%d][Event:%d] \r\n", pPvPRoom->GetIndex(), pPvPRoom->GetGameServerRoomIndex(), pPvPRoom->GetEventRoomIndex());
pPvPRoom->SetAllRoomID( pVillageCon, pGameCon, pMsg->iRoomID, pMsg->cServerIdx );
char szIP[IPLENMAX] = {0,};
USHORT nPort, nTcpPort;
nPort = nTcpPort = 0;
if( GetGameInfoByID( pMsg->cGameID, pMsg->cServerIdx, szIP, &nPort, &nTcpPort ) == true )
{
pVillageCon->SendSetGameID( pMsg->GameTaskType, pMsg->cReqGameIDType, pMsg->InstanceID, _inet_addr(szIP), nPort, nTcpPort, pMsg->cServerIdx, pGameCon->GetGameID(), pMsg->iRoomID, pPvPRoom->GetVillageChannelID(), pMsg->cVillageID, ERROR_NONE );
return true;
}
}
else
_DANGER_POINT();
}
else if( pMsg->cReqGameIDType == REQINFO_TYPE_SINGLE || pMsg->cReqGameIDType == REQINFO_TYPE_PVP_BREAKINTO || pMsg->cReqGameIDType == REQINFO_TYPE_PARTY_BREAKINTO || pMsg->cReqGameIDType == REQINFO_TYPE_LADDER_OBSERVER )
{
if( VillageToGame( pVillageCon, static_cast<UINT>(pMsg->InstanceID), pGameCon->GetGameID(), pMsg->iRoomID, pMsg->cServerIdx ) == true )
{
if (pMsg->cReqGameIDType == REQINFO_TYPE_PARTY_BREAKINTO)
{
CDNUser * pBreakUser = GetUserByAccountDBID(static_cast<UINT>(pMsg->InstanceID));
if (pBreakUser)
{
pBreakUser->m_VillageCheckPartyID = pMsg->PartyIDForBreakInto;
}
else
_DANGER_POINT(); //여이가 유저가 없으면 문제가 있다!!!! 게임서버에는 정상 진입되어지지만 마을로 돌아갈경우(파티전체가)파티에 속하지 않는 것처럼 보임
}
char szIP[IPLENMAX] = {0,};
USHORT nPort, nTcpPort;
nPort = nTcpPort = 0;
if( GetGameInfoByID( pMsg->cGameID, pMsg->cServerIdx, szIP, &nPort, &nTcpPort ) == true )
{
pVillageCon->SendSetGameID( pMsg->GameTaskType, pMsg->cReqGameIDType, pMsg->InstanceID, _inet_addr(szIP), nPort, nTcpPort, pMsg->cServerIdx, pGameCon->GetGameID(), pMsg->iRoomID, 0, pMsg->cVillageID, ERROR_NONE );
return true;
}
}
}
else
_DANGER_POINT();
}
#if !defined( STRESS_TEST )
_DANGER_POINT();
#endif
return false;
}
bool CDivisionManager::SetTutorialGameRoom(int nLocalGameID, UINT nAccountDBID, int nGameID, int nServerIdx, int nRoomID, int nLoginServerID)
{
CDNUser * pUser = GetUserByAccountDBID(nAccountDBID);
if (!pUser) return false;
if (pUser->SetCheckGameInfo(nLocalGameID, nServerIdx) == false)
return false;
pUser->m_nRoomID = nRoomID;
char szIP[IPLENMAX] = {0,};
USHORT nPort, nTcpPort;
nPort = nTcpPort = 0;
if (GetGameInfoByID(nGameID, nServerIdx, szIP, &nPort, &nTcpPort) == true)
{
for (int nIndex = 0 ; LOGINCOUNTMAX > nIndex ; ++nIndex) {
CDNLoginConnection * pLoginCon = m_pLoginConnectionList[nIndex];
if (!pLoginCon) {
continue;
}
if (pLoginCon->GetServerID() == nLoginServerID) {
pLoginCon->SendSetTutorialGameID(pUser->GetSessionID(), _inet_addr(szIP), nPort, nTcpPort, nServerIdx, nLocalGameID, nRoomID, ERROR_NONE);
// break; // P.S.> 만약 ServerID 가 0 이라면 전부 찾아서 보내야 될 수도 있음 ???
}
}
return true;
}
for (int nIndex = 0 ; LOGINCOUNTMAX > nIndex ; ++nIndex) {
CDNLoginConnection * pLoginCon = m_pLoginConnectionList[nIndex];
if (!pLoginCon) {
continue;
}
if (pLoginCon->GetServerID() == nLoginServerID) {
pLoginCon->SendSetTutorialGameID(pUser->GetSessionID(), _inet_addr(szIP), nPort, nTcpPort, nServerIdx, nLocalGameID, nRoomID, ERROR_GENERIC_GAMECON_NOT_FOUND);
// break; // P.S.> 만약 ServerID 가 0 이라면 전부 찾아서 보내야 될 수도 있음 ???
}
}
return false;
}
#ifdef PRE_ADD_DOORS
int CDivisionManager::PrivateChat(UINT nSenderAccountDBID, const WCHAR * pReceiverName, char cType, const WCHAR * pChatMsg, int nLen, INT64 biDoorDestCharacterDBID)
#else //#ifdef PRE_ADD_DOORS
int CDivisionManager::PrivateChat(UINT nSenderAccountDBID, const WCHAR * pReceiverName, char cType, const WCHAR * pChatMsg, int nLen)
#endif //#ifdef PRE_ADD_DOORS
{
CDNUser * pSender = GetUserByAccountDBID(nSenderAccountDBID);
if (pSender == NULL) return ERROR_CHAT_USERNOTFOUND;
CDNUser * pReceiver = GetUserByName(pReceiverName);
if (pReceiver == NULL)
{
#ifdef PRE_ADD_DOORS
if (biDoorDestCharacterDBID > 0 && g_pDoorsConnection && g_pDoorsConnection->GetActive())
{
g_pDoorsConnection->SendChatToDoors(pSender, biDoorDestCharacterDBID, pChatMsg, nLen);
return ERROR_CHAT_MOBILESENDED;
}
#endif //#ifdef PRE_ADD_DOORS
return ERROR_CHAT_USERNOTFOUND;
}
#if defined(PRE_ADD_DWC)
if (pReceiver->GetCharacterAccountLevel() >= AccountLevel_New && pReceiver->GetCharacterAccountLevel() <= AccountLevel_QA)
return ERROR_CHAT_USERNOTFOUND;
#else
if (pReceiver->GetAccountLevel() >= AccountLevel_New && pReceiver->GetAccountLevel() <= AccountLevel_QA)
return ERROR_CHAT_USERNOTFOUND;
#endif
#if defined(PRE_ADD_DWC)
//같은 타입끼리만 대화 가능
if( (pReceiver->GetCharacterAccountLevel() == AccountLevel_DWC) ^ (cType == CHATTYPE_DWC_PRIVATE) )
return ERROR_CHAT_USERNOTFOUND;
if(cType == CHATTYPE_DWC_PRIVATE)
cType = CHATTYPE_PRIVATE; //귓속말로 전환해서 쏜다.
#endif
if (pReceiver->GetUserState() == STATE_VILLAGE)
{
CDNVillageConnection * pVillageCon = pReceiver->GetCurrentVillageConnection();
if (pVillageCon != NULL)
{
pVillageCon->SendPrivateChat(pReceiver->GetAccountDBID(), pSender->GetCharacterName(), cType, pChatMsg, nLen);
return ERROR_NONE;
}
}
else if (pReceiver->GetUserState() == STATE_GAME)
{
CDNGameConnection * pGameCon = pReceiver->GetCurrentGameConnection();
if (pGameCon != NULL)
{
pGameCon->SendPrivateChat(pReceiver->GetAccountDBID(), pSender->GetCharacterName(), cType, pChatMsg, nLen);
return ERROR_NONE;
}
}
return ERROR_CHAT;
}
int CDivisionManager::ZoneChat(UINT nSenderAccountDBID, const WCHAR * pChatMsg, int nLen, int nMapIdx)
{
CDNUser * pSender = GetUserByAccountDBID(nSenderAccountDBID);
if (pSender == NULL || nMapIdx == -1) return ERROR_CHAT_USERNOTFOUND;
std::vector <CDNVillageConnection*>::iterator ii;
for (ii = m_VillageServerConList.begin(); ii != m_VillageServerConList.end(); ii++)
{
if ((*ii)->HasManagedMapIdx(nMapIdx)) //맞으면 쏘세요~
(*ii)->SendZoneChat(nMapIdx, pSender->GetCharacterName(), pChatMsg, nLen);
}
return ERROR_CHAT;
}
#if defined(PRE_ADD_WORLD_MSG_RED)
int CDivisionManager::WorldChat(UINT nSenderAccountDBID, const WCHAR * pChatMsg, int nLen, char cChatType /*= CHATTYPE_WORLD */)
#else // #if defined(PRE_ADD_WORLD_MSG_RED)
int CDivisionManager::WorldChat(UINT nSenderAccountDBID, const WCHAR * pChatMsg, int nLen)
#endif // // #if defined(PRE_ADD_WORLD_MSG_RED)
{
//빌리지만 해당합니다 각 빌리지에 쏴악 쏩니다.
CDNUser * pSender = GetUserByAccountDBID(nSenderAccountDBID);
if (pSender == NULL) return ERROR_CHAT_USERNOTFOUND;
std::vector <CDNVillageConnection*>::iterator ii;
for (ii = m_VillageServerConList.begin(); ii != m_VillageServerConList.end(); ii++)
#if defined(PRE_ADD_WORLD_MSG_RED)
(*ii)->SendChat(cChatType, nSenderAccountDBID, pSender->GetCharacterName(), pChatMsg, nLen);
#else // #if defined(PRE_ADD_WORLD_MSG_RED)
(*ii)->SendChat(CHATTYPE_WORLD, nSenderAccountDBID, pSender->GetCharacterName(), pChatMsg, nLen);
#endif // #if defined(PRE_ADD_WORLD_MSG_RED)
vector<CDNGameConnection*>::iterator it;
for (it = m_GameServerConList.begin(); it != m_GameServerConList.end(); ++it)
#if defined(PRE_ADD_WORLD_MSG_RED)
(*it)->SendChat(cChatType, nSenderAccountDBID, pSender->GetCharacterName(), pChatMsg, nLen);
#else // #if defined(PRE_ADD_WORLD_MSG_RED)
(*it)->SendChat(CHATTYPE_WORLD, nSenderAccountDBID, pSender->GetCharacterName(), pChatMsg, nLen);
#endif // #if defined(PRE_ADD_WORLD_MSG_RED)
return ERROR_NONE;
}
int CDivisionManager::WorldSystemMsg(UINT nSenderAccountDBID, char cType, int nID, int nValue, WCHAR* pwszToCharacterName)
{
CDNUser *pSender = GetUserByAccountDBID(nSenderAccountDBID);
if (!pSender) return ERROR_CHAT_USERNOTFOUND;
vector<CDNVillageConnection*>::iterator iter;
for (iter = m_VillageServerConList.begin(); iter != m_VillageServerConList.end(); ++iter){
(*iter)->SendWorldSystemMsg(pSender->GetCharacterName(), cType, nID, nValue, pwszToCharacterName);
}
vector<CDNGameConnection*>::iterator it;
for (it = m_GameServerConList.begin(); it != m_GameServerConList.end(); ++it){
(*it)->SendWorldSystemMsg(pSender->GetCharacterName(), cType, nID, nValue, pwszToCharacterName);
}
return ERROR_NONE;
}
#ifdef PRE_ADD_DOORS
int CDivisionManager::DoorsChat(const WCHAR * pSenderName, INT64 biCharacterID, const WCHAR * pMessage, int nLen)
{
CDNUser *pReceiver = GetUserByCharacterDBID(biCharacterID);
if (!pReceiver) return ERROR_CHAT_USERNOTFOUND;
if (pReceiver->GetAccountLevel() >= AccountLevel_New && pReceiver->GetAccountLevel() <= AccountLevel_QA)
return ERROR_CHAT_USERNOTFOUND;
if (pReceiver->GetUserState() == STATE_VILLAGE)
{
CDNVillageConnection * pVillageCon = pReceiver->GetCurrentVillageConnection();
if (pVillageCon != NULL)
{
pVillageCon->SendPrivateChat(pReceiver->GetAccountDBID(), pSenderName, static_cast<char>(CHATTYPE_PRIVATE_MOBILE), pMessage, nLen);
return ERROR_NONE;
}
}
else if (pReceiver->GetUserState() == STATE_GAME)
{
CDNGameConnection * pGameCon = pReceiver->GetCurrentGameConnection();
if (pGameCon != NULL)
{
pGameCon->SendPrivateChat(pReceiver->GetAccountDBID(), pSenderName, static_cast<char>(CHATTYPE_PRIVATE_MOBILE), pMessage, nLen);
return ERROR_NONE;
}
}
return ERROR_NONE;
}
#ifdef PRE_ADD_DOORS_GUILDCHAT_DISCONNECT
int CDivisionManager::DoorsGuildChat(INT64 biCharacterID, int nGuildID, const WCHAR * pMessage, int nLen)
{
if (pMessage == NULL || biCharacterID <= 0) return ERROR_DB;
MADoorsGuildChat packet;
memset(&packet, 0, sizeof(MADoorsGuildChat));
packet.nManagedID = g_Config.nManagedID;
packet.GuildUID.Set(g_Config.nWorldSetID, static_cast<UINT>(nGuildID));
packet.nCharacterDBID = biCharacterID;
vector<CDNVillageConnection*>::iterator itorv;
for (itorv = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itorv ; ++itorv) {
(*itorv)->SendDoorsGuildChat(&packet);
}
// 전체 GA 에 송신
vector<CDNGameConnection*>::iterator itorg;
for (itorg = m_GameServerConList.begin() ; m_GameServerConList.end() != itorg ; ++itorg) {
(*itorg)->SendDoorsGuildChat(&packet);
}
return ERROR_NONE;
}
#endif //#ifdef PRE_ADD_DOORS_GUILDCHAT_DISCONNECT
#endif //#ifdef PRE_ADD_DOORS
#if defined( PRE_PRIVATECHAT_CHANNEL )
int CDivisionManager::PrivateChannelChat(UINT nSenderAccountDBID, const WCHAR * pChatMsg, int nLen, INT64 nChannelID)
{
CDNUser * pSender = GetUserByAccountDBID(nSenderAccountDBID);
if (pSender == NULL) return ERROR_CHAT_USERNOTFOUND;
std::vector <CDNVillageConnection*>::iterator ii;
for (ii = m_VillageServerConList.begin(); ii != m_VillageServerConList.end(); ii++)
(*ii)->SendPrivateChannelChat( pSender->GetCharacterName(), pChatMsg, nLen, nChannelID );
vector<CDNGameConnection*>::iterator it;
for (it = m_GameServerConList.begin(); it != m_GameServerConList.end(); ++it){
(*it)->SendPrivateChannelChat( pSender->GetCharacterName(), pChatMsg, nLen, nChannelID );
}
return ERROR_NONE;
}
#endif
CDNPvP* CDivisionManager::GetPvPRoom( const UINT uiAccountDBID )
{
CDNUser* pUser = GetUserByAccountDBID( uiAccountDBID );
if( pUser && pUser->GetPvPIndex() )
{
_TPvPMap::iterator itor = m_mPvP.find( pUser->GetPvPIndex() );
if( itor != m_mPvP.end() )
return (*itor).second;
}
return NULL;
}
short CDivisionManager::CreatePvPRoom( CDNVillageConnection* pVillageCon, const VIMAPVP_CREATEROOM* pPacket, UINT* nOutPvPIndex )
{
CDNUser* pUser = GetUserByAccountDBID( pPacket->uiCreateAccountDBID );
#if defined( PRE_PVP_GAMBLEROOM )
if( pUser || pPacket->nEventID > 0 || pPacket->nGuildDBID[0] > 0 || nOutPvPIndex != NULL || pPacket->cGambleType )
#else
if( pUser || pPacket->nEventID > 0 || pPacket->nGuildDBID[0] > 0 || nOutPvPIndex != NULL )
#endif
{
if( pUser && pPacket->nEventID > 0 )
return ERROR_PVP_CREATEROOM_FAILED;
// 위에서 한번 거르는데 여기 들어올 일은 없을듯..
//if( pUser == NULL && pPacket->nEventID <= 0 )
// return ERROR_PVP_CREATEROOM_FAILED;
// 유저가 이미 PvP 방에 있음
if( pUser )
{
if( pUser->GetPvPIndex() )
return ERROR_PVP_ALREADY_PVPROOM;
#if !defined(PRE_ADD_PVP_VILLAGE_ACCESS)
// PvP로비검사
if( !pUser->bIsPvPLobby() )
return ERROR_PVP_CREATEROOM_FAILED;
#endif // #if !defined(PRE_ADD_PVP_VILLAGE_ACCESS)
}
// 더이상 만들 수 없음
if( m_listPvPIndex.empty() )
return ERROR_PVP_CREATEROOM_FAILED;
// 이벤트방 중복생성 검사( 이벤트방은 이벤트때에만 호출되므로 또 Repository 만들기보단 걍 쌩으로 루프 검사한다. )
if( pPacket->nEventID > 0 )
{
for( std::map<UINT,CDNPvP*>::iterator itor=m_mPvP.begin() ; itor!=m_mPvP.end() ; ++itor )
{
if( (*itor).second->GetEventRoomIndex() <= 0 )
continue;
#ifdef PRE_ADD_COLOSSEUM_BEGINNER
if( (*itor).second->GetEventDataPtr()->nEventType1 == pPacket->EventData.nEventType1
&& (*itor).second->GetEventDataPtr()->nEventType2 == pPacket->EventData.nEventType2)
return ERROR_PVP_CREATEROOM_FAILED;
#else
if( (*itor).second->GetEventDataPtr()->nEventType2 == pPacket->EventData.nEventType2 )
return ERROR_PVP_CREATEROOM_FAILED;
#endif
}
}
UINT unPvPIndex = m_listPvPIndex.front();
std::map<UINT,CDNPvP*>::iterator itor = m_mPvP.find( unPvPIndex );
if( itor != m_mPvP.end() )
return ERROR_PVP_CREATEROOM_FAILED;
CDNPvP* pPvPRoom = new (std::nothrow) CDNPvP();
INT64 biRoomCreateCharacterDBID = 0;
if( pUser )
biRoomCreateCharacterDBID = pUser->GetCharacterDBID();
#ifdef PRE_MOD_PVPOBSERVER
bool bExtendObserver = false;
if( pUser )
{
if (pUser->GetAccountLevel() >= AccountLevel_New && pUser->GetAccountLevel() <= AccountLevel_QA)
{
if(pPacket->sCSPVP_CREATEROOM.cRoomPWLen > 0)
bExtendObserver = true;
}
}
if( pPvPRoom && pPvPRoom->bCreate( pVillageCon->GetVillageID(), unPvPIndex, pPacket, biRoomCreateCharacterDBID, bExtendObserver ) )
#else //#ifdef PRE_MOD_PVPOBSERVER
if( pPvPRoom && pPvPRoom->bCreate( pVillageCon->GetVillageID(), unPvPIndex, pPacket, biRoomCreateCharacterDBID, false ) )
#endif //#ifdef PRE_MOD_PVPOBSERVER
{
// PvP방 생성 성공
m_listPvPIndex.pop_front();
m_mPvP.insert( std::make_pair( unPvPIndex, pPvPRoom ) );
pVillageCon->SendPvPCreateRoom( ERROR_NONE, pPvPRoom, pPacket );
// 비밀방인경우
if( pPvPRoom->bIsPWRoom() )
pPvPRoom->SetRoomState( pPvPRoom->GetRoomState()|PvPCommon::RoomState::Password );
else
pPvPRoom->SetRoomState( pPvPRoom->GetRoomState() );
// 방 만든사람 조인
if( pUser )
{
int iUserState = PvPCommon::UserState::Captain;
if( pPvPRoom->GetGameMode() == PvPCommon::GameMode::PvP_AllKill )
iUserState |= PvPCommon::UserState::GroupCaptain;
#ifdef PRE_MOD_PVPOBSERVER
pPvPRoom->Join( pVillageCon, pUser, iUserState, bExtendObserver );
#else //#ifdef PRE_MOD_PVPOBSERVER
pPvPRoom->Join( pVillageCon, pUser, iUserState );
#endif //#ifdef PRE_MOD_PVPOBSERVER
#if defined(PRE_ADD_PVP_TOURNAMENT)
pUser->SetUserJob(pPacket->cCreateUserJob);
#endif
}
if( nOutPvPIndex != NULL )
*nOutPvPIndex = unPvPIndex;
return ERROR_NONE;
}
else
delete pPvPRoom;
}
else
_DANGER_POINT();
return ERROR_PVP_CREATEROOM_FAILED;
}
bool CDivisionManager::DestroyPvPGameRoom(const UINT uiPvPIndex)
{
_TPvPMap::iterator itor = m_mPvP.find(uiPvPIndex);
if (itor == m_mPvP.end())
return false;
CDNPvP * pPvPRoom = (*itor).second;
CDNVillageConnection* pVillageCon = GetVillageConnectionByVillageID( pPvPRoom->GetVillageID() );
pPvPRoom->bLeaveAll( pVillageCon, PvPCommon::LeaveType::DestroyRoom );
if( pVillageCon )
pVillageCon->SendPvPDestroyRoom( pPvPRoom->GetVillageChannelID(), pPvPRoom->GetIndex() );
if (pPvPRoom->GetEventRoomIndex() > 0)
g_Log.Log(LogType::_PVPROOM, g_Config.nWorldSetID, 0, 0, 0, L"DestroyPvPGameRoom [Index:%d][Room:%d][Event:%d] \r\n", pPvPRoom->GetIndex(), pPvPRoom->GetGameServerRoomIndex(), pPvPRoom->GetEventRoomIndex());
delete pPvPRoom;
m_mPvP.erase(itor);
return true;
}
short CDivisionManager::ModifyPvPRoom( CDNVillageConnection* pVillageCon, const VIMAPVP_MODIFYROOM* pPacket )
{
CDNUser* pUser = GetUserByAccountDBID( pPacket->uiAccountDBID );
if( pUser )
{
UINT uiPvPIndex = pUser->GetPvPIndex();
// PvP방에 있는지 검사
if( uiPvPIndex == 0 )
return ERROR_PVP_MODIFYROOM_FAILED;
std::map<UINT,CDNPvP*>::iterator itor = m_mPvP.find( uiPvPIndex );
if( itor == m_mPvP.end() )
return ERROR_PVP_MODIFYROOM_FAILED;
CDNPvP* pPvPRoom = (*itor).second;
//시스템에서 생성된 길드전은 편집할 수 없다
if (pPvPRoom->GetIsGuildWarSystem())
return ERROR_PVP_MODIFYROOM_FAILED;
// Event방은 편집 할 수 없다.
if( pPvPRoom->GetEventRoomIndex() > 0)
return ERROR_PVP_MODIFYROOM_FAILED;
#if defined( PRE_PVP_GAMBLEROOM )
if( pPvPRoom->GetGambleRoomType() > 0)
return ERROR_PVP_MODIFYROOM_FAILED;
#endif
// 방장인지 검사
if( !pPvPRoom->bIsCaptain( pPacket->uiAccountDBID) )
return ERROR_PVP_MODIFYROOM_FAILED;
// RoomState 검사
if( pPvPRoom->GetRoomState()&PvPCommon::RoomState::CantModifyRoom )
return ERROR_PVP_MODIFYROOM_FAILED;
pPvPRoom->ModifyRoom( pVillageCon, pPacket );
return ERROR_NONE;
}
else
_DANGER_POINT();
return ERROR_PVP_MODIFYROOM_FAILED;
}
void CDivisionManager::LeaveLadderSystem( UINT uiAccountDBID )
{
CDNUser* pUser = GetUserByAccountDBID( uiAccountDBID );
if( pUser == NULL )
return;
CDNVillageConnection* pVillageCon = GetVillageConnectionByVillageID( m_cPvPLobbyVillageID );
if( pVillageCon == NULL || pVillageCon->GetActive() == false )
return;
pVillageCon->SendLadderSystemDelUser( pUser );
}
void CDivisionManager::LeavePvPRoom( const UINT unAccountDBID, const bool bReq )
{
CDNUser* pUser = GetUserByAccountDBID( unAccountDBID );
if( pUser )
{
UINT uiPvPIndex = pUser->GetPvPIndex();
if( uiPvPIndex == 0 )
return;
// bRet == true : 정상적인 경우에는 유저의 State 를 체크한다.
if( bReq )
{
UINT uiPvPUserState = pUser->GetPvPUserState();
if( uiPvPUserState&PvPCommon::UserState::CantLeaveMask )
return;
}
std::map<UINT,CDNPvP*>::iterator itor = m_mPvP.find( uiPvPIndex );
if( itor == m_mPvP.end() )
{
_DANGER_POINT();
return;
}
CDNVillageConnection* pVillageCon = GetVillageConnectionByVillageID(GetPvPLobbyVillageID());
(*itor).second->bLeave( pVillageCon, pUser );
// Event방은 유저Leave 에 의해 파괴되지 않는다.
if( (*itor).second->GetEventRoomIndex() > 0)
return;
// 시스템에의해 생성된 길드전 방은 유저Leave 에 의해 파괴되지 않는다.
if ((*itor).second->GetIsGuildWarSystem())
return;
#if defined( PRE_PVP_GAMBLEROOM )
if ( (*itor).second->GetGambleRoomType() > 0 )
return;
#endif
// PvP방 파괴
if( (*itor).second->bIsEmpty(true) )
{
(*itor).second->bLeaveAll( pVillageCon, PvPCommon::LeaveType::DestroyRoom );
if( pVillageCon )
pVillageCon->SendPvPDestroyRoom( (*itor).second->GetVillageChannelID(), (*itor).second->GetIndex() );
delete (*itor).second;
m_mPvP.erase( itor );
}
}
else
_DANGER_POINT();
}
short CDivisionManager::JoinPvPRoom( CDNVillageConnection* pVillageCon, const VIMAPVP_JOINROOM* pPacket )
{
CDNUser* pUser = GetUserByAccountDBID( pPacket->uiAccountDBID );
if( pUser )
{
UINT uiPvPIndex = pUser->GetPvPIndex();
if( uiPvPIndex )
return ERROR_PVP_ALREADY_PVPROOM;
std::map<UINT,CDNPvP*>::iterator itor = m_mPvP.find( pPacket->sCSPVP_JOINROOM.uiPvPIndex );
if( itor == m_mPvP.end() )
return ERROR_PVP_JOINROOM_NOTFOUNDROOM;
#if !defined(PRE_ADD_PVP_VILLAGE_ACCESS)
// PvP로비검사
if( !pUser->bIsPvPLobby() )
return ERROR_PVP_JOINROOM_FAILED;
#endif //#if !defined(PRE_ADD_PVP_VILLAGE_ACCESS)
CDNPvP* pPvPRoom = (*itor).second;
// 방최대인원 검사
if( !pPvPRoom->bIsEmptySlot( pPacket->sCSPVP_JOINROOM.bIsObserver ) )
return ERROR_PVP_JOINROOM_MAXPLAYER;
// 추방유저 검사
if( pPvPRoom->bIsBanUser( pUser->GetSessionID()) )
return ERROR_PVP_JOINROOM_BANUSER;
// 관전 모드 일 경우에는 레벨제한 검사를 하지 않는다.
if( pPacket->sCSPVP_JOINROOM.bIsObserver == false )
{
if( !pPvPRoom->bIsAllowLevel( pPacket->cUserLevel) )
return ERROR_PVP_JOINROOM_LEVELLIMIT;
}
else
{
#ifdef PRE_MOD_PVPOBSERVER
if (pPvPRoom->bIsAllowObserver() == false)
return ERROR_PVP_JOINROOM_DONTALLOW_EVENTROOM_OBSERVER;
#else //PRE_MOD_PVPOBSERVER
// 이벤트방은 관전모드로 참관할 수 없다.
if( pPvPRoom->GetEventRoomIndex() > 0 )
return ERROR_PVP_JOINROOM_DONTALLOW_EVENTROOM_OBSERVER;
#endif //PRE_MOD_PVPOBSERVER
}
// 비밀번호 검사
if( pPvPRoom->bIsPWRoom() )
{
bool bCheck = true;
#ifdef PRE_MOD_PVPOBSERVER
if (pPvPRoom->bIsExtendObserver() && pPacket->sCSPVP_JOINROOM.bIsObserver)
bCheck = false;
#endif //#ifdef PRE_MOD_PVPOBSERVER
if( bCheck )
{
if( pPacket->sCSPVP_JOINROOM.cRoomPWLen == 0 || pPacket->sCSPVP_JOINROOM.cRoomPWLen > PvPCommon::TxtMax::RoomPW )
return ERROR_PVP_JOINROOM_INVALIDPW;
WCHAR wszPW[PvPCommon::TxtMax::RoomPW+1];
memset( wszPW, 0, (PvPCommon::TxtMax::RoomPW+1)*sizeof(WCHAR) );
wcsncpy( wszPW, pPacket->sCSPVP_JOINROOM.wszRoomPW, pPacket->sCSPVP_JOINROOM.cRoomPWLen );
if( !pPvPRoom->bIsCheckPW( wszPW ) )
return ERROR_PVP_JOINROOM_INVALIDPW;
}
}
if (pPvPRoom->GetGameMode() == PvPCommon::GameMode::PvP_GuildWar)
{
if (pPvPRoom->GetIsGuildWarSystem())
{
//시스템에서 생성되어진 길드전일경우 관전입장은 운영자만 가능하다
if (pPacket->sCSPVP_JOINROOM.bIsObserver && pUser->GetAccountLevel() < AccountLevel_New)
return ERROR_PVP_JOINROOM_FAILED;
}
}
#if defined(PRE_ADD_PVP_TOURNAMENT)
pUser->SetUserJob(pPacket->cUserJob);
#endif
return pPvPRoom->Join( pVillageCon, pUser, PvPCommon::UserState::None, pPacket->sCSPVP_JOINROOM.bIsObserver, pPacket->sCSPVP_JOINROOM.nGuildDBID );
}
else
_DANGER_POINT();
return ERROR_NONE;
}
short CDivisionManager::RandomJoinPvPRoom( CDNVillageConnection* pVillageCon, const VIMAPVP_RANDOMJOINROOM* pPacket )
{
CDNUser* pUser = GetUserByAccountDBID( pPacket->uiAccountDBID );
if( pUser )
{
UINT uiPvPIndex = pUser->GetPvPIndex();
if( uiPvPIndex )
return ERROR_PVP_ALREADY_PVPROOM;
#if !defined(PRE_ADD_PVP_VILLAGE_ACCESS)
// PvP로비검사
if( !pUser->bIsPvPLobby() )
return ERROR_PVP_JOINROOM_FAILED;
#endif
// 0.PvP방 없는 경우 예외처리
if( m_mPvP.empty() )
return ERROR_PVP_JOINROOM_FAILED;
// 1.랜덤하게 방하나 뽑아보기
size_t AdvanceOffset = rand()%m_mPvP.size();
std::map<UINT,CDNPvP*>::iterator itor = m_mPvP.begin();
std::advance( itor, AdvanceOffset );
CDNPvP* pPvPRoom = (*itor).second;
// 빈자리가 있고 추방유저가 아니고 비밀방이 아니라면 조인시켜준다.
if( pPvPRoom->bIsEmptySlot() && !pPvPRoom->bIsPWRoom() && !pPvPRoom->bIsBanUser( pUser->GetSessionID() ) )
{
#if defined( PRE_PVP_GAMBLEROOM )
if( pPvPRoom->bIsAllowLevel( pPacket->cUserLevel) && pPvPRoom->GetEventRoomIndex() <= 0 && pPvPRoom->GetGambleRoomType() <= 0 )
#else
if( pPvPRoom->bIsAllowLevel( pPacket->cUserLevel) && pPvPRoom->GetEventRoomIndex() <= 0 )
#endif
return pPvPRoom->Join( pVillageCon, pUser, PvPCommon::UserState::None );
}
// 2.순차적으로 방검사
for( itor=m_mPvP.begin() ; itor!=m_mPvP.end() ; ++itor )
{
CDNPvP* pPvPRoom = (*itor).second;
#if defined( PRE_ADD_PVP_COMBOEXERCISE )
if( pPvPRoom->GetGameMode() == PvPCommon::GameMode::PvP_ComboExercise )
{
continue;
}
#endif // #if defined( PRE_ADD_PVP_COMBOEXERCISE )
// 빈자리가 있고 추방유저가 아니고 비밀방이 아니라면 조인시켜준다.
if( pPvPRoom->bIsEmptySlot() && !pPvPRoom->bIsPWRoom() && !pPvPRoom->bIsBanUser( pUser->GetSessionID() ) )
{
#if defined( PRE_PVP_GAMBLEROOM )
if( pPvPRoom->bIsAllowLevel( pPacket->cUserLevel) && pPvPRoom->GetEventRoomIndex() <= 0 && pPvPRoom->GetGambleRoomType() <= 0 )
#else
if( pPvPRoom->bIsAllowLevel( pPacket->cUserLevel) && pPvPRoom->GetEventRoomIndex() <= 0 )
#endif
return pPvPRoom->Join( pVillageCon, pUser, PvPCommon::UserState::None );
}
}
}
else
_DANGER_POINT();
return ERROR_PVP_JOINROOM_FAILED;
}
void CDivisionManager::ChangePvPTeam( CDNVillageConnection* pVillageCon, const VIMAPVP_CHANGETEAM* pPacket )
{
// RoomState검사
CDNUser* pUser = GetUserByAccountDBID( pPacket->uiAccountDBID );
if( pUser )
{
UINT uiPvPIndex = pUser->GetPvPIndex();
if( uiPvPIndex == 0 )
return;
std::map<UINT,CDNPvP*>::iterator itor = m_mPvP.find( uiPvPIndex );
if( itor == m_mPvP.end() )
return;
CDNPvP* pPvPRoom = (*itor).second;
if( pPvPRoom->GetEventRoomIndex() > 0 )
return;
#if defined( PRE_PVP_GAMBLEROOM )
if( pPvPRoom->GetGambleRoomType() > 0 )
return;
#endif
// 길드전(점령전)일 경우 무조건 팀변경 불가능으로 변경되었다. 34361이슈
if (pPvPRoom->GetGameMode() == PvPCommon::GameMode::PvP_GuildWar)
{
if (pPvPRoom->GetIsGuildWarSystem())
return;
}
#ifdef PRE_MOD_PVPOBSERVER
if (pPvPRoom->bIsExtendObserver())
{
if( pUser->bIsObserver() || (pUser->bIsObserver() == false && pPacket->sCSPVP_CHANGETEAM.usTeam == PvPCommon::Team::Observer) )
return;
}
#endif //#ifdef PRE_MOD_PVPOBSERVER
switch( pPvPRoom->GetGameMode() )
{
// 개인전은 팀변경이 되지 않는다.
case PvPCommon::GameMode::PvP_IndividualRespawn:
#if defined(PRE_ADD_PVP_TOURNAMENT)
case PvPCommon::GameMode::PvP_Tournament:
#endif //#if defined(PRE_ADD_PVP_TOURNAMENT)
#if defined( PRE_ADD_PVP_COMBOEXERCISE )
case PvPCommon::GameMode::PvP_ComboExercise:
#endif // #if defined( PRE_ADD_PVP_COMBOEXERCISE )
{
// 옵셔버 <-> 팀간 이동은 가능
if( pUser->bIsObserver() || (pUser->bIsObserver()==false && pPacket->sCSPVP_CHANGETEAM.usTeam == PvPCommon::Team::Observer) )
break;
return;
}
}
// 레뒤상태에서는 팀이동 불가
if( pUser->GetPvPUserState()&PvPCommon::UserState::Ready )
return;
// PvPCommon::UserState::Starting|PvPCommon::UserState::Syncing|PvPCommon::UserState::Playing 에서 팀이동 불가
if( pUser->GetPvPUserState()&(PvPCommon::UserState::Starting|PvPCommon::UserState::Syncing|PvPCommon::UserState::Playing) )
return;
// 팀 값 확인
if( !PvPCommon::CheckTeam( pPacket->sCSPVP_CHANGETEAM.usTeam ) || pUser->GetPvPTeam() == pPacket->sCSPVP_CHANGETEAM.usTeam )
return;
#if defined(PRE_ADD_PVP_TOURNAMENT)
if( pPvPRoom->IsMode( PvPCommon::GameMode::PvP_Tournament) == true )
{
if( pPacket->sCSPVP_CHANGETEAM.usTeam == PvPCommon::Team::Observer ) // 옵저버 일때만 검사..다른넘은 밑에서 검사.
{
// 옮길 팀 여유 슬롯 있는지 검사
if( !pPvPRoom->bIsEmptyTeamSlot( pPacket->sCSPVP_CHANGETEAM.usTeam ) )
{
pVillageCon->SendPvPChangeTeam( ERROR_PVP_CANTCHANGETEAM_NOSLOT, pPvPRoom->GetVillageChannelID(), uiPvPIndex, pPacket );
return;
}
}
}
else
#endif
{
// 옮길 팀 여유 슬롯 있는지 검사
if( !pPvPRoom->bIsEmptyTeamSlot( pPacket->sCSPVP_CHANGETEAM.usTeam ) )
{
pVillageCon->SendPvPChangeTeam( ERROR_PVP_CANTCHANGETEAM_NOSLOT, pPvPRoom->GetVillageChannelID(), uiPvPIndex, pPacket );
return;
}
}
// 관전모드에서 게임참여로 옮길경우 레벨 제한 체크
if( pUser->GetPvPTeam() == PvPCommon::Team::Observer && pPacket->sCSPVP_CHANGETEAM.usTeam <= PvPCommon::Team::B )
{
if( pPvPRoom->bIsAllowLevel( pPacket->cUserLevel) == false )
{
pVillageCon->SendPvPChangeTeam( ERROR_PVP_CANTCHANGETEAM_LEVELLIMIT, pPvPRoom->GetVillageChannelID(), uiPvPIndex, pPacket );
return;
}
}
// Observer 슬롯으로 변경하는 거고 방장이라면...
if( pPacket->sCSPVP_CHANGETEAM.usTeam == PvPCommon::Team::Observer && pPvPRoom->bIsCaptain( pPacket->uiAccountDBID ) )
{
// 새로운 방장으로 변경
UINT uiNewCaptain = pPvPRoom->FindNewCaptain();
if( uiNewCaptain == 0 )
{
pVillageCon->SendPvPChangeTeam( ERROR_PVP_CANTCHANGETEAM_CHANGECAPTAIN_FAILED, pPvPRoom->GetVillageChannelID(), uiPvPIndex, pPacket );
return;
}
pPvPRoom->ChangeCaptain( pVillageCon, uiNewCaptain );
}
char cTeamSlotIndex = -1;
if( pPvPRoom->IsMode( PvPCommon::GameMode::PvP_GuildWar) == true )
{
if(pPvPRoom->bIsGuildWarGrade(pPacket->uiAccountDBID, PvPCommon::UserState::GuildWarCaptain|PvPCommon::UserState::GuildWarSedcondCaptain))
{
UINT uiPvPState = pUser->GetPvPUserState();
uiPvPState &= ~PvPCommon::UserState::GuildWarCaptain;
uiPvPState &= ~PvPCommon::UserState::GuildWarSedcondCaptain;
pPvPRoom->SetPvPUserState(pUser, uiPvPState);
}
pPvPRoom->SetPvPMemberIndex(pUser->GetPvPTeam(), pUser->GetAccountDBID());
if (pPacket->sCSPVP_CHANGETEAM.usTeam != PvPCommon::Team::Observer)
{
pPvPRoom->GetAndSetRemainTeamIndex(pPacket->sCSPVP_CHANGETEAM.usTeam, pUser->GetAccountDBID(), cTeamSlotIndex);
}
}
#if defined(PRE_ADD_PVP_TOURNAMENT)
if( pPvPRoom->IsMode( PvPCommon::GameMode::PvP_Tournament) == true )
{
if (pPacket->sCSPVP_CHANGETEAM.usTeam == PvPCommon::Team::Observer)
pPvPRoom->DelTournamentIndex(pPacket->uiAccountDBID);
else
{
cTeamSlotIndex = pPvPRoom->GetTournamentIndex(pPacket->uiAccountDBID);
if( cTeamSlotIndex != -1)
pUser->SetPvPTeam(cTeamSlotIndex%2==0? PvPCommon::Team::A : PvPCommon::Team::B);
else
{
pVillageCon->SendPvPChangeTeam( ERROR_PVP_CANTCHANGETEAM_NOSLOT, pPvPRoom->GetVillageChannelID(), uiPvPIndex, pPacket );
return;
}
}
}
#endif //#if defined(PRE_ADD_PVP_TOURNAMENT)
if( pPvPRoom->IsMode( PvPCommon::GameMode::PvP_AllKill ) == true )
{
if( pUser->GetPvPUserState()&PvPCommon::UserState::GroupCaptain )
pPvPRoom->SetPvPUserState( pUser, pUser->GetPvPUserState()&~PvPCommon::UserState::GroupCaptain );
}
// 팀변경
pUser->SetPvPTeam( pPacket->sCSPVP_CHANGETEAM.usTeam );
pPvPRoom->CheckAndSetGroupCaptain();
if( pPvPRoom->IsMode( PvPCommon::GameMode::PvP_GuildWar ) == true )
{
if (pUser->GetPvPTeam() != PvPCommon::Team::Observer)
{
for (int i = 0; i < PvPCommon::TeamIndex::Max; i++)
{
if (pPvPRoom->GetUserCountByState(i == 0 ? PvPCommon::Team::A : PvPCommon::Team::B, PvPCommon::UserState::GuildWarCaptain) <= 0)
{
UINT nNewGuildWarCaptain = pPvPRoom->SelectNewGuildWarCaptain(i == 0 ? PvPCommon::Team::A : PvPCommon::Team::B);
pPvPRoom->SetPvPGuildWarMemberGrade(i == 0 ? PvPCommon::Team::A : PvPCommon::Team::B, true, PvPCommon::UserState::GuildWarCaptain, nNewGuildWarCaptain);
}
}
}
}
// 패킷 전송
pVillageCon->SendPvPChangeTeam( ERROR_NONE, pPvPRoom->GetVillageChannelID(), uiPvPIndex, pPacket, cTeamSlotIndex );
}
}
void CDivisionManager::BanPvPRoom( CDNVillageConnection* pVillageCon, const VIMAPVP_BAN* pPacket )
{
CDNPvP* pPvPRoom = GetPvPRoom( pPacket->uiAccountDBID );
if( !pPvPRoom )
return;
pPvPRoom->BanPvPRoom( pVillageCon, pPacket );
}
void CDivisionManager::EnterLobby( CDNVillageConnection* pVillageCon, const VIMAPVP_ENTERLOBBY* pPacket )
{
CDNUser* pUser = GetUserByAccountDBID( pPacket->uiAccountDBID );
if( pUser )
{
#if defined(PRE_ADD_PVP_VILLAGE_ACCESS)
if( pUser->GetLadderMatchType() != LadderSystem::MatchType::None)
{
VIMALadderEnterChannel LadderEnterChannel;
memset(&LadderEnterChannel, 0, sizeof(LadderEnterChannel));
LadderEnterChannel.MatchType = pUser->GetLadderMatchType();
LadderEnterChannel.uiAccountDBID = pPacket->uiAccountDBID;
pVillageCon->AddSendData( MAVI_LADDERSYSTEM_ENTERCHANNEL, 0, (char*)&LadderEnterChannel, sizeof(LadderEnterChannel));
pUser->SetLadderMatchType(LadderSystem::MatchType::None);
return;
}
#endif
UINT uiPvPIndex = pUser->GetPvPIndex();
if( uiPvPIndex == 0 )
{
VIMAPVP_ROOMLIST RoomList;
memset( &RoomList, 0, sizeof(RoomList) );
RoomList.uiAccountDBID = pPacket->uiAccountDBID;
RoomList.unVillageChannelID = pPacket->unVillageChannelID;
RoomList.sCSPVP_ROOMLIST.uiPage = 0;
RoomList.sCSPVP_ROOMLIST.cIsAscend = 1;
pVillageCon->SendPvPRoomList( &RoomList );
return;
}
#if defined( PRE_WORLDCOMBINE_PVP )
if( uiPvPIndex > WorldPvPMissionRoom::Common::WorldPvPRoomStartIndex )
{
pVillageCon->SendPvPJoinRoom(ERROR_NONE, pPacket->uiAccountDBID, pPacket->unVillageChannelID, uiPvPIndex, pUser->GetPvPTeam(), pUser->GetPvPUserState(), -1);
return;
}
#endif
std::map<UINT,CDNPvP*>::iterator itor = m_mPvP.find( uiPvPIndex );
if( itor == m_mPvP.end() )
return;
CDNPvP* pPvPRoom = (*itor).second;
if( pPvPRoom->bIsCheckUser( pPacket->uiAccountDBID ) )
{
char cIndex = -1;
#if defined(PRE_ADD_PVP_TOURNAMENT)
if( pPvPRoom->IsMode(PvPCommon::GameMode::PvP_Tournament) == true )
cIndex = pPvPRoom->FindTournamentIndex(pPacket->uiAccountDBID);
#endif // #if defined(PRE_ADD_PVP_TOURNAMENT)
if( pPvPRoom->IsMode(PvPCommon::GameMode::PvP_GuildWar) == true )
cIndex = pPvPRoom->GetPvPTeamIndex(pUser);
pVillageCon->SendPvPJoinRoom(ERROR_NONE, pPacket->uiAccountDBID, pPvPRoom->GetVillageChannelID(), uiPvPIndex, pUser->GetPvPTeam(), pUser->GetPvPUserState(), cIndex);
// 방장이양
UINT uiRoomState = pPvPRoom->GetRoomState();
if( uiRoomState&PvPCommon::RoomState::Playing )
{
// 게임모드가 끝났으면 방장이양하지 않는다.
if( uiRoomState&PvPCommon::RoomState::Finished )
return;
// 로비로 돌아온 캐릭터가 방장인지 검사
if( pPvPRoom->bIsCaptain( pPacket->uiAccountDBID ) )
{
#ifdef PRE_MOD_PVPOBSERVER
if (pPvPRoom->bIsExtendObserver() == false)
{
UINT uiNewCaptain = pPvPRoom->FindNewCaptain();
pPvPRoom->ChangeCaptain( pVillageCon, uiNewCaptain );
}
#else //#ifdef PRE_MOD_PVPOBSERVER
UINT uiNewCaptain = pPvPRoom->FindNewCaptain();
pPvPRoom->ChangeCaptain( pVillageCon, uiNewCaptain );
#endif //#ifdef PRE_MOD_PVPOBSERVER
}
//로비로 돌아온 캐릭터가 길드전 대장 또는 부대장인지 검사
if (pPvPRoom->bIsGuildWarGrade(pPacket->uiAccountDBID, PvPCommon::UserState::GuildWarCaptain))
{
if (pPvPRoom->GetUserCountByTeam(pUser->GetPvPTeam()) > 1)
{
UINT nPvPState = pUser->GetPvPUserState();
nPvPState &= ~PvPCommon::UserState::GuildWarCaptain;
UINT nNewGuildWarCaptain = pPvPRoom->SelectNewGuildWarCaptain(pUser->GetPvPTeam(), pUser->GetSessionID());
pPvPRoom->SetPvPGuildWarMemberGrade(pUser->GetPvPTeam(), true, PvPCommon::UserState::GuildWarCaptain, nNewGuildWarCaptain);
if (g_pDivisionManager)
{
CDNUser * pNewGuildWarCaptain = g_pDivisionManager->GetUserBySessionID(nNewGuildWarCaptain);
if (pNewGuildWarCaptain)
{
CDNGameConnection * pGameCon = g_pDivisionManager->GetGameConnectionByGameID(pNewGuildWarCaptain->GetGameID());
if (pGameCon)
{
//변경을 알린다.
pGameCon->SendPvPMemberGrade(pNewGuildWarCaptain->GetAccountDBID(), pNewGuildWarCaptain->GetPvPTeam(), pNewGuildWarCaptain->GetPvPUserState(), nNewGuildWarCaptain, ERROR_NONE);
}
else
_DANGER_POINT();
}
else
_DANGER_POINT();
}
pPvPRoom->SetPvPUserState(pUser, nPvPState);
}
}
if (pPvPRoom->bIsGuildWarGrade(pPacket->uiAccountDBID, PvPCommon::UserState::GuildWarSedcondCaptain))
{
UINT nPvPState = pUser->GetPvPUserState();
nPvPState &= ~PvPCommon::UserState::GuildWarSedcondCaptain;
pPvPRoom->SetPvPUserState(pUser, nPvPState);
}
}
}
}
else
_DANGER_POINT();
}
void CDivisionManager::ChangePvPRoomCaptain( CDNVillageConnection* pVillageCon, const VIMAPVP_CHANGECAPTAIN* pPacket )
{
if( pPacket->sCSPVP_CHANGECAPTAIN.Type == PvPCommon::CaptainType::Captain )
{
CDNUser* pUser = GetUserByAccountDBID( pPacket->uiAccountDBID );
if( pUser )
{
UINT uiPvPIndex = pUser->GetPvPIndex();
if( uiPvPIndex == 0 )
return;
std::map<UINT,CDNPvP*>::iterator itor = m_mPvP.find( uiPvPIndex );
if( itor == m_mPvP.end() )
return;
CDNPvP* pPvPRoom = (*itor).second;
if( !pPvPRoom->bIsCaptain( pPacket->uiAccountDBID ) )
return;
CDNUser* pNewUser = pPvPRoom->GetUserBySessionID( pPacket->sCSPVP_CHANGECAPTAIN.uiNewCaptainSessionID );
if( !pNewUser || pNewUser->GetAccountDBID() == pPacket->uiAccountDBID )
return;
if( pNewUser->GetPvPTeam() == PvPCommon::Team::Observer )
return;
pPvPRoom->ChangeCaptain( pVillageCon, pNewUser->GetAccountDBID() );
}
}
else if( pPacket->sCSPVP_CHANGECAPTAIN.Type == PvPCommon::CaptainType::GroupCaptain )
{
CDNUser* pUser = GetUserByAccountDBID( pPacket->uiAccountDBID );
if( pUser )
{
USHORT nTeam = pUser->GetPvPTeam();
UINT uiPvPIndex = pUser->GetPvPIndex();
if( uiPvPIndex == 0 )
return;
std::map<UINT,CDNPvP*>::iterator itor = m_mPvP.find( uiPvPIndex );
if( itor == m_mPvP.end() )
return;
CDNPvP* pPvPRoom = (*itor).second;
if( pPvPRoom->IsMode(PvPCommon::GameMode::PvP_AllKill) == false )
return;
if( !pPvPRoom->bIsGroupCaptain( pPacket->uiAccountDBID ) )
return;
CDNUser* pNewUser = pPvPRoom->GetUserBySessionID( pPacket->sCSPVP_CHANGECAPTAIN.uiNewCaptainSessionID );
if( !pNewUser || pNewUser->GetAccountDBID() == pPacket->uiAccountDBID )
return;
if( pNewUser->GetPvPTeam() == PvPCommon::Team::Observer )
return;
if( pNewUser->GetPvPTeam() != nTeam )
return;
pPvPRoom->ChangeGroupCaptain( pNewUser->GetAccountDBID(), nTeam );
}
}
}
void CDivisionManager::ReadyPvP( CDNVillageConnection* pVillageCon, VIMAPVP_READY* pPacket )
{
CDNUser* pUser = GetUserByAccountDBID( pPacket->uiAccountDBID );
if( pUser )
{
UINT uiPvPIndex = pUser->GetPvPIndex();
if( uiPvPIndex == 0 )
return;
std::map<UINT,CDNPvP*>::iterator itor = m_mPvP.find( uiPvPIndex );
if( itor == m_mPvP.end() )
return;
CDNPvP* pPvPRoom = (*itor).second;
pPvPRoom->ReadyUser( pVillageCon, pPacket );
}
else
_DANGER_POINT();
}
short CDivisionManager::StartPvP( CDNVillageConnection* pVillageCon, VIMAPVP_START* pPacket, bool bFromUser/* = false*/ )
{
CDNUser* pUser = GetUserByAccountDBID( pPacket->uiAccountDBID );
if( pUser )
{
UINT uiPvPIndex = pUser->GetPvPIndex();
if( uiPvPIndex == 0 )
return ERROR_PVP_STARTPVP_FAILED;
std::map<UINT,CDNPvP*>::iterator itor = m_mPvP.find( uiPvPIndex );
if( itor == m_mPvP.end() )
return ERROR_PVP_STARTPVP_FAILED;
CDNPvP* pPvPRoom = (*itor).second;
if (pPvPRoom->GetIsGuildWarSystem() && bFromUser && !(pPvPRoom->GetRoomState()&PvPCommon::RoomState::Playing) )
return ERROR_PVP_STARTPVP_FAILED; //시스템에서 생성한 피빕은 시스템에서만 시작할 수 있다
return pPvPRoom->StartPvP( pVillageCon, pPacket );
}
else
_DANGER_POINT();
return ERROR_PVP_STARTPVP_FAILED;
}
bool CDivisionManager::ForceStopPvP(const UINT uiPvPIndex, const WCHAR * pGuildName/* = NULL*/)
{
CDNPvP * pPvP = GetPvPRoomByIdx(uiPvPIndex);
if (pPvP)
{
bool bRet = false;
int nGameID = pPvP->GetGameServerID();
int nGameRoomID = pPvP->GetGameServerRoomIndex();
UINT nForceWinGuildDBID = 0;
if (nGameID > 0 && nGameRoomID > 0)
{
if (pGuildName && wcslen(pGuildName) > 0)
{
nForceWinGuildDBID = g_pGuildWarManager->GetGuildDBIDWithFinal(uiPvPIndex, pGuildName);
if (nForceWinGuildDBID > 0)
bRet = true;
}
else
bRet = true;
if (bRet)
{
CDNGameConnection * pGameCon = GetGameConnectionByGameID(nGameID);
if (pGameCon)
{
//게임서버에 강제파괴를 알리고
bRet = pGameCon->SendForceStopPvP(nGameRoomID, nForceWinGuildDBID);
if (bRet == false)
{
//error
}
}
}
}
if (bRet)
{
//PvPRoom을 정리한다.
SetDestroyPvPGameRoom(uiPvPIndex, nGameRoomID);
//만약 삭제처리하는 PvPRoom이 Guildwarsystem방이라면 SetDestroyPvPGameRoom이후에는 pPvPRoom은 유효하지 않다. 주의!!
return true;
}
}
return false;
}
void CDivisionManager::SetPvPFatigueOption(const VIMAPVP_FATIGUE_OPTION* pPacket )
{
CDNUser* pUser = GetUserByAccountDBID( pPacket->uiAccountDBID );
if( pUser )
pUser->SetPvPFatigue(pPacket->bFatigueOption);
else
_DANGER_POINT();
}
bool CDivisionManager::SetGuildWarMemberGrade(UINT nAccountDBID, bool bAsign, USHORT nType, UINT nTargetSessionID, USHORT &nOutUserState, USHORT &nTeam)
{
bool bRet = false;
// 유저 검사
CDNUser* pUser = GetUserByAccountDBID(nAccountDBID);
if( !pUser )
return bRet;
// PvP 방에 없음
UINT uiPvPIndex = pUser->GetPvPIndex();
if( uiPvPIndex == 0 )
return bRet;
CDNPvP* pPvPRoom = GetPvPRoomByIdx(uiPvPIndex);
if (pPvPRoom == NULL)
return bRet;
if (!(pUser->GetPvPUserState()&PvPCommon::UserState::GuildWarCaptain))
return bRet;
nTeam = pUser->GetPvPTeam();
int nRet = pPvPRoom->SetPvPGuildWarMemberGrade(pUser->GetPvPTeam(), bAsign, nType, nTargetSessionID);
CDNUser * pTargetUser = NULL;
if (nRet == ERROR_NONE)
{
pTargetUser = GetUserBySessionID(nTargetSessionID);
if (pTargetUser)
nOutUserState = pTargetUser->GetPvPUserState();
else
return false;
}
return nRet == ERROR_NONE ? true : false;
}
bool CDivisionManager::SetPvPMemberIndex(UINT nAccountDBID, BYTE cCount, const TSwapMemberIndex * pIndex, USHORT &nTeam)
{
bool bRet = false;
// 유저 검사
CDNUser* pUser = GetUserByAccountDBID(nAccountDBID);
if( !pUser )
return bRet;
// PvP 방에 없음
UINT uiPvPIndex = pUser->GetPvPIndex();
if( uiPvPIndex == 0 )
return bRet;
CDNPvP* pPvPRoom = GetPvPRoomByIdx(uiPvPIndex);
if (pPvPRoom == NULL)
return bRet;
if (!(pUser->GetPvPUserState()&PvPCommon::UserState::GuildWarCaptain))
return bRet;
nTeam = pUser->GetPvPTeam();
bRet = pPvPRoom->SwapPvPMemberIndex(pUser->GetPvPTeam(), cCount, pIndex);
return bRet;
}
#ifdef PRE_ADD_COLOSSEUM_BEGINNER
void CDivisionManager::SetPvPChangeChannel(CDNVillageConnection * pVillageCon, const PVP_CHANGECHANNEL * pChange)
{
if (pVillageCon == NULL) return;
CDNUser * pUser = GetUserByAccountDBID(pChange->nAccountDBID);
if (pUser)
{
#if defined(PRE_ADD_DWC)
if( pUser->GetCharacterAccountLevel() == AccountLevel_DWC )
{
if( pChange->cType == PvPCommon::RoomType::dwc )
{
pUser->SetPvPChannelType(pChange->cType);
if (pChange->bSend)
pVillageCon->SendPvPChangeChannelResult(pChange->nAccountDBID, static_cast<BYTE>(pUser->GetPvPChannelType()), ERROR_NONE);
return;
}
_DANGER_POINT();
}
else{
if( pChange->cType == PvPCommon::RoomType::dwc ) // 일반계정은 dwc 채널로 가면 안됨
{
_DANGER_POINT();
return;
}
#endif
if (pChange->cPvPLevel < pChange->cSeperateLevel)
{
//초짜인 친구 어디로가든 오케이!
pUser->SetPvPChannelType(pChange->cType);
if (pChange->bSend)
pVillageCon->SendPvPChangeChannelResult(pChange->nAccountDBID, static_cast<BYTE>(pUser->GetPvPChannelType()), ERROR_NONE);
return;
}
else if (pChange->cPvPLevel >= pChange->cSeperateLevel)
{
//상급자!는 일반채널만 가능
if (static_cast<PvPCommon::RoomType::eRoomType>(pChange->cPvPLevel) == PvPCommon::RoomType::regular)
{
pUser->SetPvPChannelType(pChange->cType);
if (pChange->bSend)
pVillageCon->SendPvPChangeChannelResult(pChange->nAccountDBID, static_cast<BYTE>(pUser->GetPvPChannelType()), ERROR_NONE);
return;
}
_DANGER_POINT();
}
#if defined(PRE_ADD_DWC)
}
#endif
_DANGER_POINT();
}
_DANGER_POINT();
}
#endif //#ifdef PRE_ADD_COLOSSEUM_BEGINNER
#if defined(PRE_ADD_PVP_TOURNAMENT)
bool CDivisionManager::SwapTournamentIndex(UINT nAccountDBID, char cSourceIndex, char cDestIndex)
{
bool bRet = false;
// 유저 검사
CDNUser* pUser = GetUserByAccountDBID(nAccountDBID);
if( !pUser )
return bRet;
// PvP 방에 없음
UINT uiPvPIndex = pUser->GetPvPIndex();
if( uiPvPIndex == 0 )
return bRet;
CDNPvP* pPvPRoom = GetPvPRoomByIdx(uiPvPIndex);
if (pPvPRoom == NULL)
return bRet;
if (!(pUser->GetPvPUserState()&PvPCommon::UserState::Captain))
return bRet;
bRet = pPvPRoom->SwapPvPTournamentIndex(cSourceIndex, cDestIndex);
if( bRet )
{
UINT uiSourceAccountDBID=pPvPRoom->GetPvPTournamentAccountDBID(cSourceIndex);
if( uiSourceAccountDBID > 0 )
{
CDNUser* pSourceUser = GetUserByAccountDBID(uiSourceAccountDBID);
if( pSourceUser )
pSourceUser->SetPvPTeam(cSourceIndex%2==0 ? PvPCommon::Team::A : PvPCommon::Team::B);
}
UINT uiDestAccountDBID=pPvPRoom->GetPvPTournamentAccountDBID(cDestIndex);
if( uiDestAccountDBID > 0 )
{
CDNUser* pDestUser = GetUserByAccountDBID(uiDestAccountDBID);
if( pDestUser )
pDestUser->SetPvPTeam(cDestIndex%2==0 ? PvPCommon::Team::A : PvPCommon::Team::B);
}
}
return bRet;
}
#endif // #if defined(PRE_ADD_PVP_TOURNAMENT)
void CDivisionManager::SetPvPRoomState( const UINT uiPvPIndex, const UINT uiRoomState )
{
std::map<UINT,CDNPvP*>::iterator itor = m_mPvP.find( uiPvPIndex );
if( itor == m_mPvP.end() )
{
_DANGER_POINT();
return;
}
(*itor).second->SetRoomState( uiRoomState );
}
void CDivisionManager::SetPvPRoomSyncOK( const UINT uiPvPIndex )
{
std::map<UINT, CDNPvP*>::iterator itor = m_mPvP.find( uiPvPIndex );
if( itor == m_mPvP.end() )
{
_DANGER_POINT();
return;
}
UINT uiRoomState = (*itor).second->GetRoomState();
uiRoomState &= ~PvPCommon::RoomState::Syncing;
uiRoomState |= PvPCommon::RoomState::Playing;
(*itor).second->SetRoomState( uiRoomState );
}
void CDivisionManager::SetPvPBreakIntoOK( const GAMAPVP_BREAKINTOOK* pPacket )
{
#if defined( PRE_WORLDCOMBINE_PVP )
if( pPacket->uiPvPIndex > WorldPvPMissionRoom::Common::WorldPvPRoomStartIndex )
{
return;
}
#endif
std::map<UINT, CDNPvP*>::iterator itor = m_mPvP.find( pPacket->uiPvPIndex );
if( itor == m_mPvP.end() )
{
_DANGER_POINT();
return;
}
CDNPvP* pPvPRoom = (*itor).second;
if( !pPvPRoom->bIsCheckUser( pPacket->uiAccountDBID ) )
_DANGER_POINT();
CDNUser* pUser = g_pDivisionManager->GetUserByAccountDBID( pPacket->uiAccountDBID );
if( pUser )
pPvPRoom->AddPvPUserState( pUser, PvPCommon::UserState::Playing );
else
_DANGER_POINT();
}
void CDivisionManager::SetPvPFinishGameMode( const UINT uiPvPIndex, const UINT uiRoomIndex )
{
std::map<UINT, CDNPvP*>::iterator itor = m_mPvP.find( uiPvPIndex );
if( itor == m_mPvP.end() )
{
_DANGER_POINT();
return;
}
CDNPvP* pPvPRoom = (*itor).second;
// 게임룸ID 확인
if( pPvPRoom->GetGameServerRoomIndex() != uiRoomIndex )
return;
UINT uiRoomState = (*itor).second->GetRoomState();
uiRoomState |= PvPCommon::RoomState::Finished;
(*itor).second->SetRoomState( uiRoomState );
}
void CDivisionManager::SetPvPNoMoreBreakInto( const UINT uiPvPIndex, const UINT uiRoomIndex )
{
std::map<UINT, CDNPvP*>::iterator itor = m_mPvP.find( uiPvPIndex );
if( itor == m_mPvP.end() )
{
_DANGER_POINT();
return;
}
CDNPvP* pPvPRoom = (*itor).second;
// 게임룸ID 확인
if( pPvPRoom->GetGameServerRoomIndex() != uiRoomIndex )
return;
UINT uiRoomState = (*itor).second->GetRoomState();
uiRoomState |= PvPCommon::RoomState::NoMoreBreakInto;
(*itor).second->SetRoomState( uiRoomState );
}
void CDivisionManager::SetDestroyPvPGameRoom( const UINT uiPvPIndex, const UINT uiRoomIndex )
{
std::map<UINT,CDNPvP*>::iterator itor = m_mPvP.find( uiPvPIndex );
if( itor == m_mPvP.end() )
{
g_Log.Log(LogType::_PVPROOM, g_Config.nWorldSetID, 0, 0, 0, L"Fail to find PvPRoom [Index:%d][Room:%d] \r\n", uiPvPIndex, uiRoomIndex);
return;
}
CDNPvP* pPvPRoom = (*itor).second;
// 게임룸ID 확인
if( pPvPRoom->GetGameServerRoomIndex() != uiRoomIndex )
{
g_Log.Log(LogType::_PVPROOM, g_Config.nWorldSetID, 0, 0, 0, L"Not Match PvPRoomID[%d!=%d] \r\n", pPvPRoom->GetGameServerRoomIndex(), uiRoomIndex);
return;
}
UINT uiRoomState = pPvPRoom->GetRoomState();
UINT uiNewRoomState = uiRoomState&PvPCommon::RoomState::Password;
pPvPRoom->SetRoomState( uiNewRoomState );
if (pPvPRoom->GetEventRoomIndex() > 0)
g_Log.Log(LogType::_PVPROOM, g_Config.nWorldSetID, 0, 0, 0, L"Success to destroy PvPRoom [Index:%d][Room:%d][Event:%d] \r\n", pPvPRoom->GetIndex(), pPvPRoom->GetGameServerRoomIndex(), pPvPRoom->GetEventRoomIndex());
if (pPvPRoom->GetIsGuildWarSystem())
{
if (DestroyPvPGameRoom(uiPvPIndex) == false)
_DANGER_POINT();
//주의 이하에서 pPvPRoom은 유효하지 않음!
return;
}
#if defined( PRE_PVP_GAMBLEROOM )
if( pPvPRoom->GetGambleRoomType() > 0)
{
if (DestroyPvPGameRoom(uiPvPIndex) == false)
_DANGER_POINT();
//주의 이하에서 pPvPRoom은 유효하지 않음!
return;
}
#endif
}
//Farm
void CDivisionManager::CheckProcessFarm()
{
if (m_bDestroyFarm == false) return;
g_Log.Log(LogType::_FARM, L"CheckProcessFarm\n");
//파괴되어진 농장이 있다면 (게임서버가 죽음) 다른 서버로 세팅처리 해준다.
m_bDestroyFarm = false;
std::map <UINT, CDNFarm*>::iterator ii;
for (ii = m_mFarmList.begin(); ii != m_mFarmList.end(); ii++)
{
if ((*ii).second->GetFarmStatus() == FARMSTATUS_DESTROY)
{
bool bFlag = true;
int nAssignedGameID = -1;
#if defined( PRE_ADD_FARM_DOWNSCALE )
if (RequestFarmGameRoom((*ii).second->GetFarmDBID(), (*ii).second->GetMapID(), (*ii).second->GetFarmMaxUser(), (*ii).second->GetFarmStart(), nAssignedGameID, (*ii).second->GetAttr() ))
#elif defined( PRE_ADD_VIP_FARM )
if (RequestFarmGameRoom((*ii).second->GetFarmDBID(), (*ii).second->GetMapID(), (*ii).second->GetFarmMaxUser(), (*ii).second->GetFarmStart(), nAssignedGameID, (*ii).second->GetAttr() ))
#else
if (RequestFarmGameRoom((*ii).second->GetFarmDBID(), (*ii).second->GetMapID(), (*ii).second->GetFarmMaxUser(), (*ii).second->GetFarmStart(), nAssignedGameID))
#endif // #if defined( PRE_ADD_FARM_DOWNSCALE )
{
if ((*ii).second->SetAssignedServerID(nAssignedGameID) == false)
{
_DANGER_POINT();
m_bDestroyFarm = true; //실패한게 있다면 다시 돌게한다.
g_Log.Log(LogType::_FARM, L"Create FarmGameRoom GameID[%d] FarmID[%d] SetAssignedServerID Fail\n", nAssignedGameID, (*ii).second->GetFarmDBID());
}
g_Log.Log(LogType::_FARM, L"Create FarmGameRoom GameID[%d] FarmID[%d] Success\n", nAssignedGameID, (*ii).second->GetFarmDBID());
}
else
{
m_bDestroyFarm = true; //실패한게 있다면 다시 돌게한다.
g_Log.Log(LogType::_FARM, L"Create FarmGameRoom GameID[%d] FarmID[%d] RequestFarmGameRoom Fail\n", nAssignedGameID, (*ii).second->GetFarmDBID());
}
}
}
}
#if defined( PRE_PVP_GAMBLEROOM )
void CDivisionManager::DeletePvPGambleRoom()
{
for( _TPvPMap::iterator itor=m_mPvP.begin() ; itor!=m_mPvP.end() ; ++itor )
{
CDNPvP* pPvPRoom = (*itor).second;
if( pPvPRoom->GetGambleRoomType() > 0 )
{
if( pPvPRoom->GetRoomState() == PvPCommon::RoomState::None )
{
CDNVillageConnection* pVillageCon = GetVillageConnectionByVillageID( pPvPRoom->GetVillageID() );
pPvPRoom->bLeaveAll( pVillageCon, PvPCommon::LeaveType::DestroyRoom );
if( pVillageCon )
pVillageCon->SendPvPDestroyRoom( pPvPRoom->GetVillageChannelID(), pPvPRoom->GetIndex() );
g_Log.Log(LogType::_PVPROOM, g_Config.nWorldSetID, 0, 0, 0, L"DeletePvPGambleRoom\r\n");
delete pPvPRoom;
m_mPvP.erase(itor);
return;
}
}
}
}
#endif
#ifdef PRE_MOD_OPERATINGFARM
void CDivisionManager::CheckFarmSync(DWORD dwCurTick)
#else //#ifdef PRE_MOD_OPERATINGFARM
void CDivisionManager::CheckFarmSync()
#endif //#ifdef PRE_MOD_OPERATINGFARM
{
if (m_vFarmCreateSync.empty())
return;
std::vector <TFarmItemFromDB>::iterator ii;
for (ii = m_vFarmCreateSync.begin(); ii != m_vFarmCreateSync.end(); ii++)
{
#ifdef PRE_MOD_OPERATINGFARM
CreateFarm((*ii), dwCurTick);
#else //#ifdef PRE_MOD_OPERATINGFARM
if (CreateFarm((*ii)) == NULL)
_DANGER_POINT(); //어헐 여까지 와서 이러심 안뎁니다.
#endif //#ifdef PRE_MOD_OPERATINGFARM
}
}
#ifdef PRE_MOD_OPERATINGFARM
bool CDivisionManager::IsFarmConnectionWatingTime(DWORD dwCurTick)
{
if (m_dwFarmDataCreateTick == 0 || m_dwFarmDataCreateTick + Farm::Common::OPERATINGFARM_LIMIT > dwCurTick)
return true;
return false;
}
CDNFarm * CDivisionManager::CreateFarm(TFarmItemFromDB &FarmItem, DWORD dwCurTick)
{
if (IsFarmGameConnectionAvailable(dwCurTick) == false)
{
#else //#ifdef PRE_MOD_OPERATINGFARM
CDNFarm * CDivisionManager::CreateFarm(TFarmItemFromDB &FarmItem)
{
if (GetGameConnectionCount() <= 0)
{
#endif //#ifdef PRE_MOD_OPERATINGFARM
//생성할 게임서버가 아직 연결 전이라면 버퍼에 담아둔다
std::vector <TFarmItemFromDB>::iterator ih;
for (ih = m_vFarmCreateSync.begin(); ih != m_vFarmCreateSync.end(); ih++)
{
if ((*ih).iFarmDBID == FarmItem.iFarmDBID)
return NULL;
}
m_vFarmCreateSync.push_back(FarmItem);
#ifdef PRE_MOD_OPERATINGFARM
SetCreateFarmDataTick(timeGetTime());
#endif //#ifdef PRE_MOD_OPERATINGFARM
return NULL;
}
CDNFarm * pFarm = GetFarm(FarmItem.iFarmDBID);
if (pFarm != NULL)
return pFarm;
//자 없슈~ 생성~
#if defined( PRE_ADD_VIP_FARM ) || defined( PRE_ADD_FARM_DOWNSCALE )
pFarm = new CDNFarm(FarmItem);
#else
pFarm = new CDNFarm(FarmItem.iFarmDBID, FarmItem.iFarmMapID, FarmItem.bStartActivate);
#endif // #if defined( PRE_ADD_VIP_FARM ) || defined( PRE_ADD_FARM_DOWNSCALE )
if (pFarm == NULL)
return NULL;
bool bFlag = true;
int nAssignedGameID = -1;
#if defined( PRE_ADD_FARM_DOWNSCALE )
if (RequestFarmGameRoom(FarmItem.iFarmDBID, FarmItem.iFarmMapID, FarmItem.iFarmMaxUser, FarmItem.bStartActivate, nAssignedGameID, FarmItem.iAttr ) == false)
#elif defined( PRE_ADD_VIP_FARM )
if (RequestFarmGameRoom(FarmItem.iFarmDBID, FarmItem.iFarmMapID, FarmItem.iFarmMaxUser, FarmItem.bStartActivate, nAssignedGameID, FarmItem.Attr ) == false)
#else
if (RequestFarmGameRoom(FarmItem.iFarmDBID, FarmItem.iFarmMapID, FarmItem.iFarmMaxUser, FarmItem.bStartActivate, nAssignedGameID) == false)
#endif // #if defined( PRE_ADD_FARM_DOWNSCALE )
bFlag = false;
if (bFlag)
{
if (pFarm->SetAssignedServerID(nAssignedGameID) == false)
bFlag = false;
}
if (bFlag)
m_mFarmList.insert(std::make_pair(pFarm->GetFarmDBID(), pFarm));
else
{
delete pFarm;
return NULL;
}
return pFarm;
}
CDNFarm * CDivisionManager::GetFarm(UINT nFarmDBID)
{
if (m_mFarmList.empty()) return NULL;
std::map <UINT, CDNFarm*>::iterator ii = m_mFarmList.find(nFarmDBID);
return (ii != m_mFarmList.end()) ? (*ii).second : NULL;
}
bool CDivisionManager::DestroyFarm(UINT nFarmDBID)
{
std::map <UINT, CDNFarm*>::iterator ii = m_mFarmList.find(nFarmDBID);
if (ii != m_mFarmList.end())
{
(*ii).second->DestroyFarm();
m_bDestroyFarm = true;
return true;
}
return false;
}
bool CDivisionManager::SetFarmDataLoaded(UINT nFarmDBID, int nGameServerID, int nGameServerIdx, UINT nRoomID, int nMapID, int nFarmMaxUser)
{
CDNFarm * pFarm = GetFarm(nFarmDBID);
if (pFarm)
{
if (pFarm->SetAssignedFarmData(nGameServerID, nGameServerIdx, nRoomID, nMapID, nFarmMaxUser))
{
SendFarmInfo();
return true;
}
}
g_Log.Log(LogType::_FARM, L"FarmID[%d] SetFarmDataLoaded Fail\n", nFarmDBID);
return false;
}
bool CDivisionManager::SetFarmUpdateUserCount(UINT nFarmDBID, UINT nRoomID, int nCurUserCount, bool bStarted, int nManagedID)
{
CDNFarm * pFarm = GetFarm(nFarmDBID);
if (pFarm)
{
pFarm->SetFarmCurUserCount(nCurUserCount, bStarted, nManagedID);
return true;
}
_DANGER_POINT(); //헐 없뎅~
return false;
}
void CDivisionManager::Notice(const WCHAR * pMsg, const int nLen, int nShowSec)
{
if (nLen >= CHATLENMAX)
{
_DANGER_POINT();
return;
}
//다 쏴버려!
for (int i = 0; i < (int)m_GameServerConList.size(); i++)
m_GameServerConList[i]->SendNotice(pMsg, nLen, nShowSec);
for (int i = 0; i < (int)m_VillageServerConList.size(); i++)
m_VillageServerConList[i]->SendNotice(pMsg, nLen, nShowSec);
}
void CDivisionManager::NoticeZone(int nMapIndex, const WCHAR * pMsg, const int nLen, int nShowSec)
{
if (nLen >= CHATLENMAX)
{
_DANGER_POINT();
return;
}
//다 쏴버려!
for (int i = 0; i < (int)m_VillageServerConList.size(); i++)
m_VillageServerConList[i]->SendNoticeZone(nMapIndex, pMsg, nLen, nShowSec);
}
void CDivisionManager::NoticeChannel(int nChannelID, const WCHAR * pMsg, const int nLen, int nShowSec)
{
if (nLen >= CHATLENMAX)
{
_DANGER_POINT();
return;
}
for (int i = 0; i < (int)m_VillageServerConList.size(); i++)
m_VillageServerConList[i]->SendNoticeChannel(nChannelID, pMsg, nLen, nShowSec);
}
void CDivisionManager::NoticeServer(int nManagedID, const WCHAR * pMsg, const int nLen, int nShowSec)
{
if (nLen >= CHATLENMAX)
{
_DANGER_POINT();
return;
}
for (int i = 0; i < (int)m_GameServerConList.size(); i++)
m_GameServerConList[i]->SendNoticeServer(nManagedID, pMsg, nLen, nShowSec);
for (int i = 0; i < (int)m_VillageServerConList.size(); i++)
m_VillageServerConList[i]->SendNoticeServer(nManagedID, pMsg, nLen, nShowSec);
}
void CDivisionManager::NoticeCancel()
{
for (int i = 0; i < (int)m_GameServerConList.size(); i++)
m_GameServerConList[i]->SendNoticeCancel();
for (int i = 0; i < (int)m_VillageServerConList.size(); i++)
m_VillageServerConList[i]->SendNoticeCancel();
}
int CDivisionManager::SendInvitePartyMember(int nGameServerID, const GAMAInvitePartyMember * pInvitePartyMember)
{
CDNUser * pDestUser = GetUserByName(pInvitePartyMember->wszInvitedName);
if (pDestUser)
{
//초대할 대상이 있습니다. 기본적인 판단을 해봅니다.
if (pDestUser->GetUserState() != STATE_VILLAGE)
return ERROR_PARTY_INVITEFAIL;
//파튀가 어서 왔는지 알아야겠다.
const TChannelInfo * pChannelInfo = GetChannelInfo(pInvitePartyMember->nChannelID); //어디서 오신 파티이신지
const TChannelInfo * pDestChannelInfo = GetChannelInfo(pDestUser->GetChannelID()); //어디서 오신 파티이신지
if (pChannelInfo == NULL || pDestChannelInfo == NULL)
return ERROR_GENERIC_UNKNOWNERROR;
if (pDestUser->bIsPvPLobby()) //안되는 이유비교
return ERROR_PARTY_INVITEFAIL_DESTLOCATION_NOT_SAME;
#if defined( PRE_PARTY_DB )
#else
if (pChannelInfo->nMapIdx != pDestChannelInfo->nMapIdx) //초대대상의 마을과 비교
return ERROR_PARTY_INVITEFAIL_DESTLOCATION_NOT_SAME;
#endif // #if defined( PRE_PARTY_DB )
//더 화인해봐야 할게 있나?...일단 바로 빌리지에 쏴줍니다.
CDNVillageConnection * pVillageCon = GetVillageConnectionByVillageID(pDestUser->GetVillageID());
if (pVillageCon == NULL)
return ERROR_GENERIC_VILLAGECON_NOT_FOUND;
pVillageCon->SendInvitepartyMember(nGameServerID, pChannelInfo->nMapIdx, pDestUser->GetAccountDBID(), pInvitePartyMember, pInvitePartyMember->cPassClassIds, pInvitePartyMember->cPermitLevel);
return ERROR_NONE;
}
SendInvitePartyMemberResult(nGameServerID, pInvitePartyMember->wszInviterName, pInvitePartyMember->wszInvitedName, ERROR_PARTY_INVITEFAIL_DESTUSER_NOTFOUND);
return ERROR_PARTY_INVITEFAIL_DESTUSER_NOTFOUND;
}
bool CDivisionManager::SendInvitePartyMemberResult(int nGameServerID, const WCHAR * pwszInviterName, const WCHAR * pwszInvitedName, int nRetCode)
{
CDNGameConnection * pGameCon = GetGameConnectionByGameID(nGameServerID);
if (pGameCon)
{
if(pGameCon->GetZeroPopulation())
return false;
CDNUser * pUser = GetUserByName(pwszInviterName);
if (pUser == NULL) return false;
if (nRetCode == ERROR_NONE)
{
CDNUser * pInvitedUser = GetUserByName(pwszInvitedName);
if (pInvitedUser)
{
pGameCon->SendBreakintoRoom( pUser->m_nRoomID, pInvitedUser, BreakInto::Type::WorldZoneParty );
return true;
}
}
else
{
pGameCon->SendInivitePartyMemberResult(pUser->GetAccountDBID(), pwszInvitedName, nRetCode);
return true;
}
}
return false;
}
bool CDivisionManager::SendInvitedPartyMemberReturn(UINT nAccountDBID, int nRetCode)
{
CDNUser * pUser = GetUserByAccountDBID(nAccountDBID);
if (pUser)
{
CDNVillageConnection * pVillCon = GetVillageConnectionByVillageID(pUser->GetVillageID());
if (pVillCon)
{
pVillCon->SendResult(nAccountDBID, MAVI_INVITEPARTYMEMBER_RETMSG, nRetCode);
return true;
}
}
return false;
}
bool CDivisionManager::SendDetachUser(UINT nAccountDBID, bool bIsReconnectLogin, bool bIsDuplicate, UINT nSessionID)
{
CDNUser *pUser = GetUserByAccountDBID(nAccountDBID);
if (!pUser)
{
if( bIsDuplicate )
return false;
return true;
}
g_Log.Log( LogType::_NORMAL, g_Config.nWorldSetID, nAccountDBID, 0, pUser->GetSessionID(), L"[ADBID:%u CDBID:%I64d SID:%u] SendDetachUser (State:%d)\r\n", pUser->GetAccountDBID(), pUser->GetCharacterDBID(), pUser->GetSessionID(), pUser->GetUserState());
bool bSend = false;
bool bGameSend = false;
switch(pUser->GetUserState())
{
case STATE_VILLAGE:
{
bSend = SendDetachUserAllVillage(nAccountDBID, nSessionID, pUser->GetVillageID(), bIsDuplicate);
}
break;
case STATE_GAME:
{
bSend = SendDetachUserAllGame(nAccountDBID, nSessionID, pUser->GetGameID(), bIsDuplicate);
}
break;
case STATE_CHECKVILLAGE:
case STATE_CHECKGAME:
case STATE_CHECKRECONNECTLOGIN:
{
bSend = SendDetachUserAllVillage(nAccountDBID, nSessionID, pUser->GetPreVillageID(), bIsDuplicate);
if( pUser->GetGameID() )
bGameSend = SendDetachUserAllGame(nAccountDBID, nSessionID, pUser->GetGameID(), bIsDuplicate);
}
break;
}
// 중복로그인 끊기이고 각 서버에 보냈으면 DelUser하지 말자
if( bIsDuplicate )
{
if( bSend || bGameSend)
{
g_Log.Log( LogType::_NORMAL, pUser, L"[ADBID:%u CDBID:%I64d SID:%u] SendDetachDuplicateUser (State:%d)\r\n", pUser->GetAccountDBID(), pUser->GetCharacterDBID(), pUser->GetSessionID(), pUser->GetUserState());
return true;
}
else
{
// 서버에 못 보냈으면 지우고 짤라버리라고 함.
DelUser(nAccountDBID, bIsReconnectLogin);
return false;
}
}
DelUser(nAccountDBID, bIsReconnectLogin); // 서버가 없으면 걍 유저 지워준다
return true;
}
bool CDivisionManager::SendDetachUserAllVillage(UINT nAccountDBID, INT nSessionID, BYTE cCurVillageID, bool bIsDuplicate )
{
if (m_VillageServerConList.empty()) return false;
ScopeLock<CSyncLock> Lock(m_Sync);
bool bResult = false;
std::vector <CDNVillageConnection*>::iterator ii;
for (ii = m_VillageServerConList.begin(); ii != m_VillageServerConList.end(); ii++)
{
if( (*ii)->GetConnectionCompleted() )
{
if( (*ii)->GetVillageID() == cCurVillageID )
{
// 현재 Village 한테만 중복로그인 체크
(*ii)->SendDetachUser(nAccountDBID, bIsDuplicate, nSessionID);
bResult = true;
g_Log.Log( LogType::_NORMAL, 0, nAccountDBID, 0, nSessionID, L"SendDetachUserVillage (Village:%d)\r\n", cCurVillageID);
}
else
(*ii)->SendDetachUser(nAccountDBID, false, nSessionID);
}
}
return bResult;
}
bool CDivisionManager::SendDetachUserAllGame(UINT nAccountDBID, INT nSessionID, INT nGameID, bool bIsDuplicate)
{
if (m_GameServerConList.empty()) return false;
ScopeLock<CSyncLock> Lock(m_Sync);
bool bResult = false;
std::vector <CDNGameConnection*>::iterator ii;
for (ii = m_GameServerConList.begin(); ii != m_GameServerConList.end(); ii++)
{
if( (*ii)->GetConnectionCompleted() )
{
if ((*ii)->GetGameID() == nGameID )
{
// 현재 Game 한테만 중복로그인 체크
(*ii)->SendDetachUser(nAccountDBID, bIsDuplicate, nSessionID);
bResult = true;
g_Log.Log( LogType::_NORMAL, 0, nAccountDBID, 0, nSessionID, L"SendDetachUserGame (GameID:%d)\r\n", nGameID);
}
else
(*ii)->SendDetachUser(nAccountDBID, false, nSessionID);
}
}
return bResult;
}
void CDivisionManager::SendNotifyMail(UINT nToAccountDBID, INT64 biToCharacterDBID, short wTotalMailCount, short wNotReadMailCount, short w7DaysLeftCount, bool bNewMail)
{
CDNUser *pUser = GetUserByAccountDBID(nToAccountDBID);
if (!pUser) return;
if (pUser->GetUserState() == STATE_VILLAGE){
CDNVillageConnection *pVillageCon = pUser->GetCurrentVillageConnection();
if (pVillageCon)
pVillageCon->SendNotifyMail(nToAccountDBID, biToCharacterDBID, wTotalMailCount, wNotReadMailCount, w7DaysLeftCount, bNewMail);
}
else if (pUser->GetUserState() == STATE_GAME){
CDNGameConnection *pGameCon = pUser->GetCurrentGameConnection();
if (pGameCon)
pGameCon->SendNotifyMail(nToAccountDBID, biToCharacterDBID, wTotalMailCount, wNotReadMailCount, w7DaysLeftCount, bNewMail);
}
}
void CDivisionManager::SendNotifyMarket(UINT nSellerAccountDBID, INT64 biSellerCharacterDBID, int nItemID, short wCalculationCount)
{
CDNUser *pUser = GetUserByAccountDBID(nSellerAccountDBID);
if (!pUser) return;
if (pUser->GetUserState() == STATE_VILLAGE){
CDNVillageConnection *pVillageCon = pUser->GetCurrentVillageConnection();
if (pVillageCon)
pVillageCon->SendNotifyMarket(nSellerAccountDBID, biSellerCharacterDBID, nItemID, wCalculationCount);
}
else if (pUser->GetUserState() == STATE_GAME){
CDNGameConnection *pGameCon = pUser->GetCurrentGameConnection();
if (pGameCon)
pGameCon->SendNotifyMarket(nSellerAccountDBID, biSellerCharacterDBID, nItemID, wCalculationCount);
}
}
void CDivisionManager::SendNotifyGift(UINT nToAccountDBID, INT64 biToCharacterDBID, bool bNew, int nGiftCount)
{
CDNUser *pUser = GetUserByAccountDBID(nToAccountDBID);
if (!pUser) return;
if (pUser->GetUserState() == STATE_VILLAGE){
CDNVillageConnection *pVillageCon = pUser->GetCurrentVillageConnection();
if (pVillageCon)
pVillageCon->SendNotifyGift(nToAccountDBID, biToCharacterDBID, bNew, nGiftCount);
}
else if (pUser->GetUserState() == STATE_GAME){
CDNGameConnection *pGameCon = pUser->GetCurrentGameConnection();
if (pGameCon)
pGameCon->SendNotifyGift(nToAccountDBID, biToCharacterDBID, bNew, nGiftCount);
}
}
void CDivisionManager::SendVillageInfo()
{
ScopeLock<CSyncLock> Lock(m_Sync);
std::vector <TVillageInfo> vList;
GetVillageServerInfo(&vList);
if (vList.size() > 0)
{
SendAllLoginServerVillageInfo((UINT)m_AccountDBIDList.size(), g_pWaitUserManager->GetWorldMaxUser(), &vList);
for (int i = 0; i < (int)m_VillageServerConList.size(); i++)
m_VillageServerConList[i]->SendVillageInfo(&vList);
}
if (g_pServiceConnection)
g_pServiceConnection->SendVillageInfo((UINT)m_AccountDBIDList.size(), &vList);
}
void CDivisionManager::SendVillageChannelShowInfo( USHORT unChannelID, bool bShow )
{
ScopeLock<CSyncLock> Lock(m_Sync);
// LoginServer
MALOUpdateChannelShowInfo TxPacket;
memset( &TxPacket, 0, sizeof(TxPacket) );
TxPacket.unChannelID = unChannelID;
TxPacket.bShow = bShow;
SendAllLoginServer( MALO_UPDATECHANNELSHOWINFO, 0, reinterpret_cast<char*>(&TxPacket), sizeof(TxPacket) );
// VillageServer
MAVIUpdateChannelShowInfo TxPacket2;
memset( &TxPacket2, 0, sizeof(TxPacket2) );
TxPacket2.unChannelID = unChannelID;
TxPacket2.bShow = bShow;
SendAllVillageServer( MAVI_UPDATECHANNELSHOWINFO, 0, reinterpret_cast<char*>(&TxPacket2), sizeof(TxPacket2) );
}
void CDivisionManager::SendUpdateWorldEventCounter( MAUpdateWorldEventCounter* pPacket )
{
// VillageServer
SendAllVillageServer( MAVI_UPPDATE_WORLDEVENTCOUNTER, 0, reinterpret_cast<char*>(pPacket), sizeof(MAUpdateWorldEventCounter) );
// GameServer
SendAllGameServer( MAGA_UPPDATE_WORLDEVENTCOUNTER, 0, reinterpret_cast<char*>(pPacket), sizeof(MAUpdateWorldEventCounter) );
}
void CDivisionManager::SendFarmInfo()
{
ScopeLock<CSyncLock> Lock(m_Sync);
MAVIFarmInfoUpdate packet;
memset(&packet, 0, sizeof(MAVIFarmInfoUpdate));
std::map <UINT, CDNFarm*>::iterator ii;
for (ii = m_mFarmList.begin(); ii != m_mFarmList.end(); ii++)
{
packet.FarmInfo[packet.cFarmCount].nFarmDBID = (*ii).second->GetFarmDBID();
packet.FarmInfo[packet.cFarmCount].nFarmCurUserCount = (*ii).second->GetFarmCurUserCount();
packet.FarmInfo[packet.cFarmCount].bActivate = ((*ii).second->IsActivateFarm() && (*ii).second->IsStartedFarm()) ? true : false;
packet.cFarmCount++;
if (packet.cFarmCount >= Farm::Max::FARMCOUNT)
{
_DANGER_POINT();
break;
}
}
SendAllVillageServer(MAVI_FARMINFOUPDATE, 0, reinterpret_cast<char*>(&packet), sizeof(MAVIFarmInfoUpdate));
}
void CDivisionManager::GetFarmInfo(TServiceReportMaster * pData)
{
ScopeLock<CSyncLock> Lock(m_Sync);
std::map <UINT, CDNFarm*>::iterator ii;
for (ii = m_mFarmList.begin(); ii != m_mFarmList.end(); ii++)
{
pData->FarmStatus[pData->cFarmCount].nManagedID = (*ii).second->GetManagedID();
pData->FarmStatus[pData->cFarmCount].nFarmDBID = (*ii).second->GetFarmDBID();
pData->FarmStatus[pData->cFarmCount].nFarmCurUserCount = (*ii).second->GetFarmCurUserCount();
pData->FarmStatus[pData->cFarmCount].bActivate = ((*ii).second->IsActivateFarm() && (*ii).second->IsStartedFarm()) ? true : false;
pData->cFarmCount++;
if (pData->cFarmCount >= Farm::Max::FARMCOUNT/2)
{
_DANGER_POINT();
break;
}
}
}
void CDivisionManager::SendPCBangResult(CDNUser *pUser)
{
switch(pUser->GetUserState())
{
case STATE_CHECKVILLAGE:
case STATE_VILLAGE:
{
CDNVillageConnection *pVillageCon = pUser->GetCurrentVillageConnection();
if (pVillageCon)
pVillageCon->SendPCBangResult(pUser->GetAccountDBID(), pUser);
else
DelUser(pUser->GetAccountDBID()); // 서버가 없으면 걍 유저 지워준다
}
break;
case STATE_CHECKGAME:
case STATE_GAME:
{
CDNGameConnection *pGameCon = GetGameConnectionByGameID(pUser->GetGameID());
if( pGameCon )
pGameCon->SendPCBangResult(pUser->GetAccountDBID(), pUser);
else
DelUser(pUser->GetAccountDBID()); // 서버가 없으면 걍 유저 지워준다
}
break;
default:
break;
}
}
void CDivisionManager::OnDisconnectServer( const int iConnectionKey, const int iServerID, int nManagedID )
{
//external thread call Watch!!!!
}
#if defined( PRE_ADD_NPC_REPUTATION_SYSTEM )
void CDivisionManager::SyncSystemMail( VIMASyncSystemMail* pMail )
{
CDNUser* pUser = GetUserByCharacterDBID( pMail->biReceiverCharacterDBID );
if( pUser == NULL )
return;
switch( pUser->GetUserState() )
{
case STATE_CHECKVILLAGE:
case STATE_VILLAGE:
{
CDNVillageConnection* pVillageCon = g_pDivisionManager->GetVillageConnectionByVillageID( pUser->GetVillageID() );
if( pVillageCon )
pVillageCon->SendSyncSystemMail( pUser->GetAccountDBID(), pMail );
break;
}
case STATE_CHECKGAME:
case STATE_GAME:
{
CDNGameConnection* pGameCon = g_pDivisionManager->GetGameConnectionByGameID( pUser->GetGameID() );
if( pGameCon )
pGameCon->SendSyncSystemMail( pUser->GetAccountDBID(), pMail );
break;
}
}
}
#endif // #if defined( PRE_ADD_NPC_REPUTATION_SYSTEM )
void CDivisionManager::SyncMasterSystemSimpleInfo( MasterSystem::VIMASyncSimpleInfo* pPacket )
{
CDNUser* pUser = g_pDivisionManager->GetUserByCharacterDBID( pPacket->biCharacterDBID );
if( pUser == NULL )
return;
switch( pUser->GetUserState() )
{
case STATE_CHECKVILLAGE:
case STATE_VILLAGE:
{
CDNVillageConnection* pVillageCon = g_pDivisionManager->GetVillageConnectionByVillageID( pUser->GetVillageID() );
if( pVillageCon )
pVillageCon->SendMasterSystemSyncSimpleInfo( pUser->GetAccountDBID(), pPacket->biCharacterDBID, pPacket->EventCode );
break;
}
case STATE_CHECKGAME:
case STATE_GAME:
{
CDNGameConnection* pGameCon = g_pDivisionManager->GetGameConnectionByGameID( pUser->GetGameID() );
if( pGameCon )
pGameCon->SendMasterSystemSyncSimpleInfo( pUser->GetAccountDBID(), pPacket->biCharacterDBID, pPacket->EventCode );
break;
}
}
}
void CDivisionManager::SyncMasterSystemGraduate( MasterSystem::VIMASyncGraduate* pPacket )
{
CDNUser* pUser = GetUserByCharacterDBID( pPacket->biCharacterDBID );
if( pUser == NULL )
return;
switch( pUser->GetUserState() )
{
case STATE_VILLAGE:
{
CDNVillageConnection* pVillageCon = g_pDivisionManager->GetVillageConnectionByVillageID( pUser->GetVillageID() );
if( pVillageCon )
pVillageCon->SendMasterSystemSyncGraduate( pUser->GetAccountDBID(), pPacket );
break;
}
case STATE_GAME:
{
CDNGameConnection* pGameCon = g_pDivisionManager->GetGameConnectionByGameID( pUser->GetGameID() );
if( pGameCon )
pGameCon->SendMasterSystemSyncGraduate( pUser->GetAccountDBID(), pPacket );
break;
}
}
}
void CDivisionManager::SyncMasterSystemConnect( MasterSystem::VIMASyncConnect* pPacket )
{
for( UINT i=0 ;i<pPacket->cCharacterDBIDCount ; ++i )
{
CDNUser* pUser = GetUserByCharacterDBID( pPacket->CharacterDBIDList[i] );
if( pUser == NULL )
continue;
switch( pUser->GetUserState() )
{
case STATE_VILLAGE:
{
CDNVillageConnection* pVillageCon = g_pDivisionManager->GetVillageConnectionByVillageID( pUser->GetVillageID() );
if( pVillageCon )
pVillageCon->SendMasterSystemSyncConnect( pUser->GetAccountDBID(), pPacket->bIsConnect, pPacket->wszCharName );
break;
}
case STATE_GAME:
{
CDNGameConnection* pGameCon = g_pDivisionManager->GetGameConnectionByGameID( pUser->GetGameID() );
if( pGameCon )
pGameCon->SendMasterSystemSyncConnect( pUser->GetAccountDBID(), pPacket->bIsConnect, pPacket->wszCharName );
break;
}
}
}
}
void CDivisionManager::SyncFarm( GAMAFarmSync* pPacket )
{
CDNUser* pUser = GetUserByCharacterDBID( pPacket->biCharacterDBID );
if( pUser == NULL )
return;
bool bSyncGameServer = false;
bool bSyncVillageServer = false;
switch( pPacket->Type )
{
case Farm::ServerSyncType::FIELDCOUNT:
case Farm::ServerSyncType::FIELDLIST:
{
bSyncGameServer = true;
break;
}
case Farm::ServerSyncType::WAREHOUSE_ITEMCOUNT:
{
bSyncGameServer = true;
bSyncVillageServer = true;
break;
}
}
switch( pUser->GetUserState() )
{
case STATE_GAME:
{
CDNGameConnection* pGameCon = g_pDivisionManager->GetGameConnectionByGameID( pUser->GetGameID() );
if( pGameCon && bSyncGameServer )
pGameCon->SendFarmSync( pUser->GetAccountDBID(), pUser->GetCharacterDBID(), pPacket->Type );
break;
}
case STATE_VILLAGE:
{
CDNVillageConnection* pVillageCon = g_pDivisionManager->GetVillageConnectionByVillageID( pUser->GetVillageID() );
if( pVillageCon && bSyncVillageServer)
pVillageCon->SendFarmSync( pUser->GetAccountDBID(), pUser->GetCharacterDBID(), pPacket->Type );
break;
}
}
}
void CDivisionManager::SyncFarmAddWater( GAMAFarmSyncAddWater* pPacket )
{
CDNUser* pUser = GetUserByCharacterDBID( pPacket->biCharacterDBID );
if( pUser == NULL )
return;
switch( pUser->GetUserState() )
{
case STATE_GAME:
{
CDNGameConnection* pGameCon = g_pDivisionManager->GetGameConnectionByGameID( pUser->GetGameID() );
if( pGameCon )
pGameCon->SendFarmSyncAddWater( pUser->GetAccountDBID(), pPacket->wszCharName, pPacket->iAddPoint );
break;
}
}
}
void CDivisionManager::SendLoginUserDetach(UINT nAccountDBID, int nLoginServerID)
{
for (int nIndex = 0 ; LOGINCOUNTMAX > nIndex ; ++nIndex)
{
// 나를 제외한 다른 서버들에게 끊어달라고 요청..
if( m_pLoginConnectionList[nIndex] && m_pLoginConnectionList[nIndex]->GetServerID() != nLoginServerID )
{
if( m_pLoginConnectionList[nIndex]->GetActive() )
{
m_pLoginConnectionList[nIndex]->SendDetachUser(nAccountDBID);
}
}
}
}
#if defined(PRE_ADD_QUICK_PVP)
int CDivisionManager::MakeQuickPvPRoom(UINT nMasterAccountDBID, UINT nSlaveAccountDBID)
{
CDNUser* pMasterUser = g_pDivisionManager->GetUserByAccountDBID(nMasterAccountDBID);
if( pMasterUser == NULL)
return ERROR_PVP_CREATEROOM_FAILED;
CDNUser* pSlaveUser = g_pDivisionManager->GetUserByAccountDBID(nSlaveAccountDBID);
if( pSlaveUser == NULL)
return ERROR_PVP_CREATEROOM_FAILED;
if (pMasterUser->GetUserState() != STATE_VILLAGE || pSlaveUser->GetUserState() != STATE_VILLAGE)
return ERROR_PVP_CREATEROOM_FAILED;
CDNVillageConnection* pVillageCon = g_pDivisionManager->GetVillageConnectionByVillageID( g_pDivisionManager->GetPvPLobbyVillageID() );
if( pVillageCon == NULL || pVillageCon->GetActive() == false )
return ERROR_PVP_CREATEROOM_FAILED;
if( pMasterUser->GetPvPIndex() > 0 || pSlaveUser->GetPvPIndex() > 0 )
return ERROR_PVP_CREATEROOM_FAILED;
// MapID 얻어오기
UINT uiMapIndex = 10003; // 죽음의 결투장(s) 하드코딩..
/*
// MapID로 PvPMapTable 얻어오기
const TPvPMapTable* pMapTable = g_pExtManager->GetPvPMapTable(uiMapIndex);
if( pMapTable == NULL )
return ERROR_PVP_CREATEROOM_FAILED;
// PvPMapTable에서 GameMode 정보 가져오기
const TPvPGameModeTable* pPvPGameModeTable = g_pExtManager->GetPvPGameModeTable( pMapTable->vGameModeTableID[0] );
if( pPvPGameModeTable == NULL )
return ERROR_PVP_CREATEROOM_FAILED;
*/
// 여기서 방만들기..
VIMAPVP_CREATEROOM sCreateRoom;
memset(&sCreateRoom, 0, sizeof(sCreateRoom));
sCreateRoom.unVillageChannelID = GetPvPLobbyChannelID();
sCreateRoom.uiVillageMapIndex = GetPvPLobbyMapIndex();
//sCreateRoom.uiCreateAccountDBID = nMasterAccountDBID;
sCreateRoom.cGameMode = PvPCommon::GameMode::PvP_Round;
sCreateRoom.sCSPVP_CREATEROOM.uiMapIndex = uiMapIndex;
sCreateRoom.sCSPVP_CREATEROOM.uiGameModeTableID = 10;
sCreateRoom.sCSPVP_CREATEROOM.uiSelectWinCondition = 5; // 5라운드
sCreateRoom.sCSPVP_CREATEROOM.uiSelectPlayTimeSec = 180;
sCreateRoom.sCSPVP_CREATEROOM.cMaxUser = 2;
sCreateRoom.sCSPVP_CREATEROOM.cMinUser = 0;
sCreateRoom.sCSPVP_CREATEROOM.cRoomPWLen = 0;
sCreateRoom.sCSPVP_CREATEROOM.cMinLevel = 1;
sCreateRoom.sCSPVP_CREATEROOM.cMaxLevel = 100;
sCreateRoom.sCSPVP_CREATEROOM.unRoomOptionBit = 0;
sCreateRoom.sCSPVP_CREATEROOM.uiEventItemID = 0;
#ifdef PRE_ADD_COLOSSEUM_BEGINNER
sCreateRoom.sCSPVP_CREATEROOM.cRoomType = static_cast<BYTE>(PvPCommon::RoomType::regular);
pMasterUser->SetPvPChannelType(static_cast<BYTE>(PvPCommon::RoomType::regular));
pVillageCon->SendPvPChangeChannelResult(pMasterUser->GetAccountDBID(), static_cast<BYTE>(pMasterUser->GetPvPChannelType()), ERROR_NONE);
pSlaveUser->SetPvPChannelType(static_cast<BYTE>(PvPCommon::RoomType::regular));
pVillageCon->SendPvPChangeChannelResult(pSlaveUser->GetAccountDBID(), static_cast<BYTE>(pSlaveUser->GetPvPChannelType()), ERROR_NONE);
#endif //#ifdef PRE_ADD_COLOSSEUM_BEGINNER
wsprintf(sCreateRoom.sCSPVP_CREATEROOM.wszBuf, L"%s vs %s", pMasterUser->GetCharacterName(), pSlaveUser->GetCharacterName());
sCreateRoom.sCSPVP_CREATEROOM.cRoomNameLen = (BYTE)wcslen(sCreateRoom.sCSPVP_CREATEROOM.wszBuf);
UINT uiPvPIndex = 0;
short nRetCode = g_pDivisionManager->CreatePvPRoom( pVillageCon, &sCreateRoom, &uiPvPIndex );
// 마스터 셋팅 및 PvPIndex 셋팅
if( nRetCode == ERROR_NONE )
{
CDNPvP* pPvP = GetPvPRoomByIdx(uiPvPIndex);
if( pPvP )
{
pMasterUser->SetPvPIndex(uiPvPIndex);
pMasterUser->SetPvPTeam(PvPCommon::Team::A);
pMasterUser->SetPvPUserState( PvPCommon::UserState::Captain );
pPvP->SetCaptainAccountDBID(nMasterAccountDBID);
pPvP->AddListAccountDBID(nMasterAccountDBID);
pSlaveUser->SetPvPIndex(uiPvPIndex);
pSlaveUser->SetPvPTeam(PvPCommon::Team::B);
pSlaveUser->SetPvPUserState( PvPCommon::UserState::None );
pPvP->AddListAccountDBID(nSlaveAccountDBID);
}
}
return nRetCode;
}
#endif
#if defined( PRE_WORLDCOMBINE_PARTY )
int CDivisionManager::GetWorldPartyMember( MAGetWorldPartyMember* pPacket )
{
CDNGameConnection* pGameCon = GetGameConnectionByManagedID(pPacket->iServerID);
if(pGameCon)
{
pGameCon->SendGetWorldPartyMember(pPacket);
return ERROR_NONE;
}
return ERROR_PARTY_JOINFAIL;
}
#endif
#if defined( PRE_PRIVATECHAT_CHANNEL )
int CDivisionManager::AddPrivateChatChannel( MAAddPrivateChannel* pPacket )
{
// 전체 VI 에 송신
pPacket->cWorldSetID = g_Config.nWorldSetID;
vector<CDNVillageConnection*>::iterator iterv;
for (iterv = m_VillageServerConList.begin() ; m_VillageServerConList.end() != iterv ; ++iterv) {
if (0 != (*iterv)->GetManagedID() && pPacket->nManagedID == (*iterv)->GetManagedID()) {
continue;
}
(*iterv)->SendPrivateChatChannelAdd(pPacket);
}
// 전체 GA 에 송신
vector<CDNGameConnection*>::iterator iterg;
for (iterg = m_GameServerConList.begin() ; m_GameServerConList.end() != iterg ; ++iterg)
{
(*iterg)->SendPrivateChatChannelAdd(pPacket);
}
return ERROR_NONE;
}
int CDivisionManager::AddPrivateChatChannelMember( MAAddPrivateChannelMember* pPacket )
{
pPacket->cWorldSetID = g_Config.nWorldSetID;
// 전체 VI 에 송신
vector<CDNVillageConnection*>::iterator iterv;
for (iterv = m_VillageServerConList.begin() ; m_VillageServerConList.end() != iterv ; ++iterv) {
if (0 != (*iterv)->GetManagedID() && pPacket->nManagedID == (*iterv)->GetManagedID()) {
continue;
}
(*iterv)->SendPrivateChatChannelMemberAdd(pPacket);
}
// 전체 GA 에 송신
vector<CDNGameConnection*>::iterator iterg;
for (iterg = m_GameServerConList.begin() ; m_GameServerConList.end() != iterg ; ++iterg)
{
(*iterg)->SendPrivateChatChannelMemberAdd(pPacket);
}
return ERROR_NONE;
}
int CDivisionManager::InvitePrivateChatChannelMember( MAInvitePrivateChannelMember* pPacket )
{
CDNUser* pUser = GetUserByName( pPacket->wszInviteName );
if (pUser)
{
#if defined(PRE_ADD_DWC)
if( pUser->GetCharacterAccountLevel() == AccountLevel_DWC )
{
MAInvitePrivateChannelMemberResult InviteResult;
memset(&InviteResult, 0, sizeof(InviteResult));
InviteResult.cWorldSetID = pPacket->cWorldSetID;
InviteResult.nMasterAccountDBID = pPacket->nMasterAccountDBID;
InviteResult.nRet = ERROR_NOTEXIST_INVITEUSER;
g_pDivisionManager->InviteResultPrivateChatChannelMember( &InviteResult );
return ERROR_NONE;
}
#endif
pPacket->nInviteAccountDBID = pUser->GetAccountDBID();
if (pUser->GetUserState() == STATE_CHECKVILLAGE || pUser->GetUserState() == STATE_VILLAGE)
{
CDNVillageConnection * pVillCon = GetVillageConnectionByVillageID(pUser->GetVillageID());
if (pVillCon)
pVillCon->SendPrivateChatChannelMemberInvite(pPacket);
}
else if (pUser->GetUserState() == STATE_CHECKGAME || pUser->GetUserState() == STATE_GAME)
{
CDNGameConnection * pGameCon = GetGameConnectionByGameID(pUser->GetGameID());
if (pGameCon)
pGameCon->SendPrivateChatChannelMemberInvite(pPacket);
}
}
else
{
MAInvitePrivateChannelMemberResult InviteResult;
memset(&InviteResult, 0, sizeof(InviteResult));
InviteResult.cWorldSetID = pPacket->cWorldSetID;
InviteResult.nMasterAccountDBID = pPacket->nMasterAccountDBID;
InviteResult.nRet = ERROR_NOTEXIST_INVITEUSER;
g_pDivisionManager->InviteResultPrivateChatChannelMember( &InviteResult );
}
return ERROR_NONE;
}
int CDivisionManager::InviteResultPrivateChatChannelMember( MAInvitePrivateChannelMemberResult* pPacket )
{
CDNUser* pUser = GetUserByAccountDBID( pPacket->nMasterAccountDBID );
if (pUser)
{
if (pUser->GetUserState() == STATE_CHECKVILLAGE || pUser->GetUserState() == STATE_VILLAGE)
{
CDNVillageConnection * pVillCon = GetVillageConnectionByVillageID(pUser->GetVillageID());
if (pVillCon)
pVillCon->SendPrivateChatChannelMemberInviteResult(pPacket);
}
else if (pUser->GetUserState() == STATE_CHECKGAME || pUser->GetUserState() == STATE_GAME)
{
CDNGameConnection * pGameCon = GetGameConnectionByGameID(pUser->GetGameID());
if (pGameCon)
pGameCon->SendPrivateChatChannelMemberInviteResult(pPacket);
}
}
return ERROR_NONE;
}
int CDivisionManager::DelPrivateChatChannelMember( MADelPrivateChannelMember* pPacket )
{
pPacket->cWorldSetID = g_Config.nWorldSetID;
vector<CDNVillageConnection*>::iterator iterv;
for (iterv = m_VillageServerConList.begin() ; m_VillageServerConList.end() != iterv ; ++iterv) {
if (0 != (*iterv)->GetManagedID() && pPacket->nManagedID == (*iterv)->GetManagedID()) {
continue;
}
(*iterv)->SendPrivateChatChannelMemberDel(pPacket);
}
// 전체 GA 에 송신
vector<CDNGameConnection*>::iterator iterg;
for (iterg = m_GameServerConList.begin() ; m_GameServerConList.end() != iterg ; ++iterg)
{
(*iterg)->SendPrivateChatChannelMemberDel(pPacket);
}
return ERROR_NONE;
}
int CDivisionManager::KickPrivateChatChannelMemberResult( MAKickPrivateChannelMemberResult* pPacket )
{
CDNUser* pUser = GetUserByCharacterDBID( pPacket->biCharacterDBID );
if (pUser)
{
pPacket->nAccountDBID = pUser->GetAccountDBID();
if (pUser->GetUserState() == STATE_CHECKVILLAGE || pUser->GetUserState() == STATE_VILLAGE)
{
CDNVillageConnection * pVillCon = GetVillageConnectionByVillageID(pUser->GetVillageID());
if (pVillCon)
pVillCon->SendPrivateChatChannelMemberKickResult(pPacket);
}
else if (pUser->GetUserState() == STATE_CHECKGAME || pUser->GetUserState() == STATE_GAME)
{
CDNGameConnection * pGameCon = GetGameConnectionByGameID(pUser->GetGameID());
if (pGameCon)
pGameCon->SendPrivateChatChannelMemberKickResult(pPacket);
}
}
return ERROR_NONE;
}
int CDivisionManager::ModPrivateChatChannel( MAModPrivateChannel* pPacket )
{
pPacket->cWorldSetID = g_Config.nWorldSetID;
vector<CDNVillageConnection*>::iterator iterv;
for (iterv = m_VillageServerConList.begin() ; m_VillageServerConList.end() != iterv ; ++iterv) {
if (0 != (*iterv)->GetManagedID() && pPacket->nManagedID == (*iterv)->GetManagedID()) {
continue;
}
(*iterv)->SendPrivateChatChannelMod(pPacket);
}
// 전체 GA 에 송신
vector<CDNGameConnection*>::iterator iterg;
for (iterg = m_GameServerConList.begin() ; m_GameServerConList.end() != iterg ; ++iterg)
{
(*iterg)->SendPrivateChatChannelMod(pPacket);
}
return ERROR_NONE;
}
int CDivisionManager::ModPrivateChatChannelMemberName( MAModPrivateChannelMemberName* pPacket )
{
pPacket->cWorldSetID = g_Config.nWorldSetID;
vector<CDNVillageConnection*>::iterator iterv;
for (iterv = m_VillageServerConList.begin() ; m_VillageServerConList.end() != iterv ; ++iterv) {
if (0 != (*iterv)->GetManagedID() && pPacket->nManagedID == (*iterv)->GetManagedID()) {
continue;
}
(*iterv)->SendPrivateChatChannelModMemberName(pPacket);
}
// 전체 GA 에 송신
vector<CDNGameConnection*>::iterator iterg;
for (iterg = m_GameServerConList.begin() ; m_GameServerConList.end() != iterg ; ++iterg)
{
(*iterg)->SendPrivateChatChannelModMemberName(pPacket);
}
return ERROR_NONE;
}
#endif
#ifdef _WORK
#include "StringUtil.h"
#include "DNWaitUserManager.h"
void CDivisionManager::Parse(const char * pMsg)
{
std::string strCmd;
strCmd = pMsg;
ToLowerA(strCmd);
std::vector<std::string> tokens;
TokenizeA(strCmd, tokens, "|");
std::wstring szWStr;
if (tokens.size() > 0)
{
if (tokens[0] == "notice")
{
ToWideString(tokens[2], szWStr);
Notice(szWStr.c_str(), (int)wcslen(szWStr.c_str()), atoi(tokens[1].c_str()));
}
if (tokens[0] == "noticezone")
{
ToWideString(tokens[3], szWStr);
NoticeZone(atoi(tokens[1].c_str()), szWStr.c_str(), (int)wcslen(szWStr.c_str()), atoi(tokens[2].c_str()));
}
if (tokens[0] == "noticechannel")
{
ToWideString(tokens[3], szWStr);
NoticeChannel(atoi(tokens[1].c_str()), szWStr.c_str(), (int)wcslen(szWStr.c_str()), atoi(tokens[2].c_str()));
}
if (tokens[0] == "userban")
{
ToWideString(tokens[1], szWStr);
CDNUser * user = GetUserByName(szWStr.c_str());
if (user)
SendDetachUser(user->GetAccountDBID());
}
if (tokens[0] == "maxuser")
{
g_pWaitUserManager->Initialize(100);
}
if (tokens[0] == "selectjoin")
{
ToWideString(tokens[2], szWStr);
g_pDivisionManager->AddSelectJoin(atoi(tokens[1].c_str()), szWStr.c_str());
}
if (tokens[0] == "clearselectjoin")
{
g_pDivisionManager->ClearSelectJoin();
}
if (tokens[0] == "destroypvp")
{
if (tokens.size() > 2)
{
ToWideString(tokens[2], szWStr);
g_pDivisionManager->ForceStopPvP(atoi(tokens[1].c_str()), szWStr.c_str());
}
else
{
g_pDivisionManager->ForceStopPvP(atoi(tokens[1].c_str()));
}
}
if (tokens[0] == "reloadext")
{
g_pDivisionManager->ReloadExt();
}
if (tokens[0] == "reloadact")
{
g_pDivisionManager->ReloadAct();
}
if (tokens[0] == "kick")
{
if (tokens.size() >= 2)
{
ToWideString(tokens[1], szWStr);
CDNUser * pUser = g_pDivisionManager->GetUserByName(szWStr.c_str());
if(pUser)
g_pDivisionManager->SendDetachUser(pUser->GetAccountDBID());
}
}
if (tokens[0] == "refreshguildware")
{
if (tokens.size() >= 2)
{
SendUpdateGuildWare(atoi(tokens[1].c_str()));
}
}
#ifdef PRE_ADD_DOORS_GUILDCHAT_DISCONNECT
if (tokens[0] == "guildchat")
{
if (tokens.size() >= 4)
{
if (g_pDivisionManager)
{
std::wstring wstrMessage;
ToWideString(tokens[3], wstrMessage);
if (g_pDivisionManager->DoorsGuildChat(_atoi64(tokens[1].c_str()), atoi(tokens[2].c_str()), wstrMessage.c_str(), static_cast<int>(wstrMessage.size())))
_DANGER_POINT();
}
}
}
#endif //#ifdef PRE_ADD_DOORS_GUILDCHAT_DISCONNECT
}
}
#endif
#if defined( PRE_ALTEIAWORLD_EXPLORE )
int CDivisionManager::AlteiaSendTicket( MAAlteiaWorldSendTicket* pPacket )
{
CDNUser* pUser = GetUserByName( pPacket->wszRecvCharacterName );
if (pUser)
{
pPacket->nAccountDBID = pUser->GetAccountDBID();
if (pUser->GetUserState() == STATE_CHECKVILLAGE || pUser->GetUserState() == STATE_VILLAGE)
{
CDNVillageConnection * pVillCon = GetVillageConnectionByVillageID(pUser->GetVillageID());
if (pVillCon)
{
pVillCon->SendAlteiaWorldSendTicket(pPacket);
return ERROR_NONE;
}
}
else if (pUser->GetUserState() == STATE_CHECKGAME || pUser->GetUserState() == STATE_GAME)
{
CDNGameConnection * pGameCon = GetGameConnectionByGameID(pUser->GetGameID());
if (pGameCon)
{
pGameCon->SendAlteiaWorldSendTicket(pPacket);
return ERROR_NONE;
}
}
}
return ERROR_ALTEIAWORLD_NOTEXISTUSER;
}
int CDivisionManager::AlteiaSendTicketResult( MAAlteiaWorldSendTicketResult* pPacket )
{
CDNUser* pUser = GetUserByCharacterDBID( pPacket->biSendCharacterDBID );
if (pUser)
{
pPacket->nSendAccountDBID = pUser->GetAccountDBID();
if (pUser->GetUserState() == STATE_CHECKVILLAGE || pUser->GetUserState() == STATE_VILLAGE)
{
CDNVillageConnection * pVillCon = GetVillageConnectionByVillageID(pUser->GetVillageID());
if (pVillCon)
pVillCon->SendAlteiaWorldSendTicketResult(pPacket);
}
else if (pUser->GetUserState() == STATE_CHECKGAME || pUser->GetUserState() == STATE_GAME)
{
CDNGameConnection * pGameCon = GetGameConnectionByGameID(pUser->GetGameID());
if (pGameCon)
pGameCon->SendAlteiaWorldSendTicketResult(pPacket);
}
}
return ERROR_NONE;
}
#endif
#if defined( PRE_DRAGONBUFF )
int CDivisionManager::SendApplyWorldBuff( MAApplyWorldBuff* pPacket )
{
vector<CDNVillageConnection*>::iterator iterv;
for (iterv = m_VillageServerConList.begin() ; m_VillageServerConList.end() != iterv ; ++iterv) {
if (0 != (*iterv)->GetManagedID() && pPacket->nManagedID == (*iterv)->GetManagedID()) {
continue;
}
(*iterv)->SendApplyWorldBuff(pPacket);
}
return ERROR_NONE;
}
#endif
#if defined(PRE_ADD_DWC)
bool CDivisionManager::SendInviteDWCTeamMember(MAInviteDWCTeamMember* pPacket)
{
// 길드초대할 유저를 찾는다
CDNUser * pUser = GetUserByName(pPacket->wszToCharacterName);
if( pUser && pUser->GetUserState() == STATE_VILLAGE)
{
CDNVillageConnection* pVillageCon = g_pDivisionManager->GetVillageConnectionByVillageID( pUser->GetVillageID() );
if( pVillageCon )
{
pVillageCon->SendInviteDWCTeamMember(pPacket);
return true;
}
}
return false;
}
bool CDivisionManager::SendInviteDWCTeamMemberAck(MAInviteDWCTeamMemberAck* pPacket)
{
// 길드원 초대 요청한 유저를 찾는다.
CDNUser * pUser = g_pDivisionManager->GetUserByAccountDBID(pPacket->nInviterDBID);
if( pUser && pUser->GetUserState() == STATE_VILLAGE)
{
CDNVillageConnection* pVillageCon = g_pDivisionManager->GetVillageConnectionByVillageID( pUser->GetVillageID() );
if( pVillageCon )
{
pVillageCon->SendInviteDWCTeamMemberAck(pPacket);
return true;
}
}
return false;
}
bool CDivisionManager::SendChangeDWCTeamMemberState(MAChangeDWCTeamMemberState* pPacket)
{
CDNUser * pUser = g_pDivisionManager->GetUserByAccountDBID(pPacket->nTartgetUserAccountDBID);
if (pUser)
{
if (pUser->GetUserState() == STATE_CHECKVILLAGE || pUser->GetUserState() == STATE_VILLAGE)
{
CDNVillageConnection * pVillCon = GetVillageConnectionByVillageID(pUser->GetVillageID());
if (pVillCon)
pVillCon->SendChangeDWCTeamMemberState(pPacket);
}
else if (pUser->GetUserState() == STATE_CHECKGAME || pUser->GetUserState() == STATE_GAME)
{
CDNGameConnection * pGameCon = GetGameConnectionByGameID(pUser->GetGameID());
if (pGameCon)
pGameCon->SendChangeDWCTeamMemberState(pPacket);
}
}
return ERROR_NONE;
}
void CDivisionManager::SetDWCTeamMemberList(VIMADWCTeamMemberList *pPacket)
{
CDNUser * pUser = g_pDivisionManager->GetUserByAccountDBID(pPacket->nAccountDBID);
if (pUser)
{ //빌리지 최초 접속시에만 처리
if (pUser->GetUserState() == STATE_CHECKVILLAGE || pUser->GetUserState() == STATE_VILLAGE)
pUser->SetDWCTeamInfo(pPacket);
}
}
void CDivisionManager::SendDWCTeamChat(MADWCTeamChat *pPacket)
{
CDNUser * pSender = g_pDivisionManager->GetUserByAccountDBID(pPacket->nAccountDBID);
if (pSender && pSender->GetDWCTeamID() > 0 )
{
std::vector<Int64> vecMemberList;
pSender->GetDWCMemberList(vecMemberList);
for(int i = 0 ; i < vecMemberList.size() ; i++)
{
CDNUser * pUser = g_pDivisionManager->GetUserByCharacterDBID(vecMemberList[i]);
if (pUser)
{
if (pUser->GetUserState() == STATE_CHECKVILLAGE || pUser->GetUserState() == STATE_VILLAGE)
{
CDNVillageConnection * pVillCon = GetVillageConnectionByVillageID(pUser->GetVillageID());
if (pVillCon)
pVillCon->SendChat(CHATTYPE_DWC_TEAM, pUser->GetAccountDBID(), pSender->GetCharacterName(), pPacket->wszChatMsg, pPacket->nLen);
}
else if (pUser->GetUserState() == STATE_CHECKGAME || pUser->GetUserState() == STATE_GAME)
{
CDNGameConnection * pGameCon = GetGameConnectionByGameID(pUser->GetGameID());
if (pGameCon)
pGameCon->SendDWCTeamChat(CHATTYPE_DWC_TEAM, pUser->GetAccountDBID(), pSender->GetCharacterName(), pPacket->wszChatMsg, pPacket->nLen);
}
}
}
}
}
bool CDivisionManager::_RecvAddDWCTeamMember(MAAddDWCTeamMember* pPacket)
{
CDNUser * pUser = g_pDivisionManager->GetUserByAccountDBID(pPacket->nTartgetUserAccountDBID);
if (pUser)
{
pUser->AddDWCMemberList(pPacket->biCharacterDBID);
if(pPacket->bAlredySentByVillage) //빌리지 서버에서 이미 유저에게 패킷전송했음
return ERROR_NONE;
return SendAddDWCTeamMember(pPacket, pUser);
}
return ERROR_NONE;
}
bool CDivisionManager::_RecvLeaveDWCTeamMember(MALeaveDWCTeamMember* pPacket)
{
CDNUser * pUser = g_pDivisionManager->GetUserByAccountDBID(pPacket->nTartgetUserAccountDBID);
if (pUser)
{
pUser->DelDWCMemberList(pPacket->biLeaveUserCharacterDBID);
if(pPacket->bAlredySentByVillage) //빌리지 서버에서 이미 유저에게 패킷전송했음
return ERROR_NONE;
return SendLeaveDWCTeamMember(pPacket, pUser);
}
return ERROR_NONE;
}
bool CDivisionManager::_RecvDismissDWCTeam(MADismissDWCTeam* pPacket)
{
CDNUser * pUser = g_pDivisionManager->GetUserByAccountDBID(pPacket->nTartgetUserAccountDBID);
if (pUser)
{
pUser->ResetDWCInfo();
if(pPacket->bAlredySentByVillage) //빌리지 서버에서 이미 유저에게 패킷전송했음
return ERROR_NONE;
return SendDismissDWCTeam(pPacket, pUser);
}
return ERROR_NONE;
}
bool CDivisionManager::SendAddDWCTeamMember(MAAddDWCTeamMember* pPacket, CDNUser * pUser)
{
if (pUser)
{
if (pUser->GetUserState() == STATE_CHECKVILLAGE || pUser->GetUserState() == STATE_VILLAGE)
{
CDNVillageConnection * pVillCon = GetVillageConnectionByVillageID(pUser->GetVillageID());
if (pVillCon)
pVillCon->SendAddDWCTeamMember(pPacket);
}
else if (pUser->GetUserState() == STATE_CHECKGAME || pUser->GetUserState() == STATE_GAME)
{
CDNGameConnection * pGameCon = GetGameConnectionByGameID(pUser->GetGameID());
if (pGameCon)
pGameCon->SendAddDWCTeamMember(pPacket);
}
}
return ERROR_NONE;
}
bool CDivisionManager::SendLeaveDWCTeamMember(MALeaveDWCTeamMember* pPacket, CDNUser * pUser)
{
if (pUser)
{
if (pUser->GetUserState() == STATE_CHECKVILLAGE || pUser->GetUserState() == STATE_VILLAGE)
{
CDNVillageConnection * pVillCon = GetVillageConnectionByVillageID(pUser->GetVillageID());
if (pVillCon)
pVillCon->SendLeaveDWCTeamMember(pPacket);
}
else if (pUser->GetUserState() == STATE_CHECKGAME || pUser->GetUserState() == STATE_GAME)
{
CDNGameConnection * pGameCon = GetGameConnectionByGameID(pUser->GetGameID());
if (pGameCon)
pGameCon->SendLeaveDWCTeamMember(pPacket);
}
}
return ERROR_NONE;
}
bool CDivisionManager::SendDismissDWCTeam(MADismissDWCTeam* pPacket, CDNUser * pUser)
{
if (pUser)
{
if (pUser->GetUserState() == STATE_CHECKVILLAGE || pUser->GetUserState() == STATE_VILLAGE)
{
CDNVillageConnection * pVillCon = GetVillageConnectionByVillageID(pUser->GetVillageID());
if (pVillCon)
pVillCon->SendDismissDWCTeam(pPacket);
}
else if (pUser->GetUserState() == STATE_CHECKGAME || pUser->GetUserState() == STATE_GAME)
{
CDNGameConnection * pGameCon = GetGameConnectionByGameID(pUser->GetGameID());
if (pGameCon)
pGameCon->SendDismissDWCTeam(pPacket);
}
}
return ERROR_NONE;
}
void CDivisionManager::SendUpdateDWCScore(MADWCUpdateScore *pPacket)
{
vector<CDNVillageConnection*>::iterator itorv;
for (itorv = m_VillageServerConList.begin() ; m_VillageServerConList.end() != itorv ; ++itorv)
(*itorv)->SendUpdateDWCScore(pPacket);
}
#endif