#include "stdafx.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mmsystem.h" #include "RylGameServer.h" #include "./Commands/DummyCharacters.h" struct FnDisconnectCharacter { bool operator() (CCharacter* lpCharacter) { if (NULL != lpCharacter) { CGameClientDispatch* lpDispatch = lpCharacter->GetDispatcher(); if (NULL != lpDispatch) { lpDispatch->Disconnect(); } } return true; } }; struct FnRegenHPAndMP { bool operator() (CAggresiveCreature* lpAggresiveCreature) { if (NULL != lpAggresiveCreature) { lpAggresiveCreature->RegenHPAndMP(0, 0, true); } return true; } }; struct FnCSAuth { bool operator() (CCharacter* lpCharacter) { if (NULL != lpCharacter) { // edith 2009.08.11 °ÔÀÓ°¡µå Å×½ºÆ® if (0 == lpCharacter->GetAdminLevel()) { CGameClientDispatch* lpDispatch = lpCharacter->GetDispatcher(); if (NULL != lpDispatch) { /* // edith 2009.08.11 °ÔÀÓ°¡µå 2.5 ¾÷±×·¹À̵å if (false == lpDispatch->IsAuth()) { ERRLOG1(g_Log, "CID:0x%08x °ÔÀÓ °¡µå ÀÎÁõ Äڵ带 º¸³»Áö¾Ê¾Æ ¿¬°áÀ» ²÷½À´Ï´Ù.", lpCharacter->GetCID()); lpDispatch->Disconnect(); return true; } */ GG_AUTH_DATA* lpAuthData = NULL; if (false == lpDispatch->GetAuthQuery(&lpAuthData)) { ERRLOG1(g_Log, "CID:0x%08x °ÔÀÓ °¡µå ÀÎÁõ ÄÚµå(2) üũ¿¡ ½ÇÆÐÇÏ¿© ¿¬°áÀ» ²÷½À´Ï´Ù.", lpCharacter->GetCID()); lpDispatch->Disconnect(); return true; } // edith 2009.08.11 °ÔÀÓ°¡µå 2.5 ¾÷±×·¹À̵å // MessageBox(NULL, "°ÔÀÓ°¡µå ÀÎÁõ ½Ã°£ üũ °á°ú", "GG", MB_OK); return GameClientSendPacket::SendCSAuth(lpDispatch->GetSendStream(), lpCharacter->GetCID(), lpDispatch->GetAuthCode(), lpAuthData, PktBase::NO_SERVER_ERR); } } } return true; } }; struct InstrumentInfo { InstrumentInfo(unsigned long dwIndex, char* szName) : m_dwIndex(dwIndex), m_szName(szName) { } unsigned long m_dwIndex; char* m_szName; }; struct PrepareBroadcastData { void operator() (CCharacter* lpCharacter) { if(0 != lpCharacter) { lpCharacter->GetSerializeData().PrepareData(*lpCharacter); } } void operator() (CMonster* lpMonster) { if(0 != lpMonster) { lpMonster->GetSerializeData().PrepareData(*lpMonster); } } }; enum InstrumentsType { INSTRUMENT_TOTAL_LOOP, INSTRUMENT_CHECK_DELETE_ITEM, INSTRUMENT_REGEN_HP_MP, INSTRUMENT_DBUPDATE, INSTRUMENT_CELLBROADCASTING, INSTRUMENT_GLOBALSPELLMGR, INSTRUMENT_PROCESS_ALL_MONSTER, INSTRUMENT_CHARACTER_LOGOUT, INSTRUMENT_PROCESS_RESPAWN_QUEUE, INSTRUMENT_AUTO_RESPAWN, INSTRUMENT_VIRTUALAREA, INSTRUMENT_RESPAWN, INSTRUMENT_CHAR_SPHERE_TREE, INSTRUMENT_WORLDWEAPON_FIRE, MAX_PERFORMANCE_INSTRUMENTS }; #define DECLARE_INSTRUMENT_INFO(name) InstrumentInfo(name, #name) const InstrumentInfo g_InstrumentInfo[MAX_PERFORMANCE_INSTRUMENTS] = { DECLARE_INSTRUMENT_INFO(INSTRUMENT_TOTAL_LOOP), DECLARE_INSTRUMENT_INFO(INSTRUMENT_CHECK_DELETE_ITEM), DECLARE_INSTRUMENT_INFO(INSTRUMENT_REGEN_HP_MP), DECLARE_INSTRUMENT_INFO(INSTRUMENT_DBUPDATE), DECLARE_INSTRUMENT_INFO(INSTRUMENT_CELLBROADCASTING), DECLARE_INSTRUMENT_INFO(INSTRUMENT_GLOBALSPELLMGR), DECLARE_INSTRUMENT_INFO(INSTRUMENT_PROCESS_ALL_MONSTER), DECLARE_INSTRUMENT_INFO(INSTRUMENT_CHARACTER_LOGOUT), DECLARE_INSTRUMENT_INFO(INSTRUMENT_PROCESS_RESPAWN_QUEUE), DECLARE_INSTRUMENT_INFO(INSTRUMENT_AUTO_RESPAWN), DECLARE_INSTRUMENT_INFO(INSTRUMENT_VIRTUALAREA), DECLARE_INSTRUMENT_INFO(INSTRUMENT_RESPAWN), DECLARE_INSTRUMENT_INFO(INSTRUMENT_CHAR_SPHERE_TREE), DECLARE_INSTRUMENT_INFO(INSTRUMENT_WORLDWEAPON_FIRE) }; #define INSTRUMENT_GAMESERVER(object, name) PERFORMANCE_CHECK(CAutoInstrument (name)((object)[(name)])); class CGameServerProcessThread : public CProcessThread { public: enum { GAME_PROCESS_TICK = 100, TICKS_PER_SECOND = 1000 / GAME_PROCESS_TICK }; CGameServerProcessThread(CRylGameServer& RylGameServer); virtual void InternalRun(CPulse& Pulse); virtual void Cleanup(CPulse& Pulse); private: CRylGameServer& m_RylGameServer; CCreatureManager& m_CreatureManager; CCellManager& m_CellManager; CDuelCellManager& m_DuelCellManager; CGlobalSpellMgr& m_GlobalSpellMgr; CGameLog& m_GameLog; Castle::CCastleMgr& m_CastleMgr; CSiegeObjectMgr& m_SiegeObjectMgr; CCharRespawnMgr& m_CharRespawnMgr; CCharSphereTree& m_CharSphereTree; VirtualArea::CVirtualAreaMgr& m_VirtualAreaMgr; CPerformanceInstrument m_Instruments[MAX_PERFORMANCE_INSTRUMENTS]; std::mem_fun_t m_processMonster; std::mem_fun_ref_t m_processPrepareBroadCast; std::mem_fun1_ref_t m_processBroadCast; }; bool CRylGameServer::AddGameProcessThread() { return AddProcessThread(new CGameServerProcessThread(*this)); } CGameServerProcessThread::CGameServerProcessThread(CRylGameServer& RylGameServer) : CProcessThread(RylGameServer, GAME_PROCESS_TICK), m_RylGameServer(RylGameServer), m_CreatureManager(CCreatureManager::GetInstance()), m_CellManager(CCellManager::GetInstance()), m_VirtualAreaMgr(VirtualArea::CVirtualAreaMgr::GetInstance()), m_DuelCellManager(CDuelCellManager::GetInstance()), m_GlobalSpellMgr(CGlobalSpellMgr::GetInstance()), m_GameLog(CGameLog::GetInstance()), m_CastleMgr(Castle::CCastleMgr::GetInstance()), m_SiegeObjectMgr(CSiegeObjectMgr::GetInstance()), m_processMonster(&CMonster::Process), m_processPrepareBroadCast(&CCell::PrepareBroadCast), m_processBroadCast(&CCell::BroadCast), m_CharRespawnMgr(CCharRespawnMgr::GetInstance()), m_CharSphereTree(CCharSphereTree::GetInstance()) { for(unsigned int nCount = 0; nCount < MAX_PERFORMANCE_INSTRUMENTS; ++nCount) { m_Instruments[nCount].SetName(g_InstrumentInfo[nCount].m_szName); } } void CGameServerProcessThread::Cleanup(CPulse& Pulse) { CLimitUserByIP* lpLimitByIP = m_RylGameServer.GetClientLimit(); if(0 != lpLimitByIP) { // ÀÌÁ¦ºÎÅÍ Á¢¼Ó ±ÝÁö! lpLimitByIP->OperateMode(CLimitUserByIP::DENY_ALL); } // ±æµå ¿ä»õ »óÁ¡ Á¤º¸ ¾÷µ¥ÀÌÆ® m_SiegeObjectMgr.ProcessCampShopUpdate(true); // Ŭ¶óÀÌ¾ðÆ® Á¢¼ÓÀ» ÀüºÎ ²÷°í, DBAgent·Î LogoutÀ» º¸³½´Ù. m_CreatureManager.ProcessAllCharacter(FnDisconnectCharacter()); m_CreatureManager.ProcessAllCharacter(std::bind2nd(std::mem_fun1(&CCharacter::DBUpdateForce), DBUpdateData::LOGOUT)); GET_SINGLE_DISPATCH(lpDBAgentDispatch, CDBAgentDispatch, CDBAgentDispatch::GetDispatchTable()); if(0 != lpDBAgentDispatch) { DBAgentPacketParse::SendServerLogout(*lpDBAgentDispatch); SERLOG1(g_Log, "this:0x%p/try client logout process", this); CIOCPNet* lpIOCPNet = m_RylGameServer.GetIOCPNet(); if(0 != lpIOCPNet) { // 10Ãʰ£ ´ë±â. unsigned long dwTotalWaitPulse = 10 * Pulse.GetTicksPerSec(); unsigned long dwStartPulse = Pulse.GetCurrentPulse(); // ¼­¹ö ·Î±×¾Æ¿ôÀ» ¹ÞÀ¸¸é Áß°è Á¢¼ÓÀ» ²÷±â ¶§¹®¿¡, Áß°è Á¢¼ÓÀÌ ²÷±æ¶§±îÁö ·çÇÁ¸¦ µ·´Ù. while(!CDBAgentDispatch::GetDispatchTable().IsEmpty() && dwTotalWaitPulse < Pulse.GetCurrentPulse() - dwStartPulse) { Pulse.CheckSleep(); lpIOCPNet->Process(); } } SERLOG2(g_Log, "this:0x%p/client logout process finish (%s)", this, CDBAgentDispatch::GetDispatchTable().IsEmpty() ? "Finish complete" : "Timeout"); } // ¸ðµç Å©¸®Ãĸ¦ Á¦°ÅÇÑ´Ù. CCreatureManager::GetInstance().DestroyAll(); CDummyCharacterList::GetInstance().Destroy(); // ¼¿À» Á¦°ÅÇÑ´Ù. CCellManager::GetInstance().Destroy(); GetFunctionTimingResult("RowGameServer"); } void CGameServerProcessThread::InternalRun(CPulse& Pulse) { unsigned long dwCurrentPulse = Pulse.GetCurrentPulse(); // °ÔÀÓ ·Î±× ½Ã°£À» ¾÷µ¥ÀÌÆ® m_GameLog.UpdateLogTime(); INSTRUMENT_GAMESERVER(m_Instruments, INSTRUMENT_TOTAL_LOOP); // ½ºÆç(æƮ&ÀÎæƮ) ó¸® (1ÃÊ´ÜÀ§·Î ó¸®) if (0 == (dwCurrentPulse % (1 * TICKS_PER_SECOND))) { INSTRUMENT_GAMESERVER(m_Instruments, INSTRUMENT_GLOBALSPELLMGR); m_GlobalSpellMgr.Process(); } // ÀÏÁ¤ ½Ã°£ ´ÜÀ§·Î ¸Ê¿¡¼­ ¾ÆÀÌÅÛÀ» Áö¿ì´Â ó¸® assert(1 < CCell::CHECK_TIME && "ÆÞ½º ¼¼ÆÃ¿¡ ¹®Á¦°¡ ÀÖ½À´Ï´Ù."); if (1 == (dwCurrentPulse % CCell::CHECK_TIME)) { INSTRUMENT_GAMESERVER(m_Instruments, INSTRUMENT_CHECK_DELETE_ITEM); m_CellManager.ProcessAllCell(std::mem_fun_ref(&CCell::CheckDeleteItem)); m_VirtualAreaMgr.ProcessDeleteItem(); } // ¸ó½ºÅÍ Ã³¸® (0.2 ÃÊ¿¡ Çѹø ó¸®) if (1 == (dwCurrentPulse % 2)) { INSTRUMENT_GAMESERVER(m_Instruments, INSTRUMENT_PROCESS_ALL_MONSTER); m_CreatureManager.ProcessAllMonster(m_processMonster); m_SiegeObjectMgr.ProcessAllSiegeObject(); m_VirtualAreaMgr.ProcessAllMonster(); } // ¸ó½ºÅÍ¿Í Ç÷¹À̾îÀÇ Regen ó¸® assert(2 < CAggresiveCreature::REGEN_TIME && "ÆÞ½º ¼¼ÆÃ¿¡ ¹®Á¦°¡ ÀÖ½À´Ï´Ù."); if (2 == (dwCurrentPulse % CAggresiveCreature::REGEN_TIME)) { INSTRUMENT_GAMESERVER(m_Instruments, INSTRUMENT_REGEN_HP_MP); m_CreatureManager.ProcessAllMonster(FnRegenHPAndMP()); m_CreatureManager.ProcessAllCharacter(FnRegenHPAndMP()); m_VirtualAreaMgr.ProcessMonsterRegenHPAndMP(); m_CastleMgr.ProcessEmblemRegenHPAndMP(); m_SiegeObjectMgr.ProcessCampRegenHPAndMP(); } // °¡»ó¸Ê ó¸® assert(2 < VirtualArea::CVirtualAreaMgr::VIRTUALAREA_PULSE && "ÆÞ½º ¼¼ÆÃ¿¡ ¹®Á¦°¡ ÀÖ½À´Ï´Ù."); if (2 == (dwCurrentPulse % VirtualArea::CVirtualAreaMgr::VIRTUALAREA_PULSE)) { INSTRUMENT_GAMESERVER(m_Instruments, INSTRUMENT_VIRTUALAREA); m_VirtualAreaMgr.ProcessAllVirtualArea(); } // DBUpdate ó¸® assert(3 < CCharacter::DBUPDATE_PULSE && "ÆÞ½º ¼¼ÆÃ¿¡ ¹®Á¦°¡ ÀÖ½À´Ï´Ù."); if (3 == (dwCurrentPulse % (CCharacter::DBUPDATE_PULSE))) { INSTRUMENT_GAMESERVER(m_Instruments, INSTRUMENT_DBUPDATE); // ij¸¯ÅÍ Á¤º¸ m_CreatureManager.ProcessAllCharacter( std::bind2nd(std::mem_fun1(&CCharacter::DBUpdate), DBUpdateData::UPDATE)); // ±æµå ¿ä»õ »óÁ¡ Á¤º¸ m_SiegeObjectMgr.ProcessCampShopUpdate(false); } // ij¸¯ÅÍ ·Î±×¾Æ¿ô ó¸®, ¼Òȯ ¸ó½ºÅÍÀÇ »ç¸Á ó¸® assert(3 < CCharacter::LOGOUT_PULSE && "ÆÞ½º ¼¼ÆÃ¿¡ ¹®Á¦°¡ ÀÖ½À´Ï´Ù."); if (3 == (dwCurrentPulse % CCharacter::LOGOUT_PULSE)) { INSTRUMENT_GAMESERVER(m_Instruments, INSTRUMENT_CHARACTER_LOGOUT); m_CreatureManager.ProcessCharacterLogout(); m_CreatureManager.ProcessSummonMonsterDead(); m_VirtualAreaMgr.ProcessSummonMonsterDead(); } // °øÇå ¸Þ´Þ ³ª´²ÁÖ±â // ¹èƲ ±×¶ó¿îµå, ¹èƲ ¼­¹ö¿¡¼­ ÀáÀÚ´Â ½Ãü ÀÚµ¿ ¸®½ºÆù ó¸® // ¹èƲ ±×¶ó¿îµå ¼®»ó »óÅ ó¸® (ÀüÅõ »óÅÂ, ÈÞ½Ä »óÅÂ) assert(3 < CCharacter::BATTLE_GROUND_PULSE && "ÆÞ½º ¼¼ÆÃ¿¡ ¹®Á¦°¡ ÀÖ½À´Ï´Ù."); if (3 == (dwCurrentPulse % CCharacter::BATTLE_GROUND_PULSE)) { INSTRUMENT_GAMESERVER(m_Instruments, INSTRUMENT_AUTO_RESPAWN); m_CreatureManager.ProcessBattleGround(); } // Ŭ¶óÀÌ¾ðÆ® ºê·Îµå ij½ºÆÃ assert(4 < CCell::BROADCASTING_TIME && "ÆÞ½º ¼¼ÆÃ¿¡ ¹®Á¦°¡ ÀÖ½À´Ï´Ù."); if (4 == (dwCurrentPulse % CCell::BROADCASTING_TIME)) { INSTRUMENT_GAMESERVER(m_Instruments, INSTRUMENT_CELLBROADCASTING); CCreatureManager::GetInstance().ProcessAllCharacter(PrepareBroadcastData()); CCreatureManager::GetInstance().ProcessAllMonster(PrepareBroadcastData()); m_CellManager.ProcessAllCell(m_processPrepareBroadCast); m_CellManager.ProcessAllCell(m_processBroadCast, dwCurrentPulse); m_DuelCellManager.ProcessAllCell(m_processPrepareBroadCast); m_DuelCellManager.ProcessAllCell(m_processBroadCast, dwCurrentPulse); m_VirtualAreaMgr.ProcessAllCellPrepareBroadCast(); m_VirtualAreaMgr.ProcessAllCellBroadCast(dwCurrentPulse); m_SiegeObjectMgr.PrepareBroadCast(); m_SiegeObjectMgr.BroadCast(); } // ¸®½ºÆù Å¥ ÇÁ·Î¼¼½º (1 ÃÊ´ÜÀ§·Î ¹èƲ±×¶ó¿îµå¸¸ Àû¿ë) assert(7 < (1 * TICKS_PER_SECOND) && "ÆÞ½º ¼¼ÆÃ¿¡ ¹®Á¦°¡ ÀÖ½À´Ï´Ù."); if (7 == (dwCurrentPulse % (1 * TICKS_PER_SECOND))) { if (SERVER_ID::ZONE3 == CServerSetup::GetInstance().GetServerZone()) { INSTRUMENT_GAMESERVER(m_Instruments, INSTRUMENT_PROCESS_RESPAWN_QUEUE); m_CreatureManager.ProcessRespawnQueue(); } } // ¸®½ºÆù ÇÁ·Î¼¼½º (1 ÃÊ´ÜÀ§·Î) assert(7 < (1 * TICKS_PER_SECOND) && "ÆÞ½º ¼¼ÆÃ¿¡ ¹®Á¦°¡ ÀÖ½À´Ï´Ù."); if (7 == (dwCurrentPulse % (1 * TICKS_PER_SECOND))) { if (SERVER_ID::ZONE3 != CServerSetup::GetInstance().GetServerZone()) { INSTRUMENT_GAMESERVER(m_Instruments, INSTRUMENT_RESPAWN); m_CharRespawnMgr.ProcessRespawn(); } } // ij¸¯ÅÍ ½ºÇÇ¾î Æ®¸® °»½Å assert(8 < (1 * TICKS_PER_SECOND) && "ÆÞ½º ¼¼ÆÃ¿¡ ¹®Á¦°¡ ÀÖ½À´Ï´Ù."); if (8 == (dwCurrentPulse % (1 * TICKS_PER_SECOND))) { INSTRUMENT_GAMESERVER(m_Instruments, INSTRUMENT_CHAR_SPHERE_TREE); m_CharSphereTree.Process(); } // 1ÃÊ ´ÜÀ§·Î ¿ùµå ¿þÆù ¹ß»ç ó¸® assert(9 < (1 * TICKS_PER_SECOND) && "ÆÞ½º ¼¼ÆÃ¿¡ ¹®Á¦°¡ ÀÖ½À´Ï´Ù."); if (9 == (dwCurrentPulse % (1 * TICKS_PER_SECOND))) { INSTRUMENT_GAMESERVER(m_Instruments, INSTRUMENT_WORLDWEAPON_FIRE); m_SiegeObjectMgr.ProcessWorldWeaponFire(); } // 3ÃÊ´ÜÀ§·Î ÆÄƼ ÀüºÎ µ¹¸é¼­ ÆÄƼ Á¤º¸ ¾÷µ¥ÀÌÆ® if (0 == (dwCurrentPulse % (3 * TICKS_PER_SECOND))) { CPartyMgr::GetInstance().UpdatePartyData(); } // 3ÃÊ´ÜÀ§·Î ÄÜ¼Ö Á¤º¸ ¾÷µ¥ÀÌÆ® if (0 == (dwCurrentPulse % (3 * TICKS_PER_SECOND))) { m_RylGameServer.PrintServerInfo(); m_RylGameServer.PrintStatistics(); } // 2ÃÊ ´ÜÀ§·Î °ÔÀÓ ½Ã°£ Á¤º¸ ¾÷µ¥ÀÌÆ® if (0 == (dwCurrentPulse % (2 *TICKS_PER_SECOND))) { CGameTimeMgr::GetInstance().UpdateGameTimeInfo(); } // ÆÛÆ÷¸Õ½º ·Î±× Ãâ·Â (1½Ã°£¿¡ ÇÑ ¹ø¾¿) if (0 == (dwCurrentPulse % (60 * 60 * TICKS_PER_SECOND))) { GetFunctionTimingResult("RowGameServer"); } // ¿¬°á Á¤º¸ ¼¼ÆÃ (DBÁß°è, äÆÃ) if (0 == (dwCurrentPulse % (5 * TICKS_PER_SECOND))) { unsigned long dwStatusFlag = 0; if(!CDBAgentDispatch::GetDispatchTable().IsEmpty()) { dwStatusFlag |= (1 << CServerSetup::AgentServer); } if(!CChatDispatch::GetDispatchTable().IsEmpty()) { dwStatusFlag |= (1 << CServerSetup::ChatServer); } m_RylGameServer.SetStatusFlag(dwStatusFlag); } #ifdef AUTH_MY m_RylGameServer.Update( dwCurrentPulse ); #endif #ifndef NO_GAMEGUARD // °ÔÀÓ°¡µå ÀÎÁõ (3ºÐ¿¡ Çѹø¾¿) if (0 == (dwCurrentPulse % (3 * 60 * TICKS_PER_SECOND))) { // edith 2009.08.11 °ÔÀÓ°¡µå 2.5 ¾÷±×·¹À̵å if (true == CServerSetup::GetInstance().GetHackCheck()) { m_CreatureManager.ProcessAllCharacter(FnCSAuth()); } } #endif // Äù½ºÆ® ó¸®. CQuestMgr::GetInstance().ProcessPendingQuest(); /* // ¹ÝÀÀ¼ºÀ» ³ôÀ̱â À§Çؼ­, ½Ã°£ÀÌ ³²À¸¸é ÆÐŶ ó¸®Á» ´õ ÇØ ÁØ´Ù. CIOCPNet* lpIOCPNet = m_RylGameServer.GetIOCPNet(); if(0 != lpIOCPNet) { const unsigned long dwMinSleepTime = 10; while(dwMinSleepTime < Pulse.GetRemainTime()) { lpIOCPNet->Process(); } } */ }