Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1165 lines
27 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. //----------------------------------------------------------------------------------------
  4. #if defined( REPLAY_ENABLED )
  5. #include <server_class.h>
  6. #include <inetmessage.h>
  7. #include <tier0/vprof.h>
  8. #include <tier0/vcrmode.h>
  9. #include <KeyValues.h>
  10. #include <edict.h>
  11. #include <eiface.h>
  12. #include <PlayerState.h>
  13. #include <time.h>
  14. #include "replayserver.h"
  15. #include "sv_client.h"
  16. #include "server.h"
  17. #include "sv_main.h"
  18. #include "framesnapshot.h"
  19. #include "networkstringtable.h"
  20. #include "cmodel_engine.h"
  21. #include "dt_recv_eng.h"
  22. #include "cdll_engine_int.h"
  23. #include "GameEventManager.h"
  24. #include "host.h"
  25. #include "proto_version.h"
  26. #include "dt_common_eng.h"
  27. #include "baseautocompletefilelist.h"
  28. #include "sv_steamauth.h"
  29. #include "con_nprint.h"
  30. #include "tier0/icommandline.h"
  31. #include "client_class.h"
  32. #include "replay_internal.h"
  33. // memdbgon must be the last include file in a .cpp file!!!
  34. #include "tier0/memdbgon.h"
  35. extern CNetworkStringTableContainer *networkStringTableContainerClient;
  36. //////////////////////////////////////////////////////////////////////
  37. // Construction/Destruction
  38. //////////////////////////////////////////////////////////////////////
  39. CReplayServer *replay = NULL;
  40. CReplayDeltaEntityCache::CReplayDeltaEntityCache()
  41. {
  42. Q_memset( m_Cache, 0, sizeof(m_Cache) );
  43. m_nTick = 0;
  44. m_nMaxEntities = 0;
  45. m_nCacheSize = 0;
  46. }
  47. CReplayDeltaEntityCache::~CReplayDeltaEntityCache()
  48. {
  49. Flush();
  50. }
  51. void CReplayDeltaEntityCache::Flush()
  52. {
  53. if ( m_nMaxEntities != 0 )
  54. {
  55. // at least one entity was set
  56. for ( int i=0; i<m_nMaxEntities; i++ )
  57. {
  58. if ( m_Cache[i] != NULL )
  59. {
  60. free( m_Cache[i] );
  61. m_Cache[i] = NULL;
  62. }
  63. }
  64. m_nMaxEntities = 0;
  65. }
  66. m_nCacheSize = 0;
  67. }
  68. void CReplayDeltaEntityCache::SetTick( int nTick, int nMaxEntities )
  69. {
  70. if ( nTick == m_nTick )
  71. return;
  72. Flush();
  73. m_nCacheSize = 2 * 1024;
  74. if ( m_nCacheSize <= 0 )
  75. return;
  76. m_nMaxEntities = MIN(nMaxEntities,MAX_EDICTS);
  77. m_nTick = nTick;
  78. }
  79. unsigned char* CReplayDeltaEntityCache::FindDeltaBits( int nEntityIndex, int nDeltaTick, int &nBits )
  80. {
  81. nBits = -1;
  82. if ( nEntityIndex < 0 || nEntityIndex >= m_nMaxEntities )
  83. return NULL;
  84. DeltaEntityEntry_s *pEntry = m_Cache[nEntityIndex];
  85. while ( pEntry )
  86. {
  87. if ( pEntry->nDeltaTick == nDeltaTick )
  88. {
  89. nBits = pEntry->nBits;
  90. return (unsigned char*)(pEntry) + sizeof(DeltaEntityEntry_s);
  91. }
  92. else
  93. {
  94. // keep searching entry list
  95. pEntry = pEntry->pNext;
  96. }
  97. }
  98. return NULL;
  99. }
  100. void CReplayDeltaEntityCache::AddDeltaBits( int nEntityIndex, int nDeltaTick, int nBits, bf_write *pBuffer )
  101. {
  102. if ( nEntityIndex < 0 || nEntityIndex >= m_nMaxEntities || m_nCacheSize <= 0 )
  103. return;
  104. int nBufferSize = PAD_NUMBER( Bits2Bytes(nBits), 4);
  105. DeltaEntityEntry_s *pEntry = m_Cache[nEntityIndex];
  106. if ( pEntry == NULL )
  107. {
  108. if ( (int)(nBufferSize+sizeof(DeltaEntityEntry_s)) > m_nCacheSize )
  109. return; // way too big, don't even create an entry
  110. pEntry = m_Cache[nEntityIndex] = (DeltaEntityEntry_s *) malloc( m_nCacheSize );
  111. }
  112. else
  113. {
  114. char *pEnd = (char*)(pEntry) + m_nCacheSize; // end marker
  115. while( pEntry->pNext )
  116. {
  117. pEntry = pEntry->pNext;
  118. }
  119. int entrySize = sizeof(DeltaEntityEntry_s) + PAD_NUMBER( Bits2Bytes(pEntry->nBits), 4);
  120. DeltaEntityEntry_s *pNew = (DeltaEntityEntry_s*)((char*)(pEntry) + entrySize);
  121. if ( ((char*)(pNew) + sizeof(DeltaEntityEntry_s) + nBufferSize) > pEnd )
  122. return; // data wouldn't fit into cache anymore, don't add new entries
  123. pEntry = pNew;
  124. pEntry->pNext = pEntry;
  125. }
  126. pEntry->pNext = NULL; // link to next
  127. pEntry->nDeltaTick = nDeltaTick;
  128. pEntry->nBits = nBits;
  129. if ( nBits > 0 )
  130. {
  131. bf_read inBuffer;
  132. inBuffer.StartReading( pBuffer->GetData(), pBuffer->m_nDataBytes, pBuffer->GetNumBitsWritten() );
  133. bf_write outBuffer( (char*)(pEntry) + sizeof(DeltaEntityEntry_s), nBufferSize );
  134. outBuffer.WriteBitsFromBuffer( &inBuffer, nBits );
  135. }
  136. }
  137. static RecvTable* FindRecvTable( const char *pName, RecvTable **pRecvTables, int nRecvTables )
  138. {
  139. for ( int i=0; i< nRecvTables; i++ )
  140. {
  141. if ( !Q_strcmp( pName, pRecvTables[i]->GetName() ) )
  142. return pRecvTables[i];
  143. }
  144. return NULL;
  145. }
  146. static RecvTable* AddRecvTableR( SendTable *sendt, RecvTable **pRecvTables, int &nRecvTables )
  147. {
  148. RecvTable *recvt = FindRecvTable( sendt->m_pNetTableName, pRecvTables, nRecvTables );
  149. if ( recvt )
  150. return recvt; // already in list
  151. if ( sendt->m_nProps > 0 )
  152. {
  153. RecvProp *receiveProps = new RecvProp[sendt->m_nProps];
  154. for ( int i=0; i < sendt->m_nProps; i++ )
  155. {
  156. // copy property data
  157. SendProp * sp = sendt->GetProp( i );
  158. RecvProp * rp = &receiveProps[i];
  159. rp->m_pVarName = sp->m_pVarName;
  160. rp->m_RecvType = sp->m_Type;
  161. if ( sp->IsExcludeProp() )
  162. {
  163. // if prop is excluded, give different name
  164. rp->m_pVarName = "IsExcludedProp";
  165. }
  166. if ( sp->IsInsideArray() )
  167. {
  168. rp->SetInsideArray();
  169. rp->m_pVarName = "InsideArrayProp"; // give different name
  170. }
  171. if ( sp->GetType() == DPT_Array )
  172. {
  173. Assert ( sp->GetArrayProp() == sendt->GetProp( i-1 ) );
  174. Assert( receiveProps[i-1].IsInsideArray() );
  175. rp->SetArrayProp( &receiveProps[i-1] );
  176. rp->InitArray( sp->m_nElements, sp->m_ElementStride );
  177. }
  178. if ( sp->GetType() == DPT_DataTable )
  179. {
  180. // recursive create
  181. Assert ( sp->GetDataTable() );
  182. RecvTable *subTable = AddRecvTableR( sp->GetDataTable(), pRecvTables, nRecvTables );
  183. rp->SetDataTable( subTable );
  184. }
  185. }
  186. recvt = new RecvTable( receiveProps, sendt->m_nProps, sendt->m_pNetTableName );
  187. }
  188. else
  189. {
  190. // table with no properties
  191. recvt = new RecvTable( NULL, 0, sendt->m_pNetTableName );
  192. }
  193. pRecvTables[nRecvTables] = recvt;
  194. nRecvTables++;
  195. return recvt;
  196. }
  197. void CReplayServer::FreeClientRecvTables()
  198. {
  199. for ( int i=0; i< m_nRecvTables; i++ )
  200. {
  201. RecvTable *rt = m_pRecvTables[i];
  202. // delete recv table props
  203. if ( rt->m_pProps )
  204. {
  205. Assert( rt->m_nProps > 0 );
  206. delete [] rt->m_pProps;
  207. }
  208. // delete the table itself
  209. delete rt;
  210. }
  211. Q_memset( m_pRecvTables, 0, sizeof( m_pRecvTables ) );
  212. m_nRecvTables = 0;
  213. }
  214. // creates client receive tables from server send tables
  215. void CReplayServer::InitClientRecvTables()
  216. {
  217. ServerClass* pCur = NULL;
  218. if ( ClientDLL_GetAllClasses() != NULL )
  219. return; //already initialized
  220. // first create all SendTables
  221. for ( pCur = serverGameDLL->GetAllServerClasses(); pCur; pCur=pCur->m_pNext )
  222. {
  223. // create receive table from send table.
  224. AddRecvTableR( pCur->m_pTable, m_pRecvTables, m_nRecvTables );
  225. ErrorIfNot(
  226. m_nRecvTables < ARRAYSIZE( m_pRecvTables ),
  227. ("AddRecvTableR: overflowed MAX_DATATABLES")
  228. );
  229. }
  230. // now register client classes
  231. for ( pCur = serverGameDLL->GetAllServerClasses(); pCur; pCur=pCur->m_pNext )
  232. {
  233. ErrorIfNot(
  234. m_nRecvTables < ARRAYSIZE( m_pRecvTables ),
  235. ("ClientDLL_InitRecvTableMgr: overflowed MAX_DATATABLES")
  236. );
  237. // find top receive table for class
  238. RecvTable * recvt = FindRecvTable( pCur->m_pTable->GetName(), m_pRecvTables, m_nRecvTables );
  239. Assert ( recvt );
  240. // register class, constructor addes clientClass to g_pClientClassHead list
  241. ClientClass * clientclass = new ClientClass( pCur->m_pNetworkName, NULL, NULL, recvt );
  242. if ( !clientclass )
  243. {
  244. Msg("REPLAY_InitRecvTableMgr: failed to allocate client class %s.\n", pCur->m_pNetworkName );
  245. return;
  246. }
  247. }
  248. RecvTable_Init( m_pRecvTables, m_nRecvTables );
  249. }
  250. CReplayFrame::CReplayFrame()
  251. {
  252. }
  253. CReplayFrame::~CReplayFrame()
  254. {
  255. FreeBuffers();
  256. }
  257. void CReplayFrame::Reset( void )
  258. {
  259. for ( int i=0; i<REPLAY_BUFFER_MAX; i++ )
  260. {
  261. m_Messages[i].Reset();
  262. }
  263. }
  264. bool CReplayFrame::HasData( void )
  265. {
  266. for ( int i=0; i<REPLAY_BUFFER_MAX; i++ )
  267. {
  268. if ( m_Messages[i].GetNumBitsWritten() > 0 )
  269. return true;
  270. }
  271. return false;
  272. }
  273. void CReplayFrame::CopyReplayData( CReplayFrame &frame )
  274. {
  275. // copy reliable messages
  276. int bits = frame.m_Messages[REPLAY_BUFFER_RELIABLE].GetNumBitsWritten();
  277. if ( bits > 0 )
  278. {
  279. int bytes = PAD_NUMBER( Bits2Bytes(bits), 4 );
  280. m_Messages[REPLAY_BUFFER_RELIABLE].StartWriting( new char[ bytes ], bytes, bits );
  281. Q_memcpy( m_Messages[REPLAY_BUFFER_RELIABLE].GetBasePointer(), frame.m_Messages[REPLAY_BUFFER_RELIABLE].GetBasePointer(), bytes );
  282. }
  283. // copy unreliable messages
  284. bits = frame.m_Messages[REPLAY_BUFFER_UNRELIABLE].GetNumBitsWritten();
  285. bits += frame.m_Messages[REPLAY_BUFFER_TEMPENTS].GetNumBitsWritten();
  286. bits += frame.m_Messages[REPLAY_BUFFER_SOUNDS].GetNumBitsWritten();
  287. bits += frame.m_Messages[REPLAY_BUFFER_VOICE].GetNumBitsWritten();
  288. if ( bits > 0 )
  289. {
  290. // collapse all unreliable buffers in one
  291. int bytes = PAD_NUMBER( Bits2Bytes(bits), 4 );
  292. m_Messages[REPLAY_BUFFER_UNRELIABLE].StartWriting( new char[ bytes ], bytes );
  293. m_Messages[REPLAY_BUFFER_UNRELIABLE].WriteBits( frame.m_Messages[REPLAY_BUFFER_UNRELIABLE].GetData(), frame.m_Messages[REPLAY_BUFFER_UNRELIABLE].GetNumBitsWritten() );
  294. m_Messages[REPLAY_BUFFER_UNRELIABLE].WriteBits( frame.m_Messages[REPLAY_BUFFER_TEMPENTS].GetData(), frame.m_Messages[REPLAY_BUFFER_TEMPENTS].GetNumBitsWritten() );
  295. m_Messages[REPLAY_BUFFER_UNRELIABLE].WriteBits( frame.m_Messages[REPLAY_BUFFER_SOUNDS].GetData(), frame.m_Messages[REPLAY_BUFFER_SOUNDS].GetNumBitsWritten() );
  296. m_Messages[REPLAY_BUFFER_UNRELIABLE].WriteBits( frame.m_Messages[REPLAY_BUFFER_VOICE].GetData(), frame.m_Messages[REPLAY_BUFFER_VOICE].GetNumBitsWritten() );
  297. }
  298. }
  299. void CReplayFrame::AllocBuffers( void )
  300. {
  301. // allocate buffers for input frame
  302. for ( int i=0; i < REPLAY_BUFFER_MAX; i++ )
  303. {
  304. Assert( m_Messages[i].GetBasePointer() == NULL );
  305. m_Messages[i].StartWriting( new char[NET_MAX_PAYLOAD], NET_MAX_PAYLOAD);
  306. }
  307. }
  308. void CReplayFrame::FreeBuffers( void )
  309. {
  310. for ( int i=0; i<REPLAY_BUFFER_MAX; i++ )
  311. {
  312. bf_write &msg = m_Messages[i];
  313. if ( msg.GetBasePointer() )
  314. {
  315. delete[] msg.GetBasePointer();
  316. msg.StartWriting( NULL, 0 );
  317. }
  318. }
  319. }
  320. CReplayServer::CReplayServer()
  321. : m_DemoRecorder( this )
  322. {
  323. m_flTickInterval = 0.03;
  324. m_MasterClient = NULL;
  325. m_Server = NULL;
  326. m_nFirstTick = -1;
  327. m_nLastTick = 0;
  328. m_CurrentFrame = NULL;
  329. m_nViewEntity = 0;
  330. m_nPlayerSlot = 0;
  331. m_bSignonState = false;
  332. m_flStartTime = 0;
  333. m_flFPS = 0;
  334. m_nGameServerMaxClients = 0;
  335. m_fNextSendUpdateTime = 0;
  336. Q_memset( m_pRecvTables, 0, sizeof( m_pRecvTables ) );
  337. m_nRecvTables = 0;
  338. m_vPVSOrigin.Init();
  339. m_bMasterOnlyMode = false;
  340. m_nGlobalSlots = 0;
  341. m_nGlobalClients = 0;
  342. m_nGlobalProxies = 0;
  343. m_flStartRecordTime = 0.0f;
  344. m_flStopRecordTime = 0.0f;
  345. }
  346. CReplayServer::~CReplayServer()
  347. {
  348. if ( m_nRecvTables > 0 )
  349. {
  350. RecvTable_Term();
  351. FreeClientRecvTables();
  352. }
  353. // make sure everything was destroyed
  354. Assert( m_CurrentFrame == NULL );
  355. Assert( CountClientFrames() == 0 );
  356. }
  357. void CReplayServer::SetMaxClients( int number )
  358. {
  359. // allow max clients 0 in Replay
  360. m_nMaxclients = clamp( number, 0, ABSOLUTE_PLAYER_LIMIT );
  361. }
  362. void CReplayServer::StartMaster(CGameClient *client)
  363. {
  364. Clear(); // clear old settings & buffers
  365. if ( !client )
  366. {
  367. ConMsg("Replay client not found.\n");
  368. return;
  369. }
  370. m_MasterClient = client;
  371. m_MasterClient->m_bIsHLTV = false;
  372. m_MasterClient->m_bIsReplay = true;
  373. // let game.dll know that we are the Replay client
  374. Assert( serverGameClients );
  375. CPlayerState *player = serverGameClients->GetPlayerState( m_MasterClient->edict );
  376. player->replay = true;
  377. m_Server = (CGameServer*)m_MasterClient->GetServer();
  378. // set default user settings
  379. ConVarRef replay_name( "replay_name" );
  380. m_MasterClient->m_ConVars->SetString( "name", replay_name.GetString() );
  381. m_MasterClient->m_ConVars->SetString( "cl_team", "1" );
  382. m_MasterClient->m_ConVars->SetString( "rate", "30000" );
  383. m_MasterClient->m_ConVars->SetString( "cl_updaterate", "22" );
  384. m_MasterClient->m_ConVars->SetString( "cl_interp_ratio", "1.0" );
  385. m_MasterClient->m_ConVars->SetString( "cl_predict", "0" );
  386. m_nViewEntity = m_MasterClient->GetPlayerSlot() + 1;
  387. m_nPlayerSlot = m_MasterClient->GetPlayerSlot();
  388. // copy server settings from m_Server
  389. m_nGameServerMaxClients = m_Server->GetMaxClients(); // maxclients is different on proxy (128)
  390. serverclasses = m_Server->serverclasses;
  391. serverclassbits = m_Server->serverclassbits;
  392. worldmapMD5 = m_Server->worldmapMD5;
  393. m_flTickInterval= m_Server->GetTickInterval();
  394. // allocate buffers for input frame
  395. m_ReplayFrame.AllocBuffers();
  396. InstallStringTables();
  397. // copy signon buffers
  398. m_Signon.StartWriting( m_Server->m_Signon.GetBasePointer(), m_Server->m_Signon.m_nDataBytes,
  399. m_Server->m_Signon.GetNumBitsWritten() );
  400. Q_strncpy( m_szMapname, m_Server->m_szMapname, sizeof(m_szMapname) );
  401. Q_strncpy( m_szSkyname, m_Server->m_szSkyname, sizeof(m_szSkyname) );
  402. m_MasterClient->ExecuteStringCommand( "spectate" ); // become a spectator
  403. m_MasterClient->UpdateUserSettings(); // make sure UserInfo is correct
  404. // hack reduce signontick by one to catch changes made in the current tick
  405. m_MasterClient->m_nSignonTick--;
  406. SetMaxClients( 0 );
  407. m_bSignonState = false; //master proxy is instantly connected
  408. m_nSpawnCount++;
  409. m_flStartTime = net_time;
  410. m_State = ss_active;
  411. // stop any previous recordings
  412. StopRecording();
  413. ReconnectClients();
  414. }
  415. int CReplayServer::GetReplaySlot( void )
  416. {
  417. return m_nPlayerSlot;
  418. }
  419. float CReplayServer::GetOnlineTime( void )
  420. {
  421. return MAX(0, net_time - m_flStartTime);
  422. }
  423. void CReplayServer::FireGameEvent(IGameEvent *event)
  424. {
  425. if ( !IsActive() )
  426. return;
  427. char buffer_data[MAX_EVENT_BYTES];
  428. SVC_GameEvent eventMsg;
  429. eventMsg.m_DataOut.StartWriting( buffer_data, sizeof(buffer_data) );
  430. // create bit stream from KeyValues
  431. if ( g_GameEventManager.SerializeEvent( event, &eventMsg.m_DataOut ) )
  432. {
  433. SendNetMsg( eventMsg );
  434. }
  435. else
  436. {
  437. DevMsg("CReplayServer::FireGameEvent: failed to serialize event '%s'.\n", event->GetName() );
  438. }
  439. }
  440. int CReplayServer::GetEventDebugID()
  441. {
  442. return m_nDebugID;
  443. }
  444. bool CReplayServer::ShouldUpdateMasterServer()
  445. {
  446. // The replay server should never do this work
  447. return false;
  448. }
  449. void CReplayServer::InstallStringTables( void )
  450. {
  451. #ifndef SHARED_NET_STRING_TABLES
  452. int numTables = m_Server->m_StringTables->GetNumTables();
  453. m_StringTables = &m_NetworkStringTables;
  454. Assert( m_StringTables->GetNumTables() == 0); // must be empty
  455. m_StringTables->AllowCreation( true );
  456. // master replay needs to keep a list of changes for all table items
  457. m_StringTables->EnableRollback( true );
  458. for ( int i =0; i<numTables; i++)
  459. {
  460. // iterate through server tables
  461. CNetworkStringTable *serverTable =
  462. (CNetworkStringTable*)m_Server->m_StringTables->GetTable( i );
  463. if ( !serverTable )
  464. continue;
  465. // get matching client table
  466. CNetworkStringTable *replayTable =
  467. (CNetworkStringTable*)m_StringTables->CreateStringTableEx(
  468. serverTable->GetTableName(),
  469. serverTable->GetMaxStrings(),
  470. serverTable->GetUserDataSize(),
  471. serverTable->GetUserDataSizeBits(),
  472. serverTable->HasFileNameStrings()
  473. );
  474. if ( !replayTable )
  475. {
  476. DevMsg("SV_InstallReplayStringTableMirrors! Missing client table \"%s\".\n ", serverTable->GetTableName() );
  477. continue;
  478. }
  479. // make replay table an exact copy of server table
  480. replayTable->CopyStringTable( serverTable );
  481. // link replay table to server table
  482. serverTable->SetMirrorTable( replayTable );
  483. }
  484. m_StringTables->AllowCreation( false );
  485. #endif
  486. }
  487. void CReplayServer::RestoreTick( int tick )
  488. {
  489. #ifndef SHARED_NET_STRING_TABLES
  490. int numTables = m_StringTables->GetNumTables();
  491. for ( int i =0; i<numTables; i++)
  492. {
  493. // iterate through server tables
  494. CNetworkStringTable *pTable = (CNetworkStringTable*) m_StringTables->GetTable( i );
  495. pTable->RestoreTick( tick );
  496. }
  497. #endif
  498. }
  499. void CReplayServer::UserInfoChanged( int nClientIndex )
  500. {
  501. // don't change UserInfo table, it keeps the infos of the original players
  502. }
  503. void CReplayServer::LinkInstanceBaselines( void )
  504. {
  505. // Forces to update m_pInstanceBaselineTable.
  506. AUTO_LOCK( g_svInstanceBaselineMutex );
  507. GetInstanceBaselineTable();
  508. Assert( m_pInstanceBaselineTable );
  509. // update all found server classes
  510. for ( ServerClass *pClass = serverGameDLL->GetAllServerClasses(); pClass; pClass=pClass->m_pNext )
  511. {
  512. char idString[32];
  513. Q_snprintf( idString, sizeof( idString ), "%d", pClass->m_ClassID );
  514. // Ok, make a new instance baseline so they can reference it.
  515. int index = m_pInstanceBaselineTable->FindStringIndex( idString );
  516. if ( index != -1 )
  517. {
  518. pClass->m_InstanceBaselineIndex = index;
  519. }
  520. else
  521. {
  522. pClass->m_InstanceBaselineIndex = INVALID_STRING_INDEX;
  523. }
  524. }
  525. }
  526. /* CReplayServer::GetOriginFromPackedEntity is such a bad, bad hack.
  527. extern float DecodeFloat(SendProp const *pProp, bf_read *pIn);
  528. Vector CReplayServer::GetOriginFromPackedEntity(PackedEntity* pe)
  529. {
  530. Vector origin; origin.Init();
  531. SendTable *pSendTable = pe->m_pSendTable;
  532. // recursively go down until BaseEntity sendtable
  533. while ( Q_strcmp( pSendTable->GetName(), "DT_BaseEntity") )
  534. {
  535. SendProp *pProp = pSendTable->GetProp( 0 ); // 0 = baseclass
  536. pSendTable = pProp->GetDataTable();
  537. }
  538. for ( int i=0; i < pSendTable->GetNumProps(); i++ )
  539. {
  540. SendProp *pProp = pSendTable->GetProp( i );
  541. if ( Q_strcmp( pProp->GetName(), "m_vecOrigin" ) == 0 )
  542. {
  543. Assert( pProp->GetType() == DPT_Vector );
  544. bf_read buf( pe->LockData(), Bits2Bytes(pe->GetNumBits()), pProp->GetOffset() );
  545. origin[0] = DecodeFloat(pProp, &buf);
  546. origin[1] = DecodeFloat(pProp, &buf);
  547. origin[2] = DecodeFloat(pProp, &buf);
  548. break;
  549. }
  550. }
  551. return origin;
  552. } */
  553. CReplayEntityData *FindReplayDataInSnapshot( CFrameSnapshot * pSnapshot, int iEntIndex )
  554. {
  555. int a = 0;
  556. int z = pSnapshot->m_nValidEntities-1;
  557. if ( iEntIndex < pSnapshot->m_pValidEntities[a] ||
  558. iEntIndex > pSnapshot->m_pValidEntities[z] )
  559. return NULL;
  560. while ( a < z )
  561. {
  562. int m = (a+z)/2;
  563. int index = pSnapshot->m_pValidEntities[m];
  564. if ( index == iEntIndex )
  565. return &pSnapshot->m_pReplayEntityData[m];
  566. if ( iEntIndex > index )
  567. {
  568. if ( pSnapshot->m_pValidEntities[z] == iEntIndex )
  569. return &pSnapshot->m_pReplayEntityData[z];
  570. if ( a == m )
  571. return NULL;
  572. a = m;
  573. }
  574. else
  575. {
  576. if ( pSnapshot->m_pValidEntities[a] == iEntIndex )
  577. return &pSnapshot->m_pReplayEntityData[a];
  578. if ( z == m )
  579. return NULL;
  580. z = m;
  581. }
  582. }
  583. return NULL;
  584. }
  585. void CReplayServer::EntityPVSCheck( CClientFrame *pFrame )
  586. {
  587. byte PVS[PAD_NUMBER( MAX_MAP_CLUSTERS,8 ) / 8];
  588. int nPVSSize = (GetCollisionBSPData()->numclusters + 7) / 8;
  589. // setup engine PVS
  590. SV_ResetPVS( PVS, nPVSSize );
  591. CFrameSnapshot * pSnapshot = pFrame->GetSnapshot();
  592. Assert ( pSnapshot->m_pReplayEntityData != NULL );
  593. m_vPVSOrigin.Init();
  594. SV_AddOriginToPVS( m_vPVSOrigin );
  595. // know remove all entities that aren't in PVS
  596. int entindex = -1;
  597. while ( true )
  598. {
  599. entindex = pFrame->transmit_entity.FindNextSetBit( entindex+1 );
  600. if ( entindex < 0 )
  601. break;
  602. // is transmit_always is set -> no PVS check
  603. if ( pFrame->transmit_always->Get(entindex) )
  604. {
  605. pFrame->last_entity = entindex;
  606. continue;
  607. }
  608. CReplayEntityData *pReplayData = FindReplayDataInSnapshot( pSnapshot, entindex );
  609. if ( !pReplayData )
  610. continue;
  611. unsigned int nNodeCluster = pReplayData->m_nNodeCluster;
  612. // check if node or cluster is in PVS
  613. if ( nNodeCluster & (1<<31) )
  614. {
  615. // it's a node SLOW
  616. nNodeCluster &= ~(1<<31);
  617. if ( CM_HeadnodeVisible( nNodeCluster, PVS, nPVSSize ) )
  618. {
  619. pFrame->last_entity = entindex;
  620. continue;
  621. }
  622. }
  623. else
  624. {
  625. // it's a cluster QUICK
  626. if ( PVS[nNodeCluster >> 3] & (1 << (nNodeCluster & 7)) )
  627. {
  628. pFrame->last_entity = entindex;
  629. continue;
  630. }
  631. }
  632. // entity is not in PVS, remove from transmit_entity list
  633. pFrame->transmit_entity.Clear( entindex );
  634. }
  635. }
  636. CClientFrame *CReplayServer::AddNewFrame( CClientFrame *clientFrame )
  637. {
  638. VPROF_BUDGET( "CReplayServer::AddNewFrame", "Replay" );
  639. Assert ( clientFrame );
  640. Assert( clientFrame->tick_count > m_nLastTick );
  641. m_nLastTick = clientFrame->tick_count;
  642. m_ReplayFrame.SetSnapshot( clientFrame->GetSnapshot() );
  643. m_ReplayFrame.tick_count = clientFrame->tick_count;
  644. m_ReplayFrame.last_entity = clientFrame->last_entity;
  645. m_ReplayFrame.transmit_entity = clientFrame->transmit_entity;
  646. // remember tick of first valid frame
  647. if ( m_nFirstTick < 0 )
  648. {
  649. m_nFirstTick = clientFrame->tick_count;
  650. m_nTickCount = m_nFirstTick;
  651. }
  652. CReplayFrame *replayFrame = new CReplayFrame;
  653. // copy tickcount & entities from client frame
  654. replayFrame->CopyFrame( *clientFrame );
  655. //copy rest (messages, tempents) from current Replay frame
  656. replayFrame->CopyReplayData( m_ReplayFrame );
  657. // add frame to Replay server
  658. AddClientFrame( replayFrame );
  659. if ( m_DemoRecorder.IsRecording() )
  660. {
  661. m_DemoRecorder.WriteFrame( &m_ReplayFrame );
  662. }
  663. // reset Replay frame for recording next messages etc.
  664. m_ReplayFrame.Reset();
  665. m_ReplayFrame.SetSnapshot( NULL );
  666. return replayFrame;
  667. }
  668. bool CReplayServer::SendNetMsg( INetMessage &msg, bool bForceReliable )
  669. {
  670. if ( m_bSignonState )
  671. {
  672. return msg.WriteToBuffer( m_Signon );
  673. }
  674. int buffer = REPLAY_BUFFER_UNRELIABLE; // default destination
  675. if ( msg.IsReliable() )
  676. {
  677. buffer = REPLAY_BUFFER_RELIABLE;
  678. }
  679. else if ( msg.GetType() == svc_Sounds )
  680. {
  681. buffer = REPLAY_BUFFER_SOUNDS;
  682. }
  683. else if ( msg.GetType() == svc_VoiceData )
  684. {
  685. buffer = REPLAY_BUFFER_VOICE;
  686. }
  687. else if ( msg.GetType() == svc_TempEntities )
  688. {
  689. buffer = REPLAY_BUFFER_TEMPENTS;
  690. }
  691. // anything else goes to the unreliable bin
  692. return msg.WriteToBuffer( m_ReplayFrame.m_Messages[buffer] );
  693. }
  694. bf_write *CReplayServer::GetBuffer( int nBuffer )
  695. {
  696. if ( nBuffer < 0 || nBuffer >= REPLAY_BUFFER_MAX )
  697. return NULL;
  698. return &m_ReplayFrame.m_Messages[nBuffer];
  699. }
  700. IServer *CReplayServer::GetBaseServer()
  701. {
  702. return (IServer*)this;
  703. }
  704. CClientFrame *CReplayServer::GetDeltaFrame( int nTick )
  705. {
  706. // TODO make that a utlmap
  707. FOR_EACH_VEC( m_FrameCache, iFrame )
  708. {
  709. if ( m_FrameCache[iFrame].nTick == nTick )
  710. return m_FrameCache[iFrame].pFrame;
  711. }
  712. int i = m_FrameCache.AddToTail();
  713. CReplayFrameCacheEntry_s &entry = m_FrameCache[i];
  714. entry.nTick = nTick;
  715. entry.pFrame = GetClientFrame( nTick ); //expensive
  716. return entry.pFrame;
  717. }
  718. void CReplayServer::RunFrame()
  719. {
  720. VPROF_BUDGET( "CReplayServer::RunFrame", "Replay" );
  721. // update network time etc
  722. NET_RunFrame( Plat_FloatTime() );
  723. // check if Replay server if active
  724. if ( !IsActive() )
  725. return;
  726. if ( host_frametime > 0 )
  727. {
  728. m_flFPS = m_flFPS * 0.99f + 0.01f/host_frametime;
  729. }
  730. // get current tick time for director module and restore
  731. // world (stringtables, framebuffers) as they were at this time
  732. UpdateTick();
  733. // Update the Steam server if we're running a relay.
  734. if ( !sv.IsActive() )
  735. Steam3Server().RunFrame();
  736. UpdateMasterServer();
  737. SendPendingEvents();
  738. }
  739. void CReplayServer::UpdateTick( void )
  740. {
  741. VPROF_BUDGET( "CReplayServer::UpdateTick", "Replay" );
  742. if ( m_nFirstTick < 0 )
  743. {
  744. m_nTickCount = 0;
  745. m_CurrentFrame = NULL;
  746. return;
  747. }
  748. // set tick time to last frame added
  749. int nNewTick = MAX( m_nLastTick, 0 );
  750. // the the closest available frame
  751. CReplayFrame *newFrame = (CReplayFrame*) GetClientFrame( nNewTick, false );
  752. if ( newFrame == NULL )
  753. return; // we dont have a new frame
  754. if ( m_CurrentFrame == newFrame )
  755. return; // current frame didn't change
  756. m_CurrentFrame = newFrame;
  757. m_nTickCount = m_CurrentFrame->tick_count;
  758. // restore string tables for this time
  759. RestoreTick( m_nTickCount );
  760. int removeTick = m_nTickCount - 16.0f/m_flTickInterval; // keep 16 second buffer
  761. if ( removeTick > 0 )
  762. {
  763. DeleteClientFrames( removeTick );
  764. }
  765. m_FrameCache.RemoveAll();
  766. }
  767. const char *CReplayServer::GetName( void ) const
  768. {
  769. ConVarRef replay_name( "replay_name" );
  770. return replay_name.GetString();
  771. }
  772. void CReplayServer::FillServerInfo(SVC_ServerInfo &serverinfo)
  773. {
  774. CBaseServer::FillServerInfo( serverinfo );
  775. serverinfo.m_nPlayerSlot = m_nPlayerSlot; // all spectators think they're the Replay client
  776. serverinfo.m_nMaxClients = m_nGameServerMaxClients;
  777. }
  778. void CReplayServer::Clear( void )
  779. {
  780. CBaseServer::Clear();
  781. m_MasterClient = NULL;
  782. m_Server = NULL;
  783. m_nFirstTick = -1;
  784. m_nLastTick = 0;
  785. m_nTickCount = 0;
  786. m_CurrentFrame = NULL;
  787. m_nPlayerSlot = 0;
  788. m_flStartTime = 0.0f;
  789. m_nViewEntity = 1;
  790. m_nGameServerMaxClients = 0;
  791. m_fNextSendUpdateTime = 0.0f;
  792. m_ReplayFrame.FreeBuffers();
  793. m_vPVSOrigin.Init();
  794. DeleteClientFrames( -1 );
  795. m_DeltaCache.Flush();
  796. m_FrameCache.RemoveAll();
  797. }
  798. void CReplayServer::Init(bool bIsDedicated)
  799. {
  800. CBaseServer::Init( bIsDedicated );
  801. // No broadcasting
  802. m_bMasterOnlyMode = true;
  803. }
  804. void CReplayServer::Changelevel()
  805. {
  806. if ( g_pReplay->IsRecording() )
  807. {
  808. g_pReplay->SV_EndRecordingSession();
  809. }
  810. InactivateClients();
  811. DeleteClientFrames(-1);
  812. m_CurrentFrame = NULL;
  813. }
  814. void CReplayServer::GetNetStats( float &avgIn, float &avgOut )
  815. {
  816. CBaseServer::GetNetStats( avgIn, avgOut );
  817. }
  818. void CReplayServer::Shutdown()
  819. {
  820. StopRecording(); // if recording, stop now
  821. if ( m_MasterClient )
  822. m_MasterClient->Disconnect( "Replay stop." );
  823. g_GameEventManager.RemoveListener( this );
  824. // Delete the temp replay if it exists
  825. if ( g_pFullFileSystem->FileExists( TMP_REPLAY_FILENAME ) )
  826. {
  827. g_pFullFileSystem->RemoveFile( TMP_REPLAY_FILENAME );
  828. }
  829. CBaseServer::Shutdown();
  830. }
  831. int CReplayServer::GetChallengeType ( netadr_t &adr )
  832. {
  833. return PROTOCOL_HASHEDCDKEY; // Replay doesn't need Steam authentication
  834. }
  835. const char *CReplayServer::GetPassword() const
  836. {
  837. return NULL;
  838. }
  839. IClient *CReplayServer::ConnectClient ( netadr_t &adr, int protocol, int challenge, int clientChallenge, int authProtocol,
  840. const char *name, const char *password, const char *hashedCDkey, int cdKeyLen )
  841. {
  842. // Don't let anyone connect to the replay server
  843. return NULL;
  844. }
  845. void CReplayServer::ReplyChallenge(netadr_t &adr, int clientChallenge )
  846. {
  847. // No reply for replay.
  848. return;
  849. }
  850. void CReplayServer::ReplyServerChallenge(netadr_t &adr)
  851. {
  852. return;
  853. }
  854. void CReplayServer::RejectConnection( const netadr_t &adr, int clientChallenge, const char *s )
  855. {
  856. return;
  857. }
  858. CBaseClient *CReplayServer::CreateFakeClient(const char *name)
  859. {
  860. return NULL;
  861. }
  862. void CReplayServer::StartRecording()
  863. {
  864. if ( m_DemoRecorder.IsRecording() )
  865. return;
  866. extern ConVar replay_debug;
  867. if ( replay_debug.GetBool() ) Msg( "CReplayServer::StartRecording() now, %f\n", host_time );
  868. m_DemoRecorder.StartRecording();
  869. m_flStartRecordTime = host_time;
  870. }
  871. void CReplayServer::StopRecording()
  872. {
  873. if ( !m_DemoRecorder.IsRecording() )
  874. return;
  875. m_DemoRecorder.StopRecording();
  876. m_flStopRecordTime = host_time;
  877. }
  878. void CReplayServer::SendPendingEvents()
  879. {
  880. // Did we recently stop recording?
  881. if ( m_flStopRecordTime != 0.0f )
  882. {
  883. // Let clients know the server has stopped recording replays
  884. g_pReplay->SV_SendReplayEvent( "replay_endrecord", -1 );
  885. // Reset stop record time
  886. m_flStopRecordTime = 0.0f;
  887. }
  888. // Did we recently begin recording?
  889. if ( m_flStartRecordTime != 0.0f )
  890. {
  891. // Send start record event to everyone
  892. g_pReplay->SV_SendReplayEvent( "replay_startrecord", -1 );
  893. // Send recording session info to everyone
  894. IGameEvent *pSessionInfoEvent = g_pServerReplayContext->CreateReplaySessionInfoEvent();
  895. if ( pSessionInfoEvent )
  896. {
  897. // Let clients know the server is ready to capture replays
  898. g_pReplay->SV_SendReplayEvent( pSessionInfoEvent, -1 );
  899. }
  900. else
  901. {
  902. AssertMsg( 0, "Failed to create replay_sessioninfo event!" );
  903. }
  904. // Reset the start record timer
  905. m_flStartRecordTime = 0.0f;
  906. }
  907. }
  908. #endif