PlayerManager.cpp
上传用户:dzyhzl
上传日期:2019-04-29
资源大小:56270k
文件大小:12k
源码类别:

模拟服务器

开发平台:

C/C++

  1. #include "StdAfx.h"
  2. #include <objbase.h>
  3. #include <initguid.h>
  4. #include <process.h> //Thread define
  5. #include "....s3clientloginLoginDef.h"
  6. #include "....coresrcKProtocol.h"
  7. #include "MGateWay.h"
  8. #include "PlayerManager.h"
  9. #include "define.h"
  10. #include "KRoleDBHeader.h"
  11. #include "KRoleBlockProcess.h"
  12. #include "tstring.h"
  13. #include "Utils.h"
  14. #include "Macro.h"
  15. #include "Exception.h"
  16. using OnlineGameLib::Win32::Output;
  17. using OnlineGameLib::Win32::CException;
  18. using OnlineGameLib::Win32::CCriticalSection;
  19. using OnlineGameLib::Win32::_tstring;
  20. using OnlineGameLib::Win32::ToString;
  21. OnlineGameLib::Win32::CLibrary CPlayerManager::m_sHeavenLib( "heaven.dll" );
  22. OnlineGameLib::Win32::CLibrary CPlayerManager::m_sRainbowLib( "rainbow.dll" );
  23. /*
  24.  * Player server
  25.  */
  26. static const int g_snPSMaxPlayerCount = 5000;
  27. static const int g_snPSPrecision = 10;
  28. static const int g_snPSMaxBuffer = 2000;
  29. static const int g_snPSBufferSize = 1024;
  30. /*
  31.  * Database client
  32.  */
  33. static const int g_scnDBRoleMaxFreeBuffers = 50;
  34. static const int g_scnDBRoleBufferSize = 1024 * 32;
  35. static const size_t g_snPlayerExchangeMemory = 48 * 1024;
  36. #define CALC_MAXFREEBUFFER_BY_COUNT( x ) ( ( ( x ) * 2 / 3 + 3 ) & ~3 );
  37. CPlayerManager::CPlayerManager( ENVIRONMENT &theEnviroment )
  38. : m_hHelperThread( NULL )
  39. , m_theEnviroment( theEnviroment )
  40. , m_pDBRoleClient( NULL )
  41. , m_pPlayerServer( NULL )
  42. {
  43. m_hQuitEvent = ::CreateEvent( NULL, TRUE, FALSE, "PMThread_QuitEvent" );
  44. }
  45. CPlayerManager::~CPlayerManager()
  46. {
  47. SAFE_CLOSEHANDLE( m_hQuitEvent );
  48. SAFE_CLOSEHANDLE( m_hHelperThread );
  49. }
  50. bool CPlayerManager::Create()
  51. {
  52. bool ret = false;
  53. /*
  54.  * Startup thread
  55.  */
  56. try
  57. {
  58. Start();
  59. ret = true;
  60. }
  61. catch( const CException &e )
  62. {
  63. /*
  64.  * Call to unqualified virtual function
  65.  */
  66. Output( _T("CGamePlayer::CGamePlayer() - Exception: ") + e.GetWhere() + _T(" - ") + e.GetMessage() );
  67. }
  68. catch(...)
  69. {
  70. /*
  71.  * Call to unqualified virtual function
  72.  */
  73. Output( _T("CGamePlayer::CGamePlayer() - Unexpected exception") );
  74. }
  75. ret &= StartupNetwork();
  76. return ret;
  77. }
  78. void CPlayerManager::Destroy()
  79. {
  80. ::SetEvent( m_hQuitEvent );
  81. CleanNetwork();
  82. try
  83. {
  84. if ( !Wait( THREAD_TERMINATE_TIMEROUT ) )
  85. {
  86. Terminate( -1 );
  87. }
  88. if ( WAIT_TIMEOUT != ::WaitForSingleObject( m_hHelperThread, THREAD_TERMINATE_TIMEROUT ) )
  89. {
  90. ::TerminateThread( m_hHelperThread, -1 );
  91. }
  92. }
  93. catch( const CException &e )
  94. {
  95. /*
  96.  * Call to unqualified virtual function
  97.  */
  98. Output( _T("CPlayerManager::Run() - Exception: ") + e.GetWhere() + _T(" - ") + e.GetMessage() );
  99. }
  100. catch(...)
  101. {
  102. /*
  103.  * Call to unqualified virtual function
  104.  */
  105. Output( _T("CPlayerManager::Run() - Unexpected exception") );
  106. }
  107. }
  108. int CPlayerManager::Run()
  109. {
  110. while ( WAIT_OBJECT_0 != ::WaitForSingleObject( m_hQuitEvent, 0L ) )
  111. {
  112. CCriticalSection::Owner locker( m_csUsedClientList );
  113. LIST::iterator it;
  114. for ( it = m_usedClientNode.begin(); it != m_usedClientNode.end(); it ++ )
  115. {
  116. size_t index = *it;
  117. /*
  118.  * Get data from player
  119.  */
  120. size_t datalength = 0;
  121. const void *pData = m_pPlayerServer->GetPackFromClient( index, datalength );
  122. while ( pData && datalength )
  123. {
  124. AnalyzePlayerRequire( index, pData, datalength );
  125. pData = m_pPlayerServer->GetPackFromClient( index, datalength );
  126. }
  127. /*
  128.  * Execute work
  129.  */
  130. IPlayer *pPlayer = m_thePlayers[index];
  131. ASSERT( pPlayer );
  132. pPlayer->Run();
  133. }
  134. Sleep( 1 );
  135. }
  136. return 0;
  137. }
  138. void __stdcall CPlayerManager::DBRoleEventNotify( LPVOID lpParam, 
  139. const unsigned long &ulnEventType )
  140. {
  141. CPlayerManager *pPM = reinterpret_cast< CPlayerManager * >( lpParam );
  142. switch( ulnEventType )
  143. {
  144. case enumServerConnectCreate:
  145. SetShowInfo( "RoleDB Connection", "OK", SIF_COLON );
  146. break;
  147. case enumServerConnectClose:
  148. SetShowInfo( "RoleDB Connection", "" );
  149. break;
  150. }
  151. }
  152. void __stdcall CPlayerManager::AccountEventNotify( LPVOID lpParam, 
  153. const unsigned long &ulnEventType )
  154. {
  155. CPlayerManager *pPM = reinterpret_cast< CPlayerManager * >( lpParam );
  156. switch( ulnEventType )
  157. {
  158. case enumServerConnectCreate:
  159. break;
  160. case enumServerConnectClose:
  161. break;
  162. }
  163. }
  164. void __stdcall CPlayerManager::PlayerEventNotify( LPVOID lpParam,
  165. const unsigned long &ulnID,
  166. const unsigned long &ulnEventType )
  167. {
  168. CPlayerManager *pPM = ( CPlayerManager * )( lpParam );
  169. ASSERT( pPM );
  170. pPM->_PlayerEventNotify( ulnID, ulnEventType );
  171. }
  172. void __stdcall CPlayerManager::GameSvrEventNotify( LPVOID lpParam,
  173. const unsigned long &ulnID,
  174. const unsigned long &ulnEventType )
  175. {
  176. switch( ulnEventType )
  177. {
  178. case enumClientConnectCreate:
  179. break;
  180. case enumClientConnectClose:
  181. break;
  182. }
  183. }
  184. void CPlayerManager::_PlayerEventNotify( const unsigned long &ulnID,
  185. const unsigned long &ulnEventType )
  186. {
  187. CCriticalSection::Owner locker( m_csUsedClientList );
  188. switch( ulnEventType )
  189. {
  190. case enumClientConnectCreate:
  191. m_usedClientNode.push_back( ulnID );
  192. break;
  193. case enumClientConnectClose:
  194. PLAYER_MAP::iterator it;
  195. if ( m_thePlayers.end() != ( it = m_thePlayers.find( ulnID ) ) )
  196. {
  197. IPlayer *pPlayer = m_thePlayers[ulnID];
  198. ASSERT( pPlayer );
  199. pPlayer->Destroy( NULL );
  200. }
  201. m_usedClientNode.remove( ulnID );
  202. break;
  203. }
  204. }
  205. bool CPlayerManager::StartupNetwork()
  206. {
  207. bool bDBRoleOK = false;
  208. bool bPlayerServerOK = false;
  209. /*
  210.  * There is connectted the heaven by the rainbow
  211.  */
  212. pfnCreateClientInterface pClientFactroyFun = ( pfnCreateClientInterface )( m_sRainbowLib.GetProcAddress( _T( "CreateInterface" ) ) );
  213. IClientFactory *pClientFactory = NULL;
  214. if ( pClientFactroyFun && SUCCEEDED( pClientFactroyFun( IID_IClientFactory, reinterpret_cast< void ** >( &pClientFactory ) ) ) )
  215. {
  216. pClientFactory->SetEnvironment( g_scnDBRoleMaxFreeBuffers, g_scnDBRoleBufferSize );
  217. pClientFactory->CreateClientInterface( IID_IESClient, reinterpret_cast< void ** >( &m_pDBRoleClient ) );
  218. SAFE_RELEASE( pClientFactory );
  219. }
  220. if ( m_pDBRoleClient )
  221. {
  222. m_pDBRoleClient->Startup();
  223. m_pDBRoleClient->RegisterMsgFilter( reinterpret_cast< void * >( this ), DBRoleEventNotify );
  224. if ( SUCCEEDED( m_pDBRoleClient->ConnectTo( m_theEnviroment.sRoleDBServerIP.c_str(), m_theEnviroment.usRoleDBSvrPort ) ) )
  225. {
  226. bDBRoleOK = true;
  227. }
  228. }
  229. /*
  230.  * We open the heaven to wait for the rainbow
  231.  */
  232. pfnCreateServerInterface pServerFactroyFun = ( pfnCreateServerInterface )( m_sHeavenLib.GetProcAddress( _T( "CreateInterface" ) ) );
  233. IServerFactory *pServerFactory = NULL;
  234. if ( pServerFactroyFun && SUCCEEDED( pServerFactroyFun( IID_IServerFactory, reinterpret_cast< void ** >( &pServerFactory ) ) ) )
  235. {
  236. pServerFactory->SetEnvironment( g_snPSMaxPlayerCount, g_snPSPrecision, g_snPSMaxBuffer, g_snPSBufferSize  );
  237. pServerFactory->CreateServerInterface( IID_IIOCPServer, reinterpret_cast< void ** >( &m_pPlayerServer ) );
  238. pServerFactory->Release();
  239. }
  240. if ( m_pPlayerServer )
  241. {
  242. m_pPlayerServer->Startup();
  243. m_pPlayerServer->RegisterMsgFilter( reinterpret_cast< void * >( this ), PlayerEventNotify );
  244. if ( SUCCEEDED( m_pPlayerServer->OpenService( INADDR_ANY, m_theEnviroment.usClientOpenPort ) ) )
  245. {
  246. bPlayerServerOK = true;
  247. }
  248. }
  249. _tstring msg;
  250. if ( !bDBRoleOK )
  251. {
  252. msg += _T( "It's failed to connect the RoleDB servern" );
  253. }
  254. if ( !bPlayerServerOK )
  255. {
  256. msg += _T( "It's failed to create server for playern" );
  257. }
  258. if ( !msg.empty() )
  259. {
  260. ::MessageBox( NULL, msg.c_str(), "StartupNetwork", MB_ICONSTOP );
  261. }
  262. if ( bDBRoleOK && bPlayerServerOK )
  263. {
  264. CCriticalSection::Owner lock( m_csSystemAction );
  265. /*
  266.  * Setup the Global Allocator
  267.  */
  268. const size_t buffersize = g_snPlayerExchangeMemory;
  269. const size_t maxfreebuffer = CALC_MAXFREEBUFFER_BY_COUNT( m_theEnviroment.lnPlayerMaxCount );
  270. CGamePlayer::SetupGlobalAllocator( buffersize, maxfreebuffer );
  271. /*
  272.  * Initialize all of player
  273.  */
  274. for ( size_t index = 0; index < m_theEnviroment.lnPlayerMaxCount; index ++ )
  275. {
  276. m_freeClientNode.push( index );
  277. IClient *pRoleDBClone = NULL;
  278. m_pDBRoleClient->QueryInterface( IID_IESClient, reinterpret_cast< void ** >( &pRoleDBClone ) );
  279. IServer *pPlayerSvrClone = NULL;
  280. m_pPlayerServer->QueryInterface( IID_IIOCPServer, reinterpret_cast< void ** >( &pPlayerSvrClone ) );
  281. /*
  282.  * Create a player node and add it into list
  283.  */
  284. IPlayer *pPlayer = new CGamePlayer( pPlayerSvrClone, pRoleDBClone, index );
  285. m_thePlayers[index] = pPlayer;
  286. }
  287. /*
  288.  * Initialize a helper thread for network
  289.  */
  290. if ( NULL == m_hHelperThread )
  291. {
  292. unsigned int threadID = 0;
  293. m_hHelperThread = (HANDLE)::_beginthreadex(0,
  294. 0, 
  295. HelperThreadFunction,
  296. ( void * )this,
  297. 0, 
  298. &threadID );
  299. if ( m_hHelperThread == INVALID_HANDLE_VALUE )
  300. {
  301. return false;
  302. }
  303. }
  304. }
  305. return ( bDBRoleOK & bPlayerServerOK );
  306. }
  307. void CPlayerManager::CleanNetwork()
  308. {
  309. if ( m_pDBRoleClient )
  310. {
  311. m_pDBRoleClient->Shutdown();
  312. m_pDBRoleClient->Cleanup();
  313. SAFE_RELEASE( m_pDBRoleClient );
  314. }
  315. if ( m_pPlayerServer )
  316. {
  317. /* CCriticalSection::Owner locker( m_csUsedClientList );
  318. LIST::iterator it;
  319. for ( it = m_usedClientNode.begin(); it != m_usedClientNode.end(); it ++ )
  320. {
  321. size_t index = *it;
  322. m_pPlayerServer->ShutdownClient( index );
  323. }
  324. */
  325. m_pPlayerServer->CloseService();
  326. m_pPlayerServer->Cleanup();
  327. SAFE_RELEASE( m_pPlayerServer );
  328. }
  329. CCriticalSection::Owner lock( m_csSystemAction );
  330. /*
  331.      * Repeat until stack is empty
  332.  */
  333. while ( !m_freeClientNode.empty() )
  334. {
  335. m_freeClientNode.pop();
  336. }
  337. CCriticalSection::Owner locker( m_csUsedClientList );
  338. m_usedClientNode.erase( m_usedClientNode.begin(), m_usedClientNode.end() );
  339. PLAYER_MAP::iterator it;
  340. for ( it = m_thePlayers.begin(); it != m_thePlayers.end(); it ++ )
  341. {
  342. IPlayer *pPlayer = ( IPlayer * )( ( *it ).second );
  343. ASSERT( pPlayer );
  344. pPlayer->Destroy( NULL );
  345. SAFE_DELETE( pPlayer );
  346. }
  347. m_thePlayers.erase( m_thePlayers.begin(), m_thePlayers.end() );
  348. }
  349. unsigned int __stdcall CPlayerManager::HelperThreadFunction( void *pV )
  350. {
  351. int result = 0;
  352. CPlayerManager* pThis = ( CPlayerManager * )pV;
  353.    
  354. if ( pThis )
  355. {
  356. try
  357. {
  358. result = pThis->Helper();
  359. }
  360. catch( ... )
  361. {
  362. }
  363. }
  364. return result;
  365. }
  366. int CPlayerManager::Helper()
  367. {
  368. while ( WAIT_OBJECT_0 != ::WaitForSingleObject( m_hQuitEvent, 0L ) )
  369. {
  370. /*
  371.  * Get data from role-database
  372.  */
  373. size_t dataLength = 0;
  374. const void *pData = m_pDBRoleClient->GetPackFromServer( dataLength );
  375. while( pData && dataLength )
  376. {
  377. KBlock *pBlock = ( KBlock * )( pData );
  378. UINT uID = pBlock->ulIdentity;
  379. if ( uID < m_theEnviroment.lnPlayerMaxCount )
  380. {
  381. IPlayer *pPlayer = m_thePlayers[uID];
  382. ASSERT( pPlayer );
  383. pPlayer->AppendData( pData );
  384. }
  385. pData = m_pDBRoleClient->GetPackFromServer( dataLength );
  386. }
  387. Sleep( 1 );
  388. }
  389. return 0;
  390. }
  391. bool CPlayerManager::AnalyzePlayerRequire( size_t index, const void *pData, size_t datalength )
  392. {
  393. ASSERT( pData && datalength );
  394. BYTE cProtocol = *( const BYTE * )pData;
  395. const BYTE *pBuffer = ( const BYTE * )pData + 1;
  396. ASSERT( pBuffer );
  397. switch ( cProtocol )
  398. {
  399. case c2s_login:
  400. {
  401. KLoginAccountInfo *pLAI = ( KLoginAccountInfo * )pBuffer;
  402. m_thePlayers[index]->Create( pLAI->Account, pLAI->Password );
  403. m_thePlayers[index]->DispatchTask( CGamePlayer::enumLogin );
  404. }
  405. break;
  406. default:
  407. break;
  408. }
  409. return true;
  410. }