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

模拟服务器

开发平台:

C/C++

  1. #include "StdAfx.h"
  2. #include "GamePlayer.h"
  3. #include "....s3clientloginLoginDef.h"
  4. #include "....coresrcKProtocol.h"
  5. #include "Macro.h"
  6. #include "define.h"
  7. #include "ICommand.h"
  8. #include "KRoleDBHeader.h"
  9. #include "KRoleBlockProcess.h"
  10. #include "Utils.h"
  11. #include "Macro.h"
  12. #include "Exception.h"
  13. #include "Buffer.h"
  14. using OnlineGameLib::Win32::Output;
  15. using OnlineGameLib::Win32::CException;
  16. using OnlineGameLib::Win32::CCriticalSection;
  17. using OnlineGameLib::Win32::ToString;
  18. using OnlineGameLib::Win32::Trace;
  19. using OnlineGameLib::Win32::_tstring;
  20. using OnlineGameLib::Win32::CBuffer;
  21. static const size_t g_scNetworkBlockSize = 1000;
  22. OnlineGameLib::Win32::CBuffer::Allocator CGamePlayer::m_theGlobalAllocator( 1024, 10 );
  23. LONG CGamePlayer::m_slnIdentityCounts = 0L;
  24. /*
  25.  * CGamePlayer Global Function
  26.  */
  27. bool CGamePlayer::SetupGlobalAllocator( size_t bufferSize, size_t maxFreeBuffers )
  28. {
  29. return CGamePlayer::m_theGlobalAllocator.ReSet( bufferSize, maxFreeBuffers );
  30. }
  31. /*
  32.  * CGamePlayer::CTask
  33.  */
  34. CGamePlayer::CTask::CTask()
  35. {
  36. ASSERT( FALSE );
  37. }
  38. CGamePlayer::CTask::~CTask()
  39. {
  40. CCriticalSection::Owner lock( m_cs );
  41. stdVector::iterator theIterator;
  42. for ( theIterator = m_stdCommand.begin(); theIterator != m_stdCommand.end(); theIterator ++ )
  43. {
  44. ICommand *pCmd = reinterpret_cast< ICommand* >( *theIterator );
  45. SAFE_DELETE( pCmd );
  46. }
  47. m_stdCommand.clear();
  48. }
  49. CGamePlayer::CTask::CTask( CGamePlayer *pReceiver, UINT nTaskID, UINT nNextTaskID /*enumComplete*/ )
  50. : m_pReceiver( pReceiver )
  51. , m_indexCmd( 0 )
  52. , m_nTaskProgID( nTaskID )
  53. , m_nNextTaskID( nNextTaskID )
  54. {
  55. }
  56. size_t CGamePlayer::CTask::AddCmd( Action pFun, UINT unFaildValue /*enumNone*/ )
  57. {
  58. CCriticalSection::Owner lock( m_cs );
  59. /*
  60.  * Convert a status to the other status
  61.  */
  62. UINT unFaildTaskID = unFaildValue;
  63. switch ( unFaildValue )
  64. {
  65. case enumRepeat:
  66. unFaildTaskID = m_nTaskProgID;
  67. break;
  68. default:
  69. unFaildTaskID = unFaildValue;
  70. break;
  71. }
  72. /*
  73.  * Generate a command and push it into the task queue
  74.  */
  75. ICommand *pCmd = new CTaskCommand< CGamePlayer >( m_pReceiver, pFun, unFaildTaskID );
  76. m_stdCommand.push_back( reinterpret_cast< void* >( pCmd ) );
  77. size_t id = m_stdCommand.size();
  78. return id;
  79. }
  80. UINT CGamePlayer::CTask::Execute()
  81. {
  82. CCriticalSection::Owner lock( m_cs );
  83. if ( m_indexCmd < m_stdCommand.size() )
  84. {
  85. ICommand *pCmd = reinterpret_cast< ICommand * >( m_stdCommand[m_indexCmd] );
  86. ASSERT( pCmd );
  87. if ( !pCmd->Execute() )
  88. {
  89. return pCmd->GetFaildValue();
  90. }
  91. m_indexCmd ++;
  92. return m_nTaskProgID;
  93. }
  94. Reset();
  95. return m_nNextTaskID;
  96. }
  97. /*
  98.  * CGamePlayer class
  99.  */
  100. CGamePlayer::CDataQueue::~CDataQueue()
  101. {
  102. CCriticalSection::Owner locker( m_csQueue );
  103. m_theData.erase( m_theData.begin(), m_theData.end() );
  104. }
  105. void CGamePlayer::CDataQueue::Empty()
  106. {
  107. CCriticalSection::Owner locker( m_csQueue );
  108. m_theData.erase( m_theData.begin(), m_theData.end() );
  109. }
  110. size_t CGamePlayer::CDataQueue::Push( LONG lnID, const void *pData )
  111. {
  112. CCriticalSection::Owner locker( m_csQueue );
  113. m_theData.insert( stdMap::value_type( lnID, pData ) );
  114. //m_theData[lnID] = pData;
  115. return m_theData.size();
  116. }
  117. const void *CGamePlayer::CDataQueue::Top( LONG lnID )
  118. {
  119. CCriticalSection::Owner locker( m_csQueue );
  120. stdMap::iterator it;
  121. if ( m_theData.end() != ( it = m_theData.find( lnID ) ) )
  122. {
  123. return m_theData[lnID];
  124. }
  125. return NULL;
  126. }
  127. size_t CGamePlayer::CDataQueue::Pop( LONG lnID )
  128. {
  129. CCriticalSection::Owner locker( m_csQueue );
  130. size_t size = m_theData.size();
  131. stdMap::iterator it;
  132. if ( m_theData.end() != ( it = m_theData.find( lnID ) ) )
  133. {
  134. m_theData.erase( lnID );
  135. size = m_theData.size();
  136. }
  137. return size;
  138. }
  139. /*
  140.  * CGamePlayer class
  141.  */
  142. CGamePlayer::CGamePlayer( IServer *pPlayerSender, IClient *pRoleDBSender, LONG nIdentityID /*-1*/ )
  143. : m_lnIdentityID( nIdentityID )
  144. , m_theLoginTask( this, enumLogin )
  145. , m_theLogoutTask( this, enumLogOut )
  146. , m_theExchangeReginTask( this, enumExchangeRegin )
  147. , m_pRoleDBSender( pRoleDBSender )
  148. , m_pPlayerServer( pPlayerSender )
  149. {
  150. ASSERT( m_pRoleDBSender );
  151. /*
  152.  * Resize block buffer
  153.  */
  154. m_sBlockBuffer.resize( g_scNetworkBlockSize );
  155. SetCurrentTask( enumNone );
  156. LONG lnID = ::InterlockedExchangeAdd( &m_slnIdentityCounts, 1 );
  157. m_lnIdentityID = ( m_lnIdentityID < 0 ) ? lnID : m_lnIdentityID;
  158. InitEventProcessor();
  159. InitTaskProcessor();
  160. }
  161. CGamePlayer::~CGamePlayer()
  162. {
  163. SAFE_RELEASE( m_pRoleDBSender );
  164. ::InterlockedExchangeAdd( &m_slnIdentityCounts, -1 );
  165. }
  166. bool CGamePlayer::DispatchTask( LONG lnTaskID )
  167. {
  168. if ( IsWorking() )
  169. {
  170. /*
  171.  * This player is processing a special tasks
  172.  */
  173. return false;
  174. }
  175. SetCurrentTask( lnTaskID );
  176. return true;
  177. }
  178. void CGamePlayer::InitTaskProcessor()
  179. {
  180. m_theLoginTask.AddCmd( &CGamePlayer::QueryAccPwd );
  181. m_theLoginTask.AddCmd( &CGamePlayer::VerifyAccount );
  182. m_theLoginTask.AddCmd( &CGamePlayer::QueryRoleList );
  183. m_theLoginTask.AddCmd( &CGamePlayer::GetRoleListInfo, enumRepeat );
  184. m_theLoginTask.AddCmd( &CGamePlayer::QueryRoleInfo );
  185. m_theLoginTask.AddCmd( &CGamePlayer::ProcessRoleInfo, enumRepeat );
  186. }
  187. int CGamePlayer::Run()
  188. {
  189. (this->*EventProcessor[enumWorkEvent])();
  190. return 0;
  191. }
  192. bool CGamePlayer::AppendData( const void *pData )
  193. {
  194. TProcessData *pBlock = m_theRoleStreamVein.Block_IN( reinterpret_cast< const KBlock * >( pData ) );
  195. if ( pBlock )
  196. {
  197. switch ( pBlock->nProtoId )
  198. {
  199. case PROTOL_GETROLELIST:
  200. m_theDataQueue.Push( PROTOL_GETROLELIST, reinterpret_cast< const void * >( pBlock->pDataBuffer ) );
  201. break;
  202. case PROTOL_LOADROLE:
  203. m_theDataQueue.Push( PROTOL_LOADROLE, reinterpret_cast< const void * >( pBlock->pDataBuffer ) );
  204. break;
  205. default:
  206. break;
  207. }
  208. }
  209. return true;
  210. }
  211. bool CGamePlayer::Create( const char * const pName, const char * const pPassword )
  212. {
  213. if ( NULL == pName )
  214. {
  215. return false;
  216. }
  217. m_sAccountName = pName;
  218. m_sPassword = pPassword ? pPassword : "";
  219. return true;
  220. }
  221. bool CGamePlayer::Destroy( const char * const pPassword )
  222. {
  223. _tstring sPassword;
  224. sPassword = pPassword ? pPassword : "";
  225. if ( m_sPassword.compare( sPassword ) )
  226. {
  227. return false;
  228. }
  229. return true;
  230. }
  231. void CGamePlayer::InitEventProcessor()
  232. {
  233. ZeroMemory( EventProcessor, sizeof(EventProcessor) );
  234. EventProcessor[enumQuitEvent] = Quit;
  235. EventProcessor[enumWorkEvent] = Work;
  236. }
  237. bool CGamePlayer::Quit()
  238. {
  239. return true;
  240. }
  241. bool CGamePlayer::Work()
  242. {
  243. LONG lnNextTask = enumNone;
  244. switch ( GetCurrentTask() )
  245. {
  246. case enumLogin:
  247. lnNextTask = m_theLoginTask.Execute();
  248. SetCurrentTask( lnNextTask );
  249. break;
  250. case enumLogOut:
  251. lnNextTask = m_theLogoutTask.Execute();
  252. SetCurrentTask( lnNextTask );
  253. break;
  254. case enumExchangeRegin:
  255. lnNextTask = m_theExchangeReginTask.Execute();
  256. SetCurrentTask( lnNextTask );
  257. break;
  258. case enumComplete:
  259. lnNextTask = TaskCompleted() ? enumNone : enumComplete;
  260. SetCurrentTask( lnNextTask );
  261. break;
  262. case enumNone:
  263. default:
  264. break;
  265. }
  266. return true;
  267. }
  268. bool CGamePlayer::TaskCompleted()
  269. {
  270. Trace( ToString( m_lnIdentityID ), "CGamePlayer::TaskCompleted" );
  271. m_theDataQueue.Empty();
  272. /*
  273.  * Clear some role data
  274.  */
  275. m_theRoleStreamVein.ClearINStream( ( size_t )( -1 ) );
  276. return true;
  277. }
  278. /*
  279.  * Task function
  280.  */
  281. bool CGamePlayer::QueryAccPwd()
  282. {
  283. Trace( ToString( m_lnIdentityID ), "CGamePlayer::QueryAccPwd -> Begin" );
  284. Trace( ToString( m_lnIdentityID ), "CGamePlayer::QueryAccPwd -> End" );
  285. return true;
  286. }
  287. bool CGamePlayer::VerifyAccount()
  288. {
  289. Trace( ToString( m_lnIdentityID ), "CGamePlayer::VerifyAccount -> Begin" );
  290. KLoginAccountInfo lai;
  291. ZeroMemory( &lai, sizeof( KLoginAccountInfo ) );
  292. /*
  293.  * Account
  294.  */
  295. size_t used = sizeof( lai.Account );
  296. used = ( used > m_sAccountName.length() ) ? m_sAccountName.length() : used;
  297. memcpy( lai.Account, m_sAccountName.c_str(), used );
  298. /*
  299.  * Password
  300.  */
  301. used = sizeof( lai.Password );
  302. used = ( used > m_sPassword.length() ) ? m_sPassword.length() : used;
  303. memcpy( lai.Password, m_sPassword.c_str(), used );
  304. /*
  305.  * The other info
  306.  */
  307. lai.Param = LOGIN_A_LOGIN | LOGIN_R_SUCCESS; /* LOGIN_R_FAILED | LOGIN_R_ACCOUNT_OR_PASSWORD_ERROR */
  308. lai.Size = sizeof( lai );
  309. CBuffer *pBuffer = m_theGlobalAllocator.Allocate();
  310. BYTE *pData = const_cast< BYTE * >( pBuffer->GetBuffer() );
  311. BYTE bProtocol = s2c_login;
  312. size_t sizeProtocol = sizeof( BYTE );
  313. memcpy( pData, &bProtocol, sizeProtocol );
  314. memcpy( pData + sizeProtocol, ( BYTE * )( &lai ), sizeof( lai ) );
  315. pBuffer->Use( lai.Size + sizeof( BYTE )/* protocol id */ );
  316. m_pPlayerServer->PreparePackSink();
  317. m_pPlayerServer->PackDataToClient( m_lnIdentityID, pBuffer->GetBuffer(), pBuffer->GetUsed() );
  318. m_pPlayerServer->SendPackToClient();
  319. pBuffer->Release();
  320. Trace( ToString( m_lnIdentityID ), "CGamePlayer::VerifyAccount -> End" );
  321. return true;
  322. }
  323. bool CGamePlayer::QueryRoleList()
  324. {
  325. Trace( ToString( m_lnIdentityID ), "CGamePlayer::QueryRoleList -> Begin" );
  326. const size_t lenAN = m_sAccountName.length();
  327. const size_t lenPL = lenAN + sizeof( TStreamData );
  328. /*
  329.  * Require to get rolelist from the role-db server.
  330.  */
  331. CBuffer *pBuffer = m_theGlobalAllocator.Allocate();
  332. TStreamData *pPlayerList = reinterpret_cast< TStreamData * >( const_cast< BYTE * >( pBuffer->GetBuffer() ) );
  333. ASSERT( pPlayerList );
  334. pPlayerList->nProtoId = PROTOL_GETROLELIST;
  335. pPlayerList->nDataLen = lenAN + 1;
  336. pPlayerList->ulNetId = 0;
  337. pPlayerList->ulIdentity = m_lnIdentityID;
  338. pPlayerList->pDataBuffer[0] = enumRoleListCount;
  339. memcpy( &pPlayerList->pDataBuffer[1], m_sAccountName.c_str(), lenAN );
  340. pBuffer->Use( lenPL );
  341. /*
  342.  * Send this information to role database server
  343.  */
  344. KRoleBlockProcess theRoleBlocks( pPlayerList, lenPL );
  345. for ( size_t block = 0; block < theRoleBlocks.GetBlockCount( g_scNetworkBlockSize ); block ++ )
  346. {
  347. KBlock *pBlock = reinterpret_cast< KBlock * >( const_cast< char * >( m_sBlockBuffer.c_str() ) );
  348. size_t sizeBlock = theRoleBlocks.GetBlockPtr( pBlock, block, g_scNetworkBlockSize );
  349. m_pRoleDBSender->SendPackToServer( pBlock, sizeBlock );
  350. }
  351. pBuffer->Release();
  352. Trace( ToString( m_lnIdentityID ), "CGamePlayer::QueryRoleList -> End" );
  353. return true;
  354. }
  355. bool CGamePlayer::GetRoleListInfo()
  356. {
  357. Trace( ToString( m_lnIdentityID ), "CGamePlayer::GetRoleListInfo -> Begin" );
  358. bool ok = false;
  359. const void *pData = NULL;
  360. if ( NULL != ( pData = m_theDataQueue.Top( PROTOL_GETROLELIST ) ) )
  361. {
  362. int nRoleCount = *( char * )pData;
  363. const S3DBI_RoleBaseInfo *pRoleList = ( const S3DBI_RoleBaseInfo * )( ( const char * )pData + 1/* sizeof( char ) */ );
  364. const size_t datalength = sizeof( S3DBI_RoleBaseInfo ) * nRoleCount;
  365. if ( nRoleCount > 0 && nRoleCount <= enumRoleListCount && pRoleList )
  366. {
  367. ZeroMemory ( m_theRoleDBList, sizeof( S3DBI_RoleBaseInfo ) * enumRoleListCount );
  368. for ( int no = 0; no < nRoleCount; no ++ )
  369. {
  370. memcpy( &m_theRoleDBList[no], &pRoleList[no], sizeof( S3DBI_RoleBaseInfo ) );
  371. Trace( ToString( m_lnIdentityID ), m_theRoleDBList[no].szRoleName );
  372. }
  373. /*
  374.  * Send this info to player
  375.  */
  376. KRoleBlockProcess theRoleBlocks( ( const TStreamData * )pData, datalength );
  377. for ( size_t block = 0; block < theRoleBlocks.GetBlockCount( g_scNetworkBlockSize ); block ++ )
  378. {
  379. m_pPlayerServer->PreparePackSink();
  380. KBlock *pBlock = reinterpret_cast< KBlock * >( const_cast< char * >( m_sBlockBuffer.c_str() ) );
  381. size_t sizeBlock = theRoleBlocks.GetBlockPtr( pBlock, block, g_scNetworkBlockSize );
  382. m_pPlayerServer->PackDataToClient( m_lnIdentityID, pBlock, sizeBlock );
  383. m_pPlayerServer->SendPackToClient();
  384. }
  385. ok = true;
  386. }
  387. m_theDataQueue.Pop( PROTOL_GETROLELIST );
  388. }
  389. Trace( ToString( m_lnIdentityID ), "CGamePlayer::GetRoleListInfo -> End" );
  390. return ok;
  391. }
  392. bool CGamePlayer::QueryRoleInfo()
  393. {
  394. Trace( ToString( m_lnIdentityID ), "CGamePlayer::QueryRoleInfo -> Begin" );
  395. enum enumProcessRoleInfo
  396. {
  397. enumCreateRole,
  398. enumQueryRoleInfo,
  399. enumError
  400. };
  401. ZeroMemory( &m_theRoleInfomation, sizeof( tagRoleInfomation ) );
  402. // TEMPORAL
  403. m_theRoleInfomation.nIndexInList = 0;
  404. UINT nProcessor = enumQueryRoleInfo;
  405. switch ( nProcessor )
  406. {
  407. case enumQueryRoleInfo:
  408. {
  409. /*
  410.  * Query player information
  411.  */
  412. // TEMPORAL
  413. _tstring  sRoleName = m_theRoleDBList[ m_theRoleInfomation.nIndexInList ].szRoleName;
  414. const size_t lenRN = sRoleName.length();
  415. const size_t lenRI = sizeof( TStreamData ) - 1 + lenRN;
  416. CBuffer *pBuffer = m_theGlobalAllocator.Allocate();
  417. TStreamData *pRoleInfo = reinterpret_cast< TStreamData * >( const_cast< BYTE * >( pBuffer->GetBuffer() ) );
  418. ASSERT( pRoleInfo );
  419. pRoleInfo->nProtoId = PROTOL_LOADROLE;
  420. pRoleInfo->nDataLen = lenRN;
  421. pRoleInfo->ulNetId = 0;
  422. pRoleInfo->ulIdentity = m_lnIdentityID;
  423. memcpy( &pRoleInfo->pDataBuffer[0], sRoleName.c_str(), lenRN );
  424. pBuffer->Use( lenRI );
  425. /*
  426.  * Send this information to role database server
  427.  */
  428. KRoleBlockProcess theRoleInfo( pRoleInfo, lenRI );
  429. for ( size_t block = 0; block < theRoleInfo.GetBlockCount( g_scNetworkBlockSize ); block ++ )
  430. {
  431. KBlock *pBlock = reinterpret_cast< KBlock * >( const_cast< char * >( m_sBlockBuffer.c_str() ) );
  432. size_t sizeBlock = theRoleInfo.GetBlockPtr( pBlock, block, g_scNetworkBlockSize );
  433. m_pRoleDBSender->SendPackToServer( pBlock, sizeBlock );
  434. }
  435. pBuffer->Release();
  436. }
  437. break;
  438. }
  439. Trace( ToString( m_lnIdentityID ), "CGamePlayer::QueryRoleInfo -> End" );
  440. return true;
  441. }
  442. bool CGamePlayer::ProcessRoleInfo()
  443. {
  444. Trace( ToString( m_lnIdentityID ), "CGamePlayer::ProcessRoleInfo -> Begin" );
  445. bool ok = false;
  446. const void *pData = NULL;
  447. if ( NULL != ( pData = m_theDataQueue.Top( PROTOL_LOADROLE ) ) )
  448. {
  449. const TRoleData *pRoleData = ( const TRoleData * )( ( const char * )( pData ) );
  450. if ( pRoleData )
  451. {
  452. memcpy( &m_theRoleInfomation.theRoleData, pRoleData, sizeof( TRoleData ) );
  453. Trace( ToString( m_lnIdentityID ), m_theRoleInfomation.theRoleData.BaseInfo.caccname );
  454. ok = true;
  455. }
  456. m_theDataQueue.Pop( PROTOL_LOADROLE );
  457. }
  458. Trace( ToString( m_lnIdentityID ), "CGamePlayer::ProcessRoleInfo -> End" );
  459. return ok;
  460. }