void MMatchServer::OnAdminRequestSwitchLadderGame(const MUID& uidAdmin, const bool bEnabled)
{
	MMatchObject* pObj = GetObject(uidAdmin);
	if (!IsEnabledObject(pObj)) return;

	// 관리자 권한을 가진 사람이 아니면 연결을 끊는다.
	if (!IsAdminGrade(pObj))
	{
//		DisconnectObject(uidAdmin);		
		return;
	}

	
	MGetServerConfig()->SetEnabledCreateLadderGame(bEnabled);


	char szMsg[256] = "설정되었습니다.";
	Announce(pObj, szMsg);
}
Example #2
0
bool MBMatchServer::IsKeeper( const MUID& uidKeeper )
{
	MMatchObject* pObj = GetObject( uidKeeper );
	if( 0 == pObj )
		return false;

	if( !MGetServerConfig()->IsKeeperIP(pObj->GetIPString()) )
	{
		mlog( "Keeper hacking. " );
		if( 0 != pObj->GetIPString() )
			mlog( "IP:%s, ", pObj->GetIPString() );

		if( (0 != pObj->GetCharInfo()) && (0 != pObj->GetCharInfo()->m_szName) )
			mlog( "Name:%s", pObj->GetCharInfo()->m_szName );

		mlog( "\n" );

		return false;
	}

	return true;
}
void MMatchServer::OnMatchLoginFromDBAgent(const MUID& CommUID, const char* szLoginID, const char* szName, int nSex, bool bFreeLoginIP, unsigned long nChecksumPack)
{
#ifndef LOCALE_NHNUSA
	MCommObject* pCommObj = (MCommObject*)m_CommRefCache.GetRef(CommUID);
	if (pCommObj == NULL) return;

	string strCountryCode3;
	CheckIsValidIP( CommUID, pCommObj->GetIPString(), strCountryCode3, false );

	const char* pUserID = szLoginID;
	char szPassword[16] = "";			// 패스워드는 없다
	char szCertificate[16] = "";
	const char* pName = szName;
	int nAge = 20;

	bool bCheckPremiumIP = MGetServerConfig()->CheckPremiumIP();
	const char* szIP = pCommObj->GetIPString();
	DWORD dwIP = pCommObj->GetIP();

	// Async DB
	MAsyncDBJob_GetLoginInfo* pNewJob = new MAsyncDBJob_GetLoginInfo(CommUID);
	pNewJob->Input(new MMatchAccountInfo,
					new MMatchAccountPenaltyInfo,
					pUserID, 
					szPassword, 
					szCertificate, 
					pName, 
					nAge, 
					nSex, 
					bFreeLoginIP, 
					nChecksumPack,
					bCheckPremiumIP,
					szIP,
					dwIP,
					strCountryCode3);
	PostAsyncJob(pNewJob);
#endif
}
bool CCMatchLocale::OnInit()
{
	m_bCheckAntiHackCrack = false;

	switch (m_iCountry)
	{
		case CCC_KOREA:
			break;

		case CCC_US:
			break;

		case CCC_JAPAN:
			{
//				int nGameCode = MGetServerConfig()->GetNJDBAgentGameCode();
//				int nServerCode = MGetServerConfig()->GetServerID();
//				m_pDBAgentClient = new MNJ_DBAgentClient(nGameCode, nServerCode);
//				ConnectToDBAgent();		// 일본 넷마블판만 DBAgent에 접속한다.
			}
			break;

		case CCC_BRAZIL:
			break;

		case CCC_INDIA:
			break;
	}

#ifdef _XTRAP
	// XTrap Crack을 체크한다.
	if( MGetServerConfig()->IsUseXTrap() )
		m_bCheckAntiHackCrack = true;		
#endif

	return true;
}
void MAsyncDBJob_GetLoginInfo::Run(void* pContext)
{
	_ASSERT(m_pAccountInfo);

	MMatchDBMgr* pDBMgr = (MMatchDBMgr*)pContext;

	// 원래 계정은 넷마블에 있으므로 해당 계정이 없으면 새로 생성한다. 
	if (!pDBMgr->GetLoginInfo(m_szUserID, &m_nAID, m_szDBPassword))
	{
		int nGunzSex;	// 건즈디비의 성별값은 넷마블 성별값과 반대이다.
		if (m_nSex == 0) nGunzSex = 1; else nGunzSex = 0;

		int nCert = 0;
		if (strlen(m_szCertificate) > 0)
		{
			if (m_szCertificate[0] == '1') nCert =1;
		}

		pDBMgr->CreateAccount(m_szUserID, m_szUniqueID, nCert, m_szName, m_nAge, nGunzSex);
		pDBMgr->GetLoginInfo(m_szUserID, &m_nAID, m_szDBPassword);
	}

	// 계정 정보를 읽는다.
	if (!pDBMgr->GetAccountInfo(m_nAID, m_pAccountInfo, MGetServerConfig()->GetServerID()))
	{
		SetResult(MASYNC_RESULT_FAILED);
		return;
	}

	// 계정 페널티 정보를 읽는다. - 2010-08-10 홍기주
	if( !pDBMgr->GetAccountPenaltyInfo(m_nAID, m_pAccountPenaltyInfo) ) 
	{
		SetResult(MASYNC_RESULT_FAILED);
		return;
	}

	// 프리미엄 IP를 체크한다.
	if (m_bCheckPremiumIP)
	{
		bool bIsPremiumIP = false;
		bool bExistPremiumIPCache = false;
		
		bExistPremiumIPCache = MPremiumIPCache()->CheckPremiumIP(m_dwIP, bIsPremiumIP);

		// 만약 캐쉬에 없으면 직접 DB에서 찾도록 한다.
		if (!bExistPremiumIPCache)
		{
			if (pDBMgr->CheckPremiumIP(m_szIP, bIsPremiumIP))
			{
				// 결과를 캐쉬에 저장
				MPremiumIPCache()->AddIP(m_dwIP, bIsPremiumIP);
			}
			else
			{
				MPremiumIPCache()->OnDBFailed();
			}

		}

		//if (bIsPremiumIP) m_pAccountInfo->m_nPGrade = MMPG_PREMIUM_IP;
	}

	SetResult(MASYNC_RESULT_SUCCEED);
}
void MMatchServer::OnMatchLogin(MUID CommUID, const char* szUserID, const char* szPassword, int nCommandVersion, unsigned long nChecksumPack, char *szEncryptMd5Value, char* szHwid)
{
//	MCommObject* pCommObj = (MCommObject*)m_CommRefCache.GetRef(CommUID);
//	if (pCommObj == NULL) return;

	// 초기 위치의 노드는 검색해서 얻어낸다.
	int nMapID = 0;
	unsigned int Status = 0;
	unsigned int nAID = 0;
	char szDBPassword[64];
	string strCountryCode3;

	bool bFreeLoginIP = false;

	if(strstr(szHwid, "%") || strstr(szUserID, "%") || strstr(szPassword, "%"))
	{
		MCommand* pCmd = CreateCmdMatchResponseLoginFailed(CommUID, MERR_CLIENT_WRONG_PASSWORD);
		Post(pCmd);	
		return;
	}

	
	// 프로토콜, 최대인원 체크
	if (!CheckOnLoginPre(CommUID, nCommandVersion, bFreeLoginIP, strCountryCode3)) return;	

	// 원래 계정은 넷마블에 있으므로 해당 계정이 없으면 새로 생성한다. 
	if (!m_MatchDBMgr.GetLoginInfo(szUserID, &nAID, szDBPassword))
	{
#ifdef _DEBUG
		m_MatchDBMgr.CreateAccount(szUserID, szPassword, 0, szUserID, 20, 1);
		strcpy(szDBPassword, szPassword);

		m_MatchDBMgr.GetLoginInfo(szUserID, &nAID, szDBPassword);
#endif

		MCommand* pCmd = CreateCmdMatchResponseLoginFailed(CommUID, MERR_CLIENT_WRONG_PASSWORD);
		Post(pCmd);	

		return;
	}


	MCommObject* pCommObj = (MCommObject*)m_CommRefCache.GetRef(CommUID);
	if (pCommObj)
	{
		// 디비에 최종 접속시간을 업데이트 한다.
		if (!m_MatchDBMgr.UpdateLastConnDate(szUserID, pCommObj->GetIPString()))
		{	
			mlog("DB Query(OnMatchLogin > UpdateLastConnDate) Failed");
		}

	}

	unsigned char md5[16];
	char szPassMd5[64];
	
	MMD5 m;
	m.md5_string((unsigned char*)szPassword, strlen(szPassword), md5);

	for (int i = 0, j = 0; i < 16; i++, j+=2)
		sprintf(szPassMd5 + j, "%02x", md5[i]);


	// 패스워드가 틀렸을 경우 처리

	if (strcmp(szDBPassword, szPassMd5) != 0)
	//if(strcmp(szDBPassword, szPassword)) //md5
	{
		MCommand* pCmd = CreateCmdMatchResponseLoginFailed(CommUID, MERR_CLIENT_WRONG_PASSWORD);
		Post(pCmd);	

		return;
	}

	MMatchAccountInfo accountInfo;
	if (!m_MatchDBMgr.GetAccountInfo(nAID, &accountInfo, MGetServerConfig()->GetServerID()))
	{
		// Notify Message 필요 -> 로그인 관련 - 해결(Login Fail 메세지 이용)
		// Disconnect(CommUID);
		MCommand* pCmd = CreateCmdMatchResponseLoginFailed(CommUID, MERR_FAILED_GETACCOUNTINFO);
		Post(pCmd);	
	}

	MMatchAccountPenaltyInfo accountpenaltyInfo;
	if( !m_MatchDBMgr.GetAccountPenaltyInfo(nAID, &accountpenaltyInfo) ) 
	{
		MCommand* pCmd = CreateCmdMatchResponseLoginFailed(CommUID, MERR_FAILED_GETACCOUNTINFO);
		Post(pCmd);	
	}

#ifndef _DEBUG
	// 중복 로그인이면 이전에 있던 사람을 끊어버린다.
	MMatchObject* pCopyObj = GetPlayerByAID(accountInfo.m_nAID);
 	if (pCopyObj != NULL) 
	{
		// 내가 로그인일때 이미 로그인 돼있는 클라이언트가 있으면 이미 로그인 클라이언트에 
		// 중복 로그인이란 메세지 보내고 접속을 끊음. - by kammir 2008.09.30
		MCommand* pCmd = CreateCmdMatchResponseLoginFailed(pCopyObj->GetUID(), MERR_MULTIPLE_LOGIN);
		Post(pCmd);	
		//Disconnect(pCopyObj->GetUID());
	}
#endif
	
	// 사용정지 계정인지 확인한다.
	if ((accountInfo.m_nUGrade == MMUG_BLOCKED) || (accountInfo.m_nUGrade == MMUG_PENALTY))
	{
		MCommand* pCmd = CreateCmdMatchResponseLoginFailed(CommUID, MERR_CLIENT_MMUG_BLOCKED);
		Post(pCmd);	
		return;
	}


	/*
	 * Steven: Hwid
	 */
	
	m_MatchDBMgr.GetHwidInfo(&Status, szHwid);

	if(Status == 1) {
		MCommand* pCmd = CreateCmdMatchResponseLoginFailed(CommUID, MERR_HWID_BANNED);
		Post(pCmd);	
		return;
	}
	m_MatchDBMgr.CreateHwid(accountInfo.m_nAID, szHwid); //Actualiza el HWID de la Cuenta


#ifndef _DEBUG // debug에선 상관없다. 테스트가 필요하면 따로 설정을 해야 함. - by SungE 2007-05-03
	// gunz.exe 실행파일의 무결성을 확인한다. (암호화 되어 있다)
	// server.ini 파일에서 설정된 값에 따라 사용하지 않으면 검사하지 않는다.
	if (MGetServerConfig()->IsUseMD5() && accountInfo.m_nUGrade < 252)	
	{
		if(timeGetTime() > actualizarMD5)
			CargarMD5();
		unsigned char szMD5Value[ MAX_MD5LENGH ] = {0, };
		pCommObj->GetCrypter()->Decrypt(szEncryptMd5Value, MAX_MD5LENGH, (MPacketCrypterKey*)pCommObj->GetCrypter()->GetKey());
		memcpy( szMD5Value, szEncryptMd5Value, MAX_MD5LENGH );

		if ((memcmp(m_szMD5Value, szMD5Value, MAX_MD5LENGH)) != 0)
		{
			// "정상적인 실행파일이 아닙니다." 이런 오류 패킷이 없어서 전송 생략
			LOG(LOG_PROG, "MD5 error : AID(%u).\n \n", accountInfo.m_nAID);
			// 접속 끊어버리자
//			Disconnect(CommUID);
			return;
		}
	}
#endif

	// 로그인성공하여 오브젝트(MMatchObject) 생성
	AddObjectOnMatchLogin(CommUID, &accountInfo, &accountpenaltyInfo, bFreeLoginIP, strCountryCode3, nChecksumPack);

/*
	MUID AllocUID = CommUID;
	int nErrCode = ObjectAdd(CommUID);
	if(nErrCode!=MOK){
		LOG(LOG_DEBUG, MErrStr(nErrCode) );
	}

	MMatchObject* pObj = GetObject(AllocUID);
	pObj->AddCommListener(CommUID);
	pObj->SetObjectType(MOT_PC);
	memcpy(pObj->GetAccountInfo(), &accountInfo, sizeof(MMatchAccountInfo));
	pObj->SetFreeLoginIP(bFreeLoginIP);
	pObj->SetCountryCode3( strCountryCode3 );
	pObj->UpdateTickLastPacketRecved();

	if (pCommObj != NULL)
	{
		pObj->SetPeerAddr(pCommObj->GetIP(), pCommObj->GetIPString(), pCommObj->GetPort());
	}
	
	SetClientClockSynchronize(CommUID);


	// 프리미엄 IP를 체크한다.
	if (MGetServerConfig()->CheckPremiumIP())
	{
		if (pCommObj)
		{
			bool bIsPremiumIP = false;
			bool bExistPremiumIPCache = false;
			
			bExistPremiumIPCache = MPremiumIPCache()->CheckPremiumIP(pCommObj->GetIP(), bIsPremiumIP);

			// 만약 캐쉬에 없으면 직접 DB에서 찾도록 한다.
			if (!bExistPremiumIPCache)
			{
				if (m_MatchDBMgr.CheckPremiumIP(pCommObj->GetIPString(), bIsPremiumIP))
				{
					// 결과를 캐쉬에 저장
					MPremiumIPCache()->AddIP(pCommObj->GetIP(), bIsPremiumIP);
				}
				else
				{
					MPremiumIPCache()->OnDBFailed();
				}

			}

			if (bIsPremiumIP) pObj->GetAccountInfo()->m_nPGrade = MMPG_PREMIUM_IP;
		}		
	}


	MCommand* pCmd = CreateCmdMatchResponseLoginOK(CommUID, 
												   AllocUID, 
												   pObj->GetAccountInfo()->m_szUserID,
												   pObj->GetAccountInfo()->m_nUGrade,
                                                   pObj->GetAccountInfo()->m_nPGrade);
	Post(pCmd);	

	// 접속 로그를 남긴다.
	m_MatchDBMgr.InsertConnLog(pObj->GetAccountInfo()->m_nAID, pObj->GetIPString(), pObj->GetCountryCode3() );

#ifndef _DEBUG
	// Client DataFile Checksum을 검사한다.
	unsigned long nChecksum = nChecksumPack ^ CommUID.High ^ CommUID.Low;
	if (nChecksum != GetItemFileChecksum()) {
		LOG(LOG_PROG, "Invalid ZItemChecksum(%u) , UserID(%s) ", nChecksum, pObj->GetAccountInfo()->m_szUserID);
		Disconnect(CommUID);
	}
#endif

*/
}
bool MMatchServer::AddObjectOnMatchLogin(const MUID& uidComm, 
										const MMatchAccountInfo* pSrcAccountInfo,
										const MMatchAccountPenaltyInfo* pSrcAccountPenaltyInfo,
										bool bFreeLoginIP, string strCountryCode3, unsigned long nChecksumPack)
{
	MCommObject* pCommObj = (MCommObject*)m_CommRefCache.GetRef(uidComm);
	if (pCommObj == NULL) return false;

	MUID AllocUID = uidComm;
	int nErrCode = ObjectAdd(uidComm);
	if(nErrCode!=MOK) {
		LOG(LOG_DEBUG, MErrStr(nErrCode) );
	}

	MMatchObject* pObj = GetObject(AllocUID);
	if (pObj == NULL) {
		// Notify Message 필요 -> 로그인 관련 - 해결(Login Fail 메세지 이용)
		// Disconnect(uidComm);
		MCommand* pCmd = CreateCmdMatchResponseLoginFailed(AllocUID, MERR_FAILED_LOGIN_RETRY);
		Post(pCmd);	
		return false;
	}

	pObj->AddCommListener(uidComm);
	pObj->SetObjectType(MOT_PC);

	memcpy(pObj->GetAccountInfo(), pSrcAccountInfo, sizeof(MMatchAccountInfo));
	memcpy(pObj->GetAccountPenaltyInfo(), pSrcAccountPenaltyInfo, sizeof(MMatchAccountPenaltyInfo));
		
	pObj->SetFreeLoginIP(bFreeLoginIP);
	pObj->SetCountryCode3( strCountryCode3 );
	pObj->UpdateTickLastPacketRecved();
	pObj->UpdateLastHShieldMsgRecved();

	if (pCommObj != NULL)
	{
		pObj->SetPeerAddr(pCommObj->GetIP(), pCommObj->GetIPString(), pCommObj->GetPort());
	}
	
	SetClientClockSynchronize(uidComm);

	// 프리미엄 IP를 체크한다.
	if (MGetServerConfig()->CheckPremiumIP())
	{
		if (pCommObj)
		{
			bool bIsPremiumIP = false;
			bool bExistPremiumIPCache = false;
			
			bExistPremiumIPCache = MPremiumIPCache()->CheckPremiumIP(pCommObj->GetIP(), bIsPremiumIP);

			// 만약 캐쉬에 없으면 직접 DB에서 찾도록 한다.
			if (!bExistPremiumIPCache)
			{
				if (m_MatchDBMgr.CheckPremiumIP(pCommObj->GetIPString(), bIsPremiumIP))
				{
					// 결과를 캐쉬에 저장
					MPremiumIPCache()->AddIP(pCommObj->GetIP(), bIsPremiumIP);
				}
				else
				{
					MPremiumIPCache()->OnDBFailed();
				}

			}

			//if (bIsPremiumIP) pObj->GetAccountInfo()->m_nPGrade = MMPG_PREMIUM_IP;
		}		
	}

	if (!PreCheckAddObj(uidComm))
	{
		// 보안 관련 초기화 서버 설정에 문제가 생겼다고 로그인 실패를 리턴한다. //
		MCommand* pCmd = CreateCmdMatchResponseLoginFailed(uidComm, MERR_FAILED_AUTHENTICATION);
		Post(pCmd);	
		return false;
	}



	MCommand* pCmd = CreateCmdMatchResponseLoginOK(uidComm, 
												   AllocUID, 
												   pObj->GetAccountInfo()->m_szUserID,
												   pObj->GetAccountInfo()->m_nUGrade,
                                                   pObj->GetAccountInfo()->m_nPGrade,
												   pObj->GetAccountInfo()->m_nECoins,
//												   pObj->GetAntiHackInfo()->m_szRandomValue,
												   pObj->GetHShieldInfo()->m_pbyGuidReqMsg);
	Post(pCmd);	

	// 접속 로그를 남긴다.
	//m_MatchDBMgr.InsertConnLog(pObj->GetAccountInfo()->m_nAID, pObj->GetIPString(), pObj->GetCountryCode3() );

	// 접속 로그
	MAsyncDBJob_InsertConnLog* pNewJob = new MAsyncDBJob_InsertConnLog(uidComm);
	pNewJob->Input(pObj->GetAccountInfo()->m_nAID, pObj->GetIPString(), pObj->GetCountryCode3() );
	PostAsyncJob(pNewJob);

	// Client DataFile Checksum을 검사한다.
	// 2006.2.20 dubble. filelist checksum으로 변경
	unsigned long nChecksum = nChecksumPack ^ uidComm.High ^ uidComm.Low;
	if( MGetServerConfig()->IsUseFileCrc() && !MMatchAntiHack::CheckClientFileListCRC(nChecksum, pObj->GetUID()) && 
		!MGetServerConfig()->IsDebugLoginIPList(pObj->GetIPString()) )
	{
		LOG(LOG_PROG, "Invalid filelist crc (%u) , UserID(%s)\n ", nChecksum, pObj->GetAccountInfo()->m_szUserID);
//		pObj->SetBadFileCRCDisconnectWaitInfo();
		pObj->DisconnectHacker( MMHT_BADFILECRC);
	}
	/*
	if (nChecksum != GetItemFileChecksum()) {
		LOG(LOG_PROG, "Invalid ZItemChecksum(%u) , UserID(%s) ", nChecksum, pObj->GetAccountInfo()->m_szUserID);
		Disconnect(uidComm);
		return false;
	}
	*/

	pObj->LoginCompleted();

	return true;
}
Example #8
0
void MAsyncDBJob_GetCharInfo::Run(void* pContext)
{
	_ASSERT(m_pCharInfo);
	MMatchDBMgr* pDBMgr = (MMatchDBMgr*)pContext;

	//int nWaitHourDiff;

	if (!pDBMgr->GetCharInfoByAID(m_nAID, m_nCharIndex, m_pCharInfo)) {
		SetResult(MASYNC_RESULT_FAILED);
		return;
	}

	unsigned int nEquipedItemID[MMCIP_END];
	unsigned int nEquipedItemCIID[MMCIP_END];

	if( !pDBMgr->GetCharEquipmentInfoByAID(m_nAID, m_nCharIndex, nEquipedItemID, nEquipedItemCIID)) {
		SetResult(MASYNC_RESULT_FAILED);
		return;
	}

	for(int i = 0; i < MMCIP_END; i++) {
		m_pCharInfo->m_nEquipedItemCIID[i] = nEquipedItemCIID[i];
	}

#ifdef _DELETE_CLAN
	// 클랜에 가입된 캐릭터이면 폐쇄요청된 클랜인지 검사를 해줘야 한다.
	if( 0 != m_pCharInfo->m_ClanInfo.m_nClanID ) 
	{
		/*
		// nWaitHourDiff의 값이 0이면 정상 클랜.
		// 0 이상이면 폐쇄요청이 접수된 클랜이다. 
		// 폐쇄 요청된 클랜을 정상 클랜으로 바꿔주기 위해서는, 
		//  Clan테이블의 DeleteDate를 NULL로 셋팅해 줘야 한다. - by SungE.

		if( UNDEFINE_DELETE_HOUR == nWaitHourDiff )
		{
			// 정상 클랜.
		}
		else if( 0 > nWaitHourDiff )
		{
			SetDeleteState( MMCDS_WAIT );
		}
		//else if( MAX_WAIT_CLAN_DELETE_HOUR < nWaitHourDiff )
		//{
		//	// 클랜정보를 DB에서 삭제.
		//	// 이작업은 DB의 Agent server작업으로 일괄 처리히한다.
		//}
		else if( 0 <= nWaitHourDiff) 
		{
			// 아직 DB는 삭제하지 않고, 유저만 일반 유저로 처리함.
			SetDeleteState( MMCDS_NORMAL );
			m_pCharInfo->m_ClanInfo.Clear();
		}
		*/
	}
#endif

	// 디비에서 아이템 정보를 가져온다. 
	// 이것은 퍼포먼스 문제로 나중에 플레이어가 자기 아이템 보기 할때만 가져와야 할듯	
	m_pCharInfo->ClearItems();
	if (!pDBMgr->GetCharItemInfo(m_pCharInfo))
	{
		SetResult(MASYNC_RESULT_FAILED);
		return;
	}

#ifdef _QUEST_ITEM
	if( MSM_TEST == MGetServerConfig()->GetServerMode() ) 
	{
		m_pCharInfo->m_QuestItemList.Clear();
		if( !pDBMgr->GetCharQuestItemInfo(m_pCharInfo) )
		{
			mlog( "MAsyncDBJob_GetCharInfo::Run - 디비에서 퀘스트 아이템 목록을 가져오는데 실패했음.\n" );
			SetResult(MASYNC_RESULT_FAILED);
			return;
		}
	}
#endif

	if( !pDBMgr->GetCharBRInfoAll(m_pCharInfo->m_nCID, m_pCharInfo->GetBRInfoMap()) )
	{
		SetResult(MASYNC_RESULT_FAILED);
		return;
	}

	SetResult(MASYNC_RESULT_SUCCEED);
}
Example #9
0
void MAsyncDBJob_InsertQuestGameLog::Run( void* pContext )
{
	if( MSM_TEST == MGetServerConfig()->GetServerMode() ) 
	{
		MMatchDBMgr* pDBMgr = reinterpret_cast< MMatchDBMgr* >( pContext );

		int nQGLID;

		// 우선 퀘스트 게임 로그를 저장함.
		if( !pDBMgr->InsertQuestGameLog(m_szStageName, 
			m_nScenarioID,
			m_nMasterCID, m_PlayersCID[0], m_PlayersCID[1], m_PlayersCID[2],
			m_nTotalRewardQItemCount,
			m_nElapsedPlayTime,
			nQGLID) )
		{
			SetResult(MASYNC_RESULT_FAILED);
			return;
		}

		// 유니크 아이템에 관한 데이터는 QUniqueItemLog에 따로 저장을 해줘야 함.
		int											i;
		int											nCID;
		int											nQIID;
		int											nQUItemCount;
		QItemLogMapIter								itQUItem, endQUItem;
		vector< MQuestPlayerLogInfo* >::iterator	itPlayer, endPlayer;

		itPlayer  = m_Player.begin();
		endPlayer = m_Player.end();

		for( ; itPlayer != endPlayer; ++itPlayer )
		{
			if( (*itPlayer)->GetUniqueItemList().empty() )
				continue;	// 유니크 아이템을 가지고 있지 않으면 무시.

			nCID		= (*itPlayer)->GetCID();
			itQUItem	= (*itPlayer)->GetUniqueItemList().begin();
			endQUItem	= (*itPlayer)->GetUniqueItemList().end();

			for( ; itQUItem != endQUItem; ++itQUItem )
			{
				nQIID			= itQUItem->first;
				nQUItemCount	= itQUItem->second;

				for( i = 0; i < nQUItemCount; ++i )
				{
					if( !pDBMgr->InsertQUniqueGameLog(nQGLID, nCID, nQIID) )
					{
						mlog( "MAsyncDBJob_InsertQuestGameLog::Run - 유니크 아이템 로그 저장 실패. CID:%d QIID:%d\n", 
							nCID, nQIID );

						SetResult(MASYNC_RESULT_FAILED);
					}
				}
			}

			// 작업이 끝난 정보는 메모리에서 삭제한다.
			delete (*itPlayer);
		}
	}

	m_Player.clear();
	
	SetResult(MASYNC_RESULT_SUCCEED);
}
Example #10
0
bool DBQuestCachingData::DoUpdateDBCharQuestItemInfo()
{
	// 퀘스트 서버인지 먼저 검사.
	if( MSM_TEST != MGetServerConfig()->GetServerMode() ) 
		return false;

	// 정상적인 Object인지 검사.
	if( !IsEnabledObject(m_pObject) )
		return false;

	// 현재 상태가 업데이트 가능한지 검사.
	if( !IsRequestUpdate() ) 
	{
		// 다음 업데이트를 검사를 위해서 마지막 업데이트 검사 시간을 저장해 놓음.
		m_dwLastUpdateTime = timeGetTime();
		return false;
	}

	MAsyncDBJob_UpdateQuestItemInfo* pAsyncJob = new MAsyncDBJob_UpdateQuestItemInfo(m_pObject->GetUID());
	if( 0 == pAsyncJob )
	{
		mlog( "DBQuestCachingData::DoUpdateDBCharQuestItemInfo - QuestItemUpdate async작업 실패.\n" );
		return false;
	}
	if( !pAsyncJob->Input(m_pObject->GetCharInfo()->m_nCID, 
		m_pObject->GetCharInfo()->m_QuestItemList, 
		m_pObject->GetCharInfo()->m_QMonsterBible) )
	{
		return false;
	}

	MMatchServer::GetInstance()->PostAsyncJob( pAsyncJob );

#ifdef _DEBUG
	{
		// 업데이트 정보가 정상적으로 되는지 로그를 남김.
		char szDbgOut[ 1000 ] = {0};
		MQuestItemMap::iterator it, end;

		strcat( szDbgOut, "Quest Item Caching UpdateDB\n" );
		strcat( szDbgOut, m_pObject->GetName() );
		strcat( szDbgOut, "\n" );

		it = m_pObject->GetCharInfo()->m_QuestItemList.begin();
		end = m_pObject->GetCharInfo()->m_QuestItemList.end();

		for( ; it != end; ++it )
		{
			char tmp[ 100 ] = {0};
			sprintf( tmp, "%s : %d\n", it->second->GetDesc()->m_szQuestItemName, it->second->GetCount() );
			strcat( szDbgOut, tmp );
		}
		strcat( szDbgOut, "\n" );
		MMatchServer::GetInstance()->LOG( MMatchServer::LOG_PROG, szDbgOut );
	}
#endif

	// 업데이트가 성공하면 다음 검사를 위해서 다시 설정함.
	Reset();

	return true;
}
void MMatchEventFactoryManager::ParseEvent( MXmlElement& chrElement )
{
	char szAttrName[ 128 ];
	char szAttrValue[ 256 ];
	
	DWORD						dwEventListID = 0;
	DWORD						dwEventID = 0;
	string						strEventName;
	string						strAnnounce;
	EVENT_TYPE					EventType;
	DWORD						dwElapsedTime = 0;
	DWORD						dwPercent = 0;
	DWORD						dwRate = 0;
	vector< EventServerType >	vServerType;
	vector< EventGameType >		vGameType;
	SYSTEMTIME					Start, End;
	float						fXPBonusRatio = 0.0f;
	float						fBPBonusRatio = 0.0f;
	vector< EventPartTime >		EventPartTimeVec;

	memset( &Start, 0, sizeof(SYSTEMTIME) );
	memset( &End, 0, sizeof(SYSTEMTIME) );

	const int nAttrCnt = chrElement.GetAttributeCount();
	for( int i = 0; i < nAttrCnt; ++i )
	{
		chrElement.GetAttribute( i, szAttrName, szAttrValue );

		if( 0 == stricmp(EL_EVENT_LIST_ID, szAttrName) )
		{
			dwEventListID = static_cast< DWORD >( atoi(szAttrValue) );
			ASSERT( 0 < dwEventListID );
			continue;
		}

		if( 0 == stricmp(EL_EVENTID, szAttrName) )
		{
			dwEventID = static_cast< DWORD >( atol(szAttrValue) );
			if( NULL == MMatchEventDescManager::GetInstance().Find(dwEventID) )
			{
				ASSERT( 0 && "Event.xml에 없는 Event ID입니다." );
				mlog( "MMatchEventFactoryManager::ParseEvent - Event.xml에 없는 Event ID(%u)입니다.\n",
					dwEventID );
				return;
			}
			continue;
		}

		if( 0 == stricmp(EL_NAME, szAttrName) )
		{
			strEventName = MGetStringResManager()->GetString( string(szAttrValue) );
			continue;
		}

		if( 0 == stricmp(EL_EVENTTYPE, szAttrName) )
		{
			EventType = static_cast< EVENT_TYPE >( atoi(szAttrValue) );
			continue;
		}

		if( 0 == stricmp(EL_ELAPSEDTIME, szAttrName) )
		{
			dwElapsedTime = static_cast< DWORD >( atoi(szAttrValue) );
			continue;
		}

		if( 0 == stricmp(EL_PERCENT, szAttrName) )
		{
			dwPercent = static_cast< DWORD >( atol(szAttrValue) );
			continue;
		}

		if( 0 == stricmp(EL_RATE, szAttrName) )
		{
			dwRate = static_cast< DWORD >( atol(szAttrValue) );
			continue;
		}

		if( 0 == stricmp(EL_ANNOUNCE, szAttrName) )
		{
			strAnnounce = MGetStringResManager()->GetString( string(szAttrValue) );
			continue;
		}

		if( 0 == stricmp(EL_XPBONUS_RATIO, szAttrName) )
		{
			fXPBonusRatio = static_cast<float>( atoi(szAttrValue) ) / 100.0f;
			continue;
		}

		if( 0 == stricmp(EL_BPBONUS_RATIO, szAttrName) )
		{
			fBPBonusRatio = static_cast<float>( atoi(szAttrValue) ) / 100.0f;
			continue;
		}
	}

	MXmlElement chrNode;
	char szTag[ 128 ];
	const int nChrNodeCnt = chrElement.GetChildNodeCount();

	EventPartTimeVec.clear();
	
	for( int j = 0; j < nChrNodeCnt; ++j )
	{
		chrNode = chrElement.GetChildNode( j );
		chrNode.GetTagName( szTag );

		if (szTag[0] == '#') continue;

		if( 0 == stricmp(EL_SERVERTYPE, szTag) )
		{
			ParseServerType( chrNode, vServerType );
			continue;
		}

		if( 0 == stricmp(EL_GAMETYPE, szTag) )
		{
			ParseGameType( chrNode, vGameType );
			continue;
		}

		if( 0 == stricmp(EL_STARTTIME, szTag) )
		{
			ParseStartEndTime( chrNode, Start );
			continue;
		}

		if( 0 == stricmp(EL_ENDTIME, szTag) )
		{
			ParseStartEndTime( chrNode, End );
			continue;
		}

		if( 0 == stricmp(EL_PART_TIME, szTag) )
		{
			ParseEventPartTime(chrNode, EventPartTimeVec );
			continue;
		}
	}

	// check start end time.
	if( !CheckUsableEventTimeByEndTime(End) )
	{
#ifdef _DEBUG
		mlog( "Time out Event(%u:%u.%u.%u.%u~%u.%u.%u.%u)\n", 
			dwEventID,
			Start.wYear, Start.wMonth, Start.wDay, Start.wHour,
			End.wYear, End.wMonth, End.wDay, End.wHour );
#endif
		return;
	}
	
	// check server type.
	vector< EventServerType >::iterator itSvrTyp, endSvrTyp;
	bool bUseEvent = false;
	endSvrTyp = vServerType.end();
	for( itSvrTyp = vServerType.begin(); itSvrTyp != endSvrTyp; ++itSvrTyp )
	{
		// 모든 서버에 적용.
		if( MSM_ALL == itSvrTyp->ServerType )
		{
			bUseEvent = true;
			continue;
		}

		// 현제 서버 타입에만 적용.
		if( MGetServerConfig()->GetServerMode() == itSvrTyp->ServerType )
		{
			bUseEvent = true;
			continue;
		}
	}

	ASSERT( (0 < Start.wYear) && (0 < Start.wMonth) && (0 < Start.wDay) && (0 <= Start.wHour) &&
			(0 < End.wYear) && (0 < End.wMonth) && (0 < End.wDay) && (0 <= End.wHour) );

	// check game type.
	if( bUseEvent )
	{
		EventData ed;
		vector< EventGameType >::iterator itGmTyp, endGmTyp;
		endGmTyp = vGameType.end();
		for( itGmTyp = vGameType.begin(); itGmTyp != endGmTyp; ++itGmTyp )
		{
			// insert event.

			ed.dwEventListID	= dwEventListID;
			ed.dwEventID		= dwEventID;
			ed.EventType		= EventType;
			ed.dwGameType			= itGmTyp->GameType;
			ed.ServerType		= MGetServerConfig()->GetServerMode();
			ed.dwElapsedTime	= dwElapsedTime;
			ed.dwPercent		= dwPercent;
			ed.dwRate			= dwRate;
			ed.Start			= Start;
			ed.End				= End;
			ed.strName			= strEventName;
			ed.strAnnounce		= strAnnounce;
			ed.fXPBonusRatio	= fXPBonusRatio;
			ed.fBPBonusRatio	= fBPBonusRatio;

			ed.EventPartTimeVec.swap( EventPartTimeVec );

			InsertEvent( ed );

			++m_LoadEventSize;
		}		
	}
}