Counter Strike : Global Offensive Source Code
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.

763 lines
23 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Parsing of entity network packets.
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "client_pch.h"
  8. #include "con_nprint.h"
  9. #include "iprediction.h"
  10. #include "cl_entityreport.h"
  11. #include "dt_recv_eng.h"
  12. #include "net_synctags.h"
  13. #include "ispatialpartitioninternal.h"
  14. #include "LocalNetworkBackdoor.h"
  15. #include "basehandle.h"
  16. #include "dt_localtransfer.h"
  17. #include "iprediction.h"
  18. #include "netmessages.h"
  19. #include "ents_shared.h"
  20. #include "cl_ents_parse.h"
  21. #include "serializedentity.h"
  22. // memdbgon must be the last include file in a .cpp file!!!
  23. #include "tier0/memdbgon.h"
  24. static ConVar cl_flushentitypacket("cl_flushentitypacket", "0", FCVAR_CHEAT, "For debugging. Force the engine to flush an entity packet.");
  25. extern ConVar replay_debug;
  26. // Prints important entity creation/deletion events to console
  27. #if defined( _DEBUG )
  28. static ConVar cl_deltatrace( "cl_deltatrace", "0", 0, "For debugging, print entity creation/deletion info to console." );
  29. #define TRACE_DELTA( text ) if ( cl_deltatrace.GetInt() ) { ConMsg( "%s", text ); };
  30. #else
  31. #define TRACE_DELTA( funcs )
  32. #endif
  33. //-----------------------------------------------------------------------------
  34. // Debug networking stuff.
  35. //-----------------------------------------------------------------------------
  36. // #define DEBUG_NETWORKING 1
  37. #if defined( DEBUG_NETWORKING )
  38. void SpewToFile( char const* pFmt, ... );
  39. static ConVar cl_packettrace( "cl_packettrace", "1", 0, "For debugging, massive spew to file." );
  40. #define TRACE_PACKET( text ) if ( cl_packettrace.GetInt() ) { SpewToFile text ; };
  41. #else
  42. #define TRACE_PACKET( text )
  43. #endif
  44. #if defined( DEBUG_NETWORKING )
  45. //-----------------------------------------------------------------------------
  46. // Opens the recording file
  47. //-----------------------------------------------------------------------------
  48. static FileHandle_t OpenRecordingFile()
  49. {
  50. FileHandle_t fp = 0;
  51. static bool s_CantOpenFile = false;
  52. static bool s_NeverOpened = true;
  53. if (!s_CantOpenFile)
  54. {
  55. fp = g_pFileSystem->Open( "cltrace.txt", s_NeverOpened ? "wt" : "at" );
  56. if (!fp)
  57. {
  58. s_CantOpenFile = true;
  59. }
  60. s_NeverOpened = false;
  61. }
  62. return fp;
  63. }
  64. //-----------------------------------------------------------------------------
  65. // Records an argument for a command, flushes when the command is done
  66. //-----------------------------------------------------------------------------
  67. void SpewToFile( char const* pFmt, ... )
  68. {
  69. static CUtlVector<unsigned char> s_RecordingBuffer;
  70. char temp[2048];
  71. va_list args;
  72. va_start( args, pFmt );
  73. int len = Q_vsnprintf( temp, sizeof( temp ), pFmt, args );
  74. va_end( args );
  75. assert( len < 2048 );
  76. int idx = s_RecordingBuffer.AddMultipleToTail( len );
  77. memcpy( &s_RecordingBuffer[idx], temp, len );
  78. if ( 1 ) //s_RecordingBuffer.Size() > 8192)
  79. {
  80. FileHandle_t fp = OpenRecordingFile();
  81. g_pFileSystem->Write( s_RecordingBuffer.Base(), s_RecordingBuffer.Size(), fp );
  82. g_pFileSystem->Close( fp );
  83. s_RecordingBuffer.RemoveAll();
  84. }
  85. }
  86. #endif // DEBUG_NETWORKING
  87. //-----------------------------------------------------------------------------
  88. //
  89. //-----------------------------------------------------------------------------
  90. //-----------------------------------------------------------------------------
  91. // Purpose: Frees the client DLL's binding to the object.
  92. // Input : iEnt -
  93. //-----------------------------------------------------------------------------
  94. void CL_DeleteDLLEntity( int iEnt, char *reason, bool bOnRecreatingAllEntities )
  95. {
  96. IClientNetworkable *pNet = entitylist->GetClientNetworkable( iEnt );
  97. if ( pNet )
  98. {
  99. ClientClass *pClientClass = pNet->GetClientClass();
  100. TRACE_DELTA( va( "Trace %i (%s): delete (%s)\n", iEnt, pClientClass ? pClientClass->m_pNetworkName : "unknown", reason ) );
  101. CL_RecordDeleteEntity( iEnt, pClientClass );
  102. if ( bOnRecreatingAllEntities )
  103. {
  104. pNet->SetDestroyedOnRecreateEntities();
  105. }
  106. pNet->Release();
  107. Assert( !entitylist->GetClientNetworkable( iEnt ) );
  108. }
  109. }
  110. //-----------------------------------------------------------------------------
  111. // Purpose: Has the client DLL allocate its data for the object.
  112. // Input : iEnt -
  113. // iClass -
  114. // Output : Returns true on success, false on failure.
  115. //-----------------------------------------------------------------------------
  116. IClientNetworkable* CL_CreateDLLEntity( int iEnt, int iClass, int iSerialNum )
  117. {
  118. #if defined( _DEBUG )
  119. IClientNetworkable *pOldNetworkable = entitylist->GetClientNetworkable( iEnt );
  120. Assert( !pOldNetworkable );
  121. #endif
  122. ClientClass *pClientClass;
  123. if ( ( pClientClass = GetBaseLocalClient().m_pServerClasses[iClass].m_pClientClass ) != NULL )
  124. {
  125. TRACE_DELTA( va( "Trace %i (%s): create\n", iEnt, pClientClass->m_pNetworkName ) );
  126. CL_RecordAddEntity( iEnt );
  127. if ( !GetBaseLocalClient().IsActive() )
  128. {
  129. COM_TimestampedLog( "cl: create '%s'", pClientClass->m_pNetworkName );
  130. EngineVGui()->UpdateProgressBar( PROGRESS_CREATEENTITIES );
  131. }
  132. // Create the entity.
  133. return pClientClass->m_pCreateFn( iEnt, iSerialNum );
  134. }
  135. Assert(false);
  136. return NULL;
  137. }
  138. void SpewBitStream( unsigned char* pMem, int bit, int lastbit )
  139. {
  140. int val = 0;
  141. char buf[1024];
  142. char* pTemp = buf;
  143. int bitcount = 0;
  144. int charIdx = 1;
  145. while( bit < lastbit )
  146. {
  147. int byte = bit >> 3;
  148. int bytebit = bit & 0x7;
  149. val |= ((pMem[byte] & bytebit) != 0) << bitcount;
  150. ++bit;
  151. ++bitcount;
  152. if (bitcount == 4)
  153. {
  154. if ((val >= 0) && (val <= 9))
  155. pTemp[charIdx] = '0' + val;
  156. else
  157. pTemp[charIdx] = 'A' + val - 0xA;
  158. if (charIdx == 1)
  159. charIdx = 0;
  160. else
  161. {
  162. charIdx = 1;
  163. pTemp += 2;
  164. }
  165. bitcount = 0;
  166. val = 0;
  167. }
  168. }
  169. if ((bitcount != 0) || (charIdx != 0))
  170. {
  171. if (bitcount > 0)
  172. {
  173. if ((val >= 0) && (val <= 9))
  174. pTemp[charIdx] = '0' + val;
  175. else
  176. pTemp[charIdx] = 'A' + val - 0xA;
  177. }
  178. if (charIdx == 1)
  179. {
  180. pTemp[0] = '0';
  181. }
  182. pTemp += 2;
  183. }
  184. pTemp[0] = '\0';
  185. TRACE_PACKET(( " CL Bitstream %s\n", buf ));
  186. }
  187. inline static void CL_AddPostDataUpdateCall( CEntityReadInfo &u, int iEnt, DataUpdateType_t updateType )
  188. {
  189. ErrorIfNot( u.m_nPostDataUpdateCalls < MAX_EDICTS,
  190. ("CL_AddPostDataUpdateCall: overflowed u.m_PostDataUpdateCalls") );
  191. u.m_PostDataUpdateCalls[u.m_nPostDataUpdateCalls].m_iEnt = iEnt;
  192. u.m_PostDataUpdateCalls[u.m_nPostDataUpdateCalls].m_UpdateType = updateType;
  193. ++u.m_nPostDataUpdateCalls;
  194. }
  195. //-----------------------------------------------------------------------------
  196. // Purpose: Get the receive table for the specified entity
  197. // Input : *pEnt -
  198. // Output : RecvTable*
  199. //-----------------------------------------------------------------------------
  200. static inline RecvTable* GetEntRecvTable( int entnum )
  201. {
  202. IClientNetworkable *pNet = entitylist->GetClientNetworkable( entnum );
  203. if ( pNet )
  204. return pNet->GetClientClass()->m_pRecvTable;
  205. else
  206. return NULL;
  207. }
  208. //-----------------------------------------------------------------------------
  209. // Purpose: Returns true if the entity index corresponds to a player slot
  210. // Input : index -
  211. // Output : bool
  212. //-----------------------------------------------------------------------------
  213. static inline bool CL_IsPlayerIndex( int index )
  214. {
  215. return ( index >= 1 && index <= GetBaseLocalClient().m_nMaxClients );
  216. }
  217. //-----------------------------------------------------------------------------
  218. // Purpose: Bad data was received, just discards incoming delta data.
  219. //-----------------------------------------------------------------------------
  220. void CL_FlushEntityPacket( CClientFrame *packet, char const *errorString, ... )
  221. {
  222. con_nprint_t np;
  223. char str[2048];
  224. va_list marker;
  225. // Spit out an error.
  226. va_start(marker, errorString);
  227. Q_vsnprintf(str, sizeof(str), errorString, marker);
  228. va_end(marker);
  229. ConMsg("%s", str);
  230. np.fixed_width_font = false;
  231. np.time_to_live = 1.0;
  232. np.index = 0;
  233. np.color[ 0 ] = 1.0;
  234. np.color[ 1 ] = 0.2;
  235. np.color[ 2 ] = 0.0;
  236. Con_NXPrintf( &np, "WARNING: CL_FlushEntityPacket, %s", str );
  237. // Free packet memory.
  238. GetBaseLocalClient().DeleteUnusedClientFrame( packet );
  239. }
  240. // ----------------------------------------------------------------------------- //
  241. // Regular handles for ReadPacketEntities.
  242. // ----------------------------------------------------------------------------- //
  243. void CL_CopyNewEntity(
  244. CEntityReadInfo &u,
  245. int iClass,
  246. int iSerialNum
  247. )
  248. {
  249. if ( u.m_nNewEntity < 0 || u.m_nNewEntity >= MAX_EDICTS )
  250. {
  251. Host_Error ("CL_CopyNewEntity: m_nNewEntity >= MAX_EDICTS");
  252. return;
  253. }
  254. // If it's new, make sure we have a slot for it.
  255. IClientNetworkable *ent = entitylist->GetClientNetworkable( u.m_nNewEntity );
  256. if( iClass >= GetBaseLocalClient().m_nServerClasses )
  257. {
  258. Host_Error("CL_CopyNewEntity: invalid class index (%d).\n", iClass);
  259. return;
  260. }
  261. // Delete the entity.
  262. ClientClass *pClass = GetBaseLocalClient().m_pServerClasses[iClass].m_pClientClass;
  263. bool bNew = false;
  264. if ( ent )
  265. {
  266. // if serial number is different, destory old entity
  267. if ( ent->GetIClientUnknown()->GetRefEHandle().GetSerialNumber() != iSerialNum )
  268. {
  269. CL_DeleteDLLEntity( u.m_nNewEntity, "CopyNewEntity" );
  270. ent = NULL; // force a recreate
  271. }
  272. }
  273. if ( !ent )
  274. {
  275. // Ok, it doesn't exist yet, therefore this is not an "entered PVS" message.
  276. ent = CL_CreateDLLEntity( u.m_nNewEntity, iClass, iSerialNum );
  277. if( !ent )
  278. {
  279. Host_Error( "CL_ParsePacketEntities: Error creating entity %s(%i)\n", GetBaseLocalClient().m_pServerClasses[iClass].m_pClientClass->m_pNetworkName, u.m_nNewEntity );
  280. return;
  281. }
  282. bNew = true;
  283. }
  284. int start_bit = u.m_pBuf->GetNumBitsRead();
  285. DataUpdateType_t updateType = bNew ? DATA_UPDATE_CREATED : DATA_UPDATE_DATATABLE_CHANGED;
  286. ent->PreDataUpdate( updateType );
  287. SerializedEntityHandle_t oldbaseline = SERIALIZED_ENTITY_HANDLE_INVALID;
  288. // Get either the static or instance baseline.
  289. PackedEntity *baseline = u.m_bAsDelta ? GetBaseLocalClient().GetEntityBaseline( u.m_nBaseline, u.m_nNewEntity ) : NULL;
  290. if ( baseline && baseline->m_pClientClass == pClass )
  291. {
  292. oldbaseline = baseline->GetPackedData();
  293. }
  294. else
  295. {
  296. // Every entity must have a static or an instance baseline when we get here.
  297. ErrorIfNot(
  298. GetBaseLocalClient().GetClassBaseline( iClass, &oldbaseline ),
  299. ("CL_CopyNewEntity: GetClassBaseline(%d) failed.", iClass)
  300. );
  301. }
  302. RecvTable *pRecvTable = GetEntRecvTable( u.m_nNewEntity );
  303. if( !pRecvTable )
  304. {
  305. Host_Error( "CL_ParseDelta: invalid recv table for ent %d.\n", u.m_nNewEntity );
  306. }
  307. else
  308. {
  309. RecvTable_ReadFieldList( pRecvTable, *u.m_pBuf, u.m_DecodeEntity, -1, true );
  310. if ( u.m_bUpdateBaselines )
  311. {
  312. // store this baseline in u.m_pUpdateBaselines
  313. SerializedEntityHandle_t newbaseline = g_pSerializedEntities->AllocateSerializedEntity( __FILE__, __LINE__ );
  314. RecvTable_MergeDeltas( pRecvTable, oldbaseline, u.m_DecodeEntity, newbaseline, -1, NULL );
  315. // set the other baseline
  316. GetBaseLocalClient().SetEntityBaseline( (u.m_nBaseline==0)?1:0, pClass, u.m_nNewEntity, newbaseline );
  317. RecvTable_Decode( pRecvTable, ent->GetDataTableBasePtr(), newbaseline, u.m_nNewEntity );
  318. }
  319. else
  320. {
  321. // write data from baseline into entity
  322. RecvTable_Decode( pRecvTable, ent->GetDataTableBasePtr(), oldbaseline, u.m_nNewEntity );
  323. // Now parse in the contents of the network stream.
  324. RecvTable_Decode( pRecvTable, ent->GetDataTableBasePtr(), u.m_DecodeEntity, u.m_nNewEntity );
  325. }
  326. }
  327. CL_AddPostDataUpdateCall( u, u.m_nNewEntity, updateType );
  328. // If ent doesn't think it's in PVS, signal that it is
  329. Assert( u.m_pTo->last_entity <= u.m_nNewEntity );
  330. u.m_pTo->last_entity = u.m_nNewEntity;
  331. Assert( !u.m_pTo->transmit_entity.Get(u.m_nNewEntity) );
  332. u.m_pTo->transmit_entity.Set( u.m_nNewEntity );
  333. //
  334. // Net stats..
  335. //
  336. int bit_count = u.m_pBuf->GetNumBitsRead() - start_bit;
  337. if ( cl_entityreport.GetBool() )
  338. CL_RecordEntityBits( u.m_nNewEntity, bit_count );
  339. if ( CL_IsPlayerIndex( u.m_nNewEntity ) )
  340. {
  341. if ( u.m_nNewEntity == GetBaseLocalClient().m_nPlayerSlot + 1 )
  342. {
  343. u.m_nLocalPlayerBits += bit_count;
  344. }
  345. else
  346. {
  347. u.m_nOtherPlayerBits += bit_count;
  348. }
  349. }
  350. }
  351. void CL_PreserveExistingEntity( int nOldEntity )
  352. {
  353. IClientNetworkable *pEnt = entitylist->GetClientNetworkable( nOldEntity );
  354. if ( !pEnt )
  355. {
  356. Host_Error( "CL_PreserveExistingEntity: missing client entity %d.\n", nOldEntity );
  357. return;
  358. }
  359. pEnt->OnDataUnchangedInPVS();
  360. }
  361. void CL_CopyExistingEntity( CEntityReadInfo &u )
  362. {
  363. int start_bit = u.m_pBuf->GetNumBitsRead();
  364. IClientNetworkable *pEnt = entitylist->GetClientNetworkable( u.m_nNewEntity );
  365. if ( !pEnt )
  366. {
  367. Host_Error( "CL_CopyExistingEntity: missing client entity %d.\n", u.m_nNewEntity );
  368. return;
  369. }
  370. Assert( u.m_pFrom->transmit_entity.Get(u.m_nNewEntity) );
  371. // Read raw data from the network stream
  372. pEnt->PreDataUpdate( DATA_UPDATE_DATATABLE_CHANGED );
  373. RecvTable *pRecvTable = GetEntRecvTable( u.m_nNewEntity );
  374. if( !pRecvTable )
  375. {
  376. Host_Error( "CL_ParseDelta: invalid recv table for ent %d.\n", u.m_nNewEntity );
  377. return;
  378. }
  379. RecvTable_ReadFieldList( pRecvTable, *u.m_pBuf, u.m_DecodeEntity, u.m_nNewEntity, true );
  380. // BUG: sometimes we get DeltaEnt packets with zero fields in them, for C_WeaponCSBaseGun-derived entities...
  381. // [CSGO, July 2 2012 - repro is to run a classic/hostage online listen server on X360]
  382. CSerializedEntity *pEntity; pEntity = reinterpret_cast< CSerializedEntity * >( u.m_DecodeEntity );
  383. //Assert( pEntity->GetFieldCount() > 0 );
  384. RecvTable_Decode( pRecvTable, pEnt->GetDataTableBasePtr(), u.m_DecodeEntity, u.m_nNewEntity );
  385. CL_AddPostDataUpdateCall( u, u.m_nNewEntity, DATA_UPDATE_DATATABLE_CHANGED );
  386. u.m_pTo->last_entity = u.m_nNewEntity;
  387. Assert( !u.m_pTo->transmit_entity.Get(u.m_nNewEntity) );
  388. u.m_pTo->transmit_entity.Set( u.m_nNewEntity );
  389. int bit_count = u.m_pBuf->GetNumBitsRead() - start_bit;
  390. if ( cl_entityreport.GetBool() )
  391. CL_RecordEntityBits( u.m_nNewEntity, bit_count );
  392. if ( CL_IsPlayerIndex( u.m_nNewEntity ) )
  393. {
  394. if ( u.m_nNewEntity == GetBaseLocalClient().m_nPlayerSlot + 1 )
  395. {
  396. u.m_nLocalPlayerBits += bit_count;
  397. }
  398. else
  399. {
  400. u.m_nOtherPlayerBits += bit_count;
  401. }
  402. }
  403. }
  404. //-----------------------------------------------------------------------------
  405. // Purpose:
  406. //-----------------------------------------------------------------------------
  407. void CL_MarkEntitiesOutOfPVS( CBitVec<MAX_EDICTS> *pvs_flags )
  408. {
  409. PREFETCH360(pvs_flags, 0);
  410. EntityCacheInfo_t *pInfo = entitylist->GetClientNetworkableArray();
  411. int entityMax = entitylist->GetHighestEntityIndex() + 1;
  412. // Note that we go up to and including the highest_index
  413. bool bReport = cl_entityreport.GetBool();
  414. for ( int i = 0; i < entityMax; i++ )
  415. {
  416. #if defined( _X360 ) || defined( _PS3 )
  417. if ( !(i & 0xF) )
  418. {
  419. PREFETCH360(&pInfo[i], 128);
  420. }
  421. #endif
  422. if ( !pInfo[i].m_pNetworkable )
  423. continue;
  424. // FIXME: We can remove IClientEntity here if we keep track of the
  425. // last frame's entity_in_pvs
  426. bool curstate = !pInfo[i].m_bDormant;
  427. bool newstate = pvs_flags->Get( i ) ? true : false;
  428. if ( !curstate && newstate )
  429. {
  430. // Inform the client entity list that the entity entered the PVS
  431. pInfo[i].m_pNetworkable->NotifyShouldTransmit( SHOULDTRANSMIT_START );
  432. }
  433. else if ( curstate && !newstate )
  434. {
  435. // Inform the client entity list that the entity left the PVS
  436. pInfo[i].m_pNetworkable->NotifyShouldTransmit( SHOULDTRANSMIT_END );
  437. if ( bReport )
  438. {
  439. CL_RecordLeavePVS( i );
  440. }
  441. }
  442. }
  443. }
  444. static void CL_CallPostDataUpdates( CEntityReadInfo &u )
  445. {
  446. MDLCACHE_CRITICAL_SECTION_(g_pMDLCache);
  447. int saveSlot = splitscreen->SetActiveSplitScreenPlayerSlot( 0 );
  448. bool bSaveResolvable = splitscreen->SetLocalPlayerIsResolvable( __FILE__, __LINE__, false );
  449. for ( int i=0; i < u.m_nPostDataUpdateCalls; i++ )
  450. {
  451. CPostDataUpdateCall *pCall = &u.m_PostDataUpdateCalls[i];
  452. IClientNetworkable *pEnt = entitylist->GetClientNetworkable( pCall->m_iEnt );
  453. ErrorIfNot( pEnt,
  454. ("CL_CallPostDataUpdates: missing ent %d", pCall->m_iEnt) );
  455. pEnt->PostDataUpdate( pCall->m_UpdateType );
  456. }
  457. splitscreen->SetActiveSplitScreenPlayerSlot( saveSlot );
  458. splitscreen->SetLocalPlayerIsResolvable( __FILE__, __LINE__, bSaveResolvable );
  459. }
  460. //-----------------------------------------------------------------------------
  461. // Purpose: An svc_packetentities has just been parsed, deal with the
  462. // rest of the data stream. This can be a delta from the baseline or from a previous
  463. // client frame for this client.
  464. // Input : delta -
  465. // *playerbits -
  466. // Output : void CL_ParsePacketEntities
  467. //-----------------------------------------------------------------------------
  468. bool CL_ProcessPacketEntities( const CSVCMsg_PacketEntities &msg )
  469. {
  470. VPROF( "_CL_ParsePacketEntities" );
  471. // Packed entities for that frame
  472. // Allocate space for new packet info.
  473. CClientFrame *newFrame = GetBaseLocalClient().AllocateAndInitFrame( GetBaseLocalClient().GetServerTickCount() );
  474. CClientFrame *oldFrame = NULL;
  475. // if cl_flushentitypacket is set to N, the next N entity updates will be flushed
  476. if ( cl_flushentitypacket.GetInt() )
  477. {
  478. // we can't use this, it is too old
  479. CL_FlushEntityPacket( newFrame, "Forced by cvar\n" );
  480. cl_flushentitypacket.SetValue( cl_flushentitypacket.GetInt() - 1 ); // Reduce the cvar.
  481. return false;
  482. }
  483. if ( msg.is_delta() )
  484. {
  485. if ( replay_debug.GetInt() > 10 && GetBaseLocalClient().m_nHltvReplayDelay )
  486. Msg( "Replay delta-%d update at tick %d, %s bytes\n", GetBaseLocalClient().GetServerTickCount() - msg.delta_from(), GetBaseLocalClient().GetServerTickCount(), V_pretifynum( msg.ByteSize() ) );
  487. if ( GetBaseLocalClient().GetServerTickCount() == msg.delta_from() )
  488. {
  489. Host_Error( "Update self-referencing, connection dropped.\n" );
  490. return false;
  491. }
  492. // Otherwise, mark where we are valid to and point to the packet entities we'll be updating from.
  493. oldFrame = GetBaseLocalClient().GetClientFrame( msg.delta_from() );
  494. if ( !oldFrame )
  495. {
  496. CL_FlushEntityPacket( newFrame, "Update delta not found.\n" );
  497. return false;
  498. }
  499. }
  500. else
  501. {
  502. if ( replay_debug.GetBool() )
  503. Msg( "Full tick %d update\n", GetBaseLocalClient().GetServerTickCount() );
  504. if ( developer.GetInt() != 0 )
  505. ConColorMsg( Color( 255, 100, 255 ), "Receiving uncompressed update from server, baseline %d, byte size %d \n", msg.baseline(), msg.ByteSize() );
  506. // Clear out the client's entity states..
  507. for ( int i=0; i <= entitylist->GetHighestEntityIndex(); i++ )
  508. {
  509. CL_DeleteDLLEntity( i, "ProcessPacketEntities", true );
  510. }
  511. GetBaseLocalClient().FreeEntityBaselines();
  512. ClientDLL_FrameStageNotify( FRAME_NET_FULL_FRAME_UPDATE_ON_REMOVE );
  513. }
  514. // signal client DLL that we have started updating entities
  515. ClientDLL_FrameStageNotify( FRAME_NET_UPDATE_START );
  516. Assert( msg.baseline() >= 0 && msg.baseline() < 2 );
  517. if ( msg.update_baseline() )
  518. {
  519. // server requested to use this snapshot as baseline update
  520. int nUpdateBaseline = ( msg.baseline() == 0) ? 1 : 0;
  521. GetBaseLocalClient().CopyEntityBaseline( msg.baseline(), nUpdateBaseline );
  522. // send new baseline acknowledgement(as reliable)
  523. // Used a (brilliantly named) named temporary because SendNetMsg
  524. // takes a non-const reference because INetMessage::WriteToBuffer
  525. // is non-const.
  526. CCLCMsg_BaselineAck_t namedTemporary;
  527. namedTemporary.set_baseline_tick( GetBaseLocalClient().GetServerTickCount() );
  528. namedTemporary.set_baseline_nr( msg.baseline() );
  529. GetBaseLocalClient().m_NetChannel->SendNetMsg( namedTemporary, true );
  530. }
  531. CEntityReadInfo u;
  532. bf_read entityBuf( &msg.entity_data()[0], msg.entity_data().size() );
  533. u.m_pBuf = &entityBuf;
  534. u.m_pFrom = oldFrame;
  535. u.m_pTo = newFrame;
  536. u.m_bAsDelta = msg.is_delta();
  537. u.m_nHeaderCount = msg.updated_entries();
  538. u.m_nBaseline = msg.baseline();
  539. u.m_bUpdateBaselines = msg.update_baseline();
  540. // update the entities
  541. {
  542. int saveSlot = splitscreen->SetActiveSplitScreenPlayerSlot( 0 );
  543. bool bSaveResolvable = splitscreen->SetLocalPlayerIsResolvable( __FILE__, __LINE__, false );
  544. GetBaseLocalClient().ReadPacketEntities( u );
  545. splitscreen->SetActiveSplitScreenPlayerSlot( saveSlot );
  546. splitscreen->SetLocalPlayerIsResolvable( __FILE__, __LINE__, bSaveResolvable );
  547. }
  548. ClientDLL_FrameStageNotify( FRAME_NET_UPDATE_POSTDATAUPDATE_START );
  549. // call PostDataUpdate() for each entity
  550. CL_CallPostDataUpdates( u );
  551. ClientDLL_FrameStageNotify( FRAME_NET_UPDATE_POSTDATAUPDATE_END );
  552. // call NotifyShouldTransmit() for entities that entered or left the PVS
  553. CL_MarkEntitiesOutOfPVS( &newFrame->transmit_entity );
  554. // adjust net channel stats
  555. GetBaseLocalClient().m_NetChannel->UpdateMessageStats( INetChannelInfo::LOCALPLAYER, u.m_nLocalPlayerBits );
  556. GetBaseLocalClient().m_NetChannel->UpdateMessageStats( INetChannelInfo::OTHERPLAYERS, u.m_nOtherPlayerBits );
  557. GetBaseLocalClient().m_NetChannel->UpdateMessageStats( INetChannelInfo::ENTITIES, -(u.m_nLocalPlayerBits+u.m_nOtherPlayerBits) );
  558. GetBaseLocalClient().DeleteClientFrames( msg.delta_from() );
  559. // If the client has more than 64 frames, the host will start to eat too much memory.
  560. // TODO: We should enforce this somehow.
  561. if ( MAX_CLIENT_FRAMES < GetBaseLocalClient().AddClientFrame( newFrame ) )
  562. {
  563. DevMsg( 1, "CL_ProcessPacketEntities: frame window too big (>%i)\n", MAX_CLIENT_FRAMES );
  564. }
  565. // all update activities are finished
  566. ClientDLL_FrameStageNotify( FRAME_NET_UPDATE_END );
  567. return true;
  568. }
  569. /*
  570. ==================
  571. CL_PreprocessEntities
  572. Server information pertaining to this client only
  573. ==================
  574. */
  575. namespace CDebugOverlay
  576. {
  577. extern void PurgeServerOverlays( void );
  578. }
  579. void CL_PreprocessEntities( void )
  580. {
  581. // Zero latency!!! (single player or listen server?)
  582. bool bIsUsingMultiplayerNetworking = NET_IsMultiplayer();
  583. bool bLastOutgoingCommandEqualsLastAcknowledgedCommand = GetBaseLocalClient().lastoutgoingcommand == GetBaseLocalClient().command_ack;
  584. // We always want to re-run prediction when using the multiplayer networking, or if we're the listen server and we get a packet
  585. // before any frames have run
  586. if ( bIsUsingMultiplayerNetworking ||
  587. bLastOutgoingCommandEqualsLastAcknowledgedCommand )
  588. {
  589. //Msg( "%i/%i CL_ParseClientdata: no latency server ack %i\n",
  590. // host_framecount, GetBaseLocalClient1().tickcount,
  591. // command_ack );
  592. CL_RunPrediction( PREDICTION_SIMULATION_RESULTS_ARRIVING_ON_SEND_FRAME );
  593. }
  594. // Copy some results from prediction back into right spot
  595. // Anything not sent over the network from server to client must be specified here.
  596. //if ( GetBaseLocalClient().last_command_ack )
  597. {
  598. int number_of_commands_executed = ( GetBaseLocalClient().command_ack - GetBaseLocalClient().last_command_ack );
  599. int number_of_simulation_ticks = ( GetBaseLocalClient().GetServerTickCount() - GetBaseLocalClient().last_server_tick );
  600. #if 0
  601. COM_Log( "GetBaseLocalClient().log", "Receiving frame acknowledging %i commands\n",
  602. number_of_commands_executed );
  603. COM_Log( "GetBaseLocalClient().log", " last command number executed %i\n",
  604. GetBaseLocalClient().command_ack );
  605. COM_Log( "GetBaseLocalClient().log", " previous last command number executed %i\n",
  606. GetBaseLocalClient().last_command_ack );
  607. COM_Log( "GetBaseLocalClient().log", " current world frame %i\n",
  608. GetBaseLocalClient().m_nCurrentSequence );
  609. #endif
  610. // Copy last set of changes right into current frame.
  611. g_pClientSidePrediction->PreEntityPacketReceived( number_of_commands_executed, GetBaseLocalClient().m_nCurrentSequence, number_of_simulation_ticks );
  612. }
  613. CDebugOverlay::PurgeServerOverlays();
  614. }