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.

1043 lines
28 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "server_pch.h"
  8. #include <eiface.h>
  9. #include <dt_send.h>
  10. #include <utllinkedlist.h>
  11. #include "tier0/etwprof.h"
  12. #include "dt_send_eng.h"
  13. #include "dt.h"
  14. #include "net_synctags.h"
  15. #include "dt_instrumentation_server.h"
  16. #include "LocalNetworkBackdoor.h"
  17. #include "ents_shared.h"
  18. #include "hltvserver.h"
  19. #include "replayserver.h"
  20. #include "tier0/vcrmode.h"
  21. #include "framesnapshot.h"
  22. // memdbgon must be the last include file in a .cpp file!!!
  23. #include "tier0/memdbgon.h"
  24. extern ConVar g_CV_DTWatchEnt;
  25. //-----------------------------------------------------------------------------
  26. // Delta timing stuff.
  27. //-----------------------------------------------------------------------------
  28. static ConVar sv_deltatime( "sv_deltatime", "0", 0, "Enable profiling of CalcDelta calls" );
  29. static ConVar sv_deltaprint( "sv_deltaprint", "0", 0, "Print accumulated CalcDelta profiling data (only if sv_deltatime is on)" );
  30. #if defined( DEBUG_NETWORKING )
  31. ConVar sv_packettrace( "sv_packettrace", "1", 0, "For debugging, print entity creation/deletion info to console." );
  32. #endif
  33. class CChangeTrack
  34. {
  35. public:
  36. char *m_pName;
  37. int m_nChanged;
  38. int m_nUnchanged;
  39. CCycleCount m_Count;
  40. CCycleCount m_EncodeCount;
  41. };
  42. static CUtlLinkedList<CChangeTrack*, int> g_Tracks;
  43. // These are the main variables used by the SV_CreatePacketEntities function.
  44. // The function is split up into multiple smaller ones and they pass this structure around.
  45. class CEntityWriteInfo : public CEntityInfo
  46. {
  47. public:
  48. bf_write *m_pBuf;
  49. int m_nClientEntity;
  50. PackedEntity *m_pOldPack;
  51. PackedEntity *m_pNewPack;
  52. // For each entity handled in the to packet, mark that's it has already been deleted if that's the case
  53. CBitVec<MAX_EDICTS> m_DeletionFlags;
  54. CFrameSnapshot *m_pFromSnapshot; // = m_pFrom->GetSnapshot();
  55. CFrameSnapshot *m_pToSnapshot; // = m_pTo->GetSnapshot();
  56. CFrameSnapshot *m_pBaseline; // the clients baseline
  57. CBaseServer *m_pServer; // the server who writes this entity
  58. int m_nFullProps; // number of properties send as full update (Enter PVS)
  59. bool m_bCullProps; // filter props by clients in recipient lists
  60. /* Some profiling data
  61. int m_nTotalGap;
  62. int m_nTotalGapCount; */
  63. };
  64. //-----------------------------------------------------------------------------
  65. // Delta timing helpers.
  66. //-----------------------------------------------------------------------------
  67. CChangeTrack* GetChangeTrack( const char *pName )
  68. {
  69. FOR_EACH_LL( g_Tracks, i )
  70. {
  71. CChangeTrack *pCur = g_Tracks[i];
  72. if ( stricmp( pCur->m_pName, pName ) == 0 )
  73. return pCur;
  74. }
  75. CChangeTrack *pCur = new CChangeTrack;
  76. int len = strlen(pName)+1;
  77. pCur->m_pName = new char[len];
  78. Q_strncpy( pCur->m_pName, pName, len );
  79. pCur->m_nChanged = pCur->m_nUnchanged = 0;
  80. g_Tracks.AddToTail( pCur );
  81. return pCur;
  82. }
  83. void PrintChangeTracks()
  84. {
  85. ConMsg( "\n\n" );
  86. ConMsg( "------------------------------------------------------------------------\n" );
  87. ConMsg( "CalcDelta MS / %% time / Encode MS / # Changed / # Unchanged / Class Name\n" );
  88. ConMsg( "------------------------------------------------------------------------\n" );
  89. CCycleCount total, encodeTotal;
  90. FOR_EACH_LL( g_Tracks, i )
  91. {
  92. CChangeTrack *pCur = g_Tracks[i];
  93. CCycleCount::Add( pCur->m_Count, total, total );
  94. CCycleCount::Add( pCur->m_EncodeCount, encodeTotal, encodeTotal );
  95. }
  96. FOR_EACH_LL( g_Tracks, j )
  97. {
  98. CChangeTrack *pCur = g_Tracks[j];
  99. ConMsg( "%6.2fms %5.2f %6.2fms %4d %4d %s\n",
  100. pCur->m_Count.GetMillisecondsF(),
  101. pCur->m_Count.GetMillisecondsF() * 100.0f / total.GetMillisecondsF(),
  102. pCur->m_EncodeCount.GetMillisecondsF(),
  103. pCur->m_nChanged,
  104. pCur->m_nUnchanged,
  105. pCur->m_pName
  106. );
  107. }
  108. ConMsg( "\n\n" );
  109. ConMsg( "Total CalcDelta MS: %.2f\n\n", total.GetMillisecondsF() );
  110. ConMsg( "Total Encode MS: %.2f\n\n", encodeTotal.GetMillisecondsF() );
  111. }
  112. //-----------------------------------------------------------------------------
  113. // Purpose: Entity wasn't dealt with in packet, but it has been deleted, we'll flag
  114. // the entity for destruction
  115. // Input : type -
  116. // entnum -
  117. // *from -
  118. // *to -
  119. // Output : Returns true on success, false on failure.
  120. //-----------------------------------------------------------------------------
  121. static inline bool SV_NeedsExplicitDestroy( int entnum, CFrameSnapshot *from, CFrameSnapshot *to )
  122. {
  123. // Never on uncompressed packet
  124. if( entnum >= to->m_nNumEntities || to->m_pEntities[entnum].m_pClass == NULL ) // doesn't exits in new
  125. {
  126. if ( entnum >= from->m_nNumEntities )
  127. return false; // didn't exist in old
  128. // in old, but not in new, destroy.
  129. if( from->m_pEntities[ entnum ].m_pClass != NULL )
  130. {
  131. return true;
  132. }
  133. }
  134. return false;
  135. }
  136. //-----------------------------------------------------------------------------
  137. // Purpose: Creates a delta header for the entity
  138. //-----------------------------------------------------------------------------
  139. static inline void SV_UpdateHeaderDelta(
  140. CEntityWriteInfo &u,
  141. int entnum )
  142. {
  143. // Profiling info
  144. // u.m_nTotalGap += entnum - u.m_nHeaderBase;
  145. // u.m_nTotalGapCount++;
  146. // Keep track of number of headers so we can tell the client
  147. u.m_nHeaderCount++;
  148. u.m_nHeaderBase = entnum;
  149. }
  150. //
  151. // Write the delta header. Also update the header delta info if bUpdateHeaderDelta is true.
  152. //
  153. // There are some cases where you want to tenatively write a header, then possibly back it out.
  154. // In these cases:
  155. // - pass in false for bUpdateHeaderDelta
  156. // - store the return value from SV_WriteDeltaHeader
  157. // - call SV_UpdateHeaderDelta ONLY if you want to keep the delta header it wrote
  158. //
  159. static inline void SV_WriteDeltaHeader(
  160. CEntityWriteInfo &u,
  161. int entnum,
  162. int flags )
  163. {
  164. bf_write *pBuf = u.m_pBuf;
  165. // int startbit = pBuf->GetNumBitsWritten();
  166. int offset = entnum - u.m_nHeaderBase - 1;
  167. Assert ( offset >= 0 );
  168. SyncTag_Write( u.m_pBuf, "Hdr" );
  169. pBuf->WriteUBitVar( offset );
  170. if ( flags & FHDR_LEAVEPVS )
  171. {
  172. pBuf->WriteOneBit( 1 ); // leave PVS bit
  173. pBuf->WriteOneBit( flags & FHDR_DELETE );
  174. }
  175. else
  176. {
  177. pBuf->WriteOneBit( 0 ); // delta or enter PVS
  178. pBuf->WriteOneBit( flags & FHDR_ENTERPVS );
  179. }
  180. SV_UpdateHeaderDelta( u, entnum );
  181. }
  182. // Calculates the delta between the two states and writes the delta and the new properties
  183. // into u.m_pBuf. Returns false if the states are the same.
  184. //
  185. // Also uses the IFrameChangeList in pTo to come up with a smaller set of properties to delta against.
  186. // It deltas against any properties that have changed since iFromFrame.
  187. // If iFromFrame is -1, then it deltas all properties.
  188. static int SV_CalcDeltaAndWriteProps(
  189. CEntityWriteInfo &u,
  190. const void *pFromData,
  191. int nFromBits,
  192. PackedEntity *pTo
  193. )
  194. {
  195. // Calculate the delta props.
  196. int deltaProps[MAX_DATATABLE_PROPS];
  197. void *pToData = pTo->GetData();
  198. int nToBits = pTo->GetNumBits();
  199. SendTable *pToTable = pTo->m_pServerClass->m_pTable;
  200. // TODO if our baseline is compressed, uncompress first
  201. Assert( !pTo->IsCompressed() );
  202. int nDeltaProps = SendTable_CalcDelta(
  203. pToTable,
  204. pFromData,
  205. nFromBits,
  206. pToData,
  207. nToBits,
  208. deltaProps,
  209. ARRAYSIZE( deltaProps ),
  210. pTo->m_nEntityIndex );
  211. // Cull out props given what the proxies say.
  212. int culledProps[MAX_DATATABLE_PROPS];
  213. int nCulledProps = 0;
  214. if ( nDeltaProps )
  215. {
  216. nCulledProps = SendTable_CullPropsFromProxies(
  217. pToTable,
  218. deltaProps,
  219. nDeltaProps,
  220. u.m_nClientEntity-1,
  221. NULL,
  222. -1,
  223. pTo->GetRecipients(),
  224. pTo->GetNumRecipients(),
  225. culledProps,
  226. ARRAYSIZE( culledProps ) );
  227. }
  228. // Write the properties.
  229. SendTable_WritePropList(
  230. pToTable,
  231. pToData, // object data
  232. pTo->GetNumBits(),
  233. u.m_pBuf, // output buffer
  234. pTo->m_nEntityIndex,
  235. culledProps,
  236. nCulledProps );
  237. return nCulledProps;
  238. }
  239. // NOTE: to optimize this, it could store the bit offsets of each property in the packed entity.
  240. // It would only have to store the offsets for the entities for each frame, since it only reaches
  241. // into the current frame's entities here.
  242. static inline void SV_WritePropsFromPackedEntity(
  243. CEntityWriteInfo &u,
  244. const int *pCheckProps,
  245. const int nCheckProps
  246. )
  247. {
  248. PackedEntity * pTo = u.m_pNewPack;
  249. PackedEntity * pFrom = u.m_pOldPack;
  250. SendTable *pSendTable = pTo->m_pServerClass->m_pTable;
  251. CServerDTITimer timer( pSendTable, SERVERDTI_WRITE_DELTA_PROPS );
  252. if ( g_bServerDTIEnabled && !u.m_pServer->IsHLTV() && !u.m_pServer->IsReplay() )
  253. {
  254. ICollideable *pEnt = sv.edicts[pTo->m_nEntityIndex].GetCollideable();
  255. ICollideable *pClientEnt = sv.edicts[u.m_nClientEntity].GetCollideable();
  256. if ( pEnt && pClientEnt )
  257. {
  258. float flDist = (pEnt->GetCollisionOrigin() - pClientEnt->GetCollisionOrigin()).Length();
  259. ServerDTI_AddEntityEncodeEvent( pSendTable, flDist );
  260. }
  261. }
  262. const void *pToData;
  263. int nToBits;
  264. if ( pTo->IsCompressed() )
  265. {
  266. // let server uncompress PackedEntity
  267. pToData = u.m_pServer->UncompressPackedEntity( pTo, nToBits );
  268. }
  269. else
  270. {
  271. // get raw data direct
  272. pToData = pTo->GetData();
  273. nToBits = pTo->GetNumBits();
  274. }
  275. Assert( pToData != NULL );
  276. // Cull out the properties that their proxies said not to send to this client.
  277. int pSendProps[MAX_DATATABLE_PROPS];
  278. const int *sendProps = pCheckProps;
  279. int nSendProps = nCheckProps;
  280. bf_write bufStart;
  281. // cull properties that are removed by SendProxies for this client.
  282. // don't do that for HLTV relay proxies
  283. if ( u.m_bCullProps )
  284. {
  285. sendProps = pSendProps;
  286. nSendProps = SendTable_CullPropsFromProxies(
  287. pSendTable,
  288. pCheckProps,
  289. nCheckProps,
  290. u.m_nClientEntity-1,
  291. pFrom->GetRecipients(),
  292. pFrom->GetNumRecipients(),
  293. pTo->GetRecipients(),
  294. pTo->GetNumRecipients(),
  295. pSendProps,
  296. ARRAYSIZE( pSendProps )
  297. );
  298. }
  299. else
  300. {
  301. // this is a HLTV relay proxy
  302. bufStart = *u.m_pBuf;
  303. }
  304. SendTable_WritePropList(
  305. pSendTable,
  306. pToData,
  307. nToBits,
  308. u.m_pBuf,
  309. pTo->m_nEntityIndex,
  310. sendProps,
  311. nSendProps
  312. );
  313. if ( !u.m_bCullProps && hltv )
  314. {
  315. // this is a HLTV relay proxy, cache delta bits
  316. int nBits = u.m_pBuf->GetNumBitsWritten() - bufStart.GetNumBitsWritten();
  317. hltv->m_DeltaCache.AddDeltaBits( pTo->m_nEntityIndex, u.m_pFromSnapshot->m_nTickCount, nBits, &bufStart );
  318. }
  319. }
  320. //-----------------------------------------------------------------------------
  321. // Purpose: See if the entity needs a "hard" reset ( i.e., and explicit creation tag )
  322. // This should only occur if the entity slot deleted and re-created an entity faster than
  323. // the last two updates toa player. Should never or almost never occur. You never know though.
  324. // Input : type -
  325. // entnum -
  326. // *from -
  327. // *to -
  328. // Output : Returns true on success, false on failure.
  329. //-----------------------------------------------------------------------------
  330. static bool SV_NeedsExplicitCreate( CEntityWriteInfo &u )
  331. {
  332. // Never on uncompressed packet
  333. if ( !u.m_bAsDelta )
  334. {
  335. return false;
  336. }
  337. const int index = u.m_nNewEntity;
  338. if ( index >= u.m_pFromSnapshot->m_nNumEntities )
  339. return true; // entity didn't exist in old frame, so create
  340. // Server thinks the entity was continues, but the serial # changed, so we might need to destroy and recreate it
  341. const CFrameSnapshotEntry *pFromEnt = &u.m_pFromSnapshot->m_pEntities[index];
  342. const CFrameSnapshotEntry *pToEnt = &u.m_pToSnapshot->m_pEntities[index];
  343. bool bNeedsExplicitCreate = (pFromEnt->m_pClass == NULL) || pFromEnt->m_nSerialNumber != pToEnt->m_nSerialNumber;
  344. #ifdef _DEBUG
  345. if ( !bNeedsExplicitCreate )
  346. {
  347. // If it doesn't need explicit create, then the classnames should match.
  348. // This assert is analagous to the "Server / Client mismatch" one on the client.
  349. static int nWhines = 0;
  350. if ( pFromEnt->m_pClass->GetName() != pToEnt->m_pClass->GetName() )
  351. {
  352. if ( ++nWhines < 4 )
  353. {
  354. Msg( "ERROR in SV_NeedsExplicitCreate: ent %d from/to classname (%s/%s) mismatch.\n", u.m_nNewEntity, pFromEnt->m_pClass->GetName(), pToEnt->m_pClass->GetName() );
  355. }
  356. }
  357. }
  358. #endif
  359. return bNeedsExplicitCreate;
  360. }
  361. static inline void SV_DetermineUpdateType( CEntityWriteInfo &u )
  362. {
  363. // Figure out how we want to update the entity.
  364. if( u.m_nNewEntity < u.m_nOldEntity )
  365. {
  366. // If the entity was not in the old packet (oldnum == 9999), then
  367. // delta from the baseline since this is a new entity.
  368. u.m_UpdateType = EnterPVS;
  369. return;
  370. }
  371. if( u.m_nNewEntity > u.m_nOldEntity )
  372. {
  373. // If the entity was in the old list, but is not in the new list
  374. // (newnum == 9999), then construct a special remove message.
  375. u.m_UpdateType = LeavePVS;
  376. return;
  377. }
  378. Assert( u.m_pToSnapshot->m_pEntities[ u.m_nNewEntity ].m_pClass );
  379. bool recreate = SV_NeedsExplicitCreate( u );
  380. if ( recreate )
  381. {
  382. u.m_UpdateType = EnterPVS;
  383. return;
  384. }
  385. // These should be the same! If they're not, then it should detect an explicit create message.
  386. Assert( u.m_pOldPack->m_pServerClass == u.m_pNewPack->m_pServerClass);
  387. // We can early out with the delta bits if we are using the same pack handles...
  388. if ( u.m_pOldPack == u.m_pNewPack )
  389. {
  390. Assert( u.m_pOldPack != NULL );
  391. u.m_UpdateType = PreserveEnt;
  392. return;
  393. }
  394. #ifndef _X360
  395. int nBits;
  396. #if defined( REPLAY_ENABLED )
  397. if ( !u.m_bCullProps && (hltv || replay) )
  398. {
  399. unsigned char *pBuffer = hltv ? hltv ->m_DeltaCache.FindDeltaBits( u.m_nNewEntity, u.m_pFromSnapshot->m_nTickCount, nBits )
  400. : replay->m_DeltaCache.FindDeltaBits( u.m_nNewEntity, u.m_pFromSnapshot->m_nTickCount, nBits );
  401. #else
  402. if ( !u.m_bCullProps && hltv )
  403. {
  404. unsigned char *pBuffer = hltv->m_DeltaCache.FindDeltaBits( u.m_nNewEntity, u.m_pFromSnapshot->m_nTickCount, nBits );
  405. #endif
  406. if ( pBuffer )
  407. {
  408. if ( nBits > 0 )
  409. {
  410. // Write a header.
  411. SV_WriteDeltaHeader( u, u.m_nNewEntity, FHDR_ZERO );
  412. // just write the cached bit stream
  413. u.m_pBuf->WriteBits( pBuffer, nBits );
  414. u.m_UpdateType = DeltaEnt;
  415. }
  416. else
  417. {
  418. u.m_UpdateType = PreserveEnt;
  419. }
  420. return; // we used the cache, great
  421. }
  422. }
  423. #endif
  424. int checkProps[MAX_DATATABLE_PROPS];
  425. int nCheckProps = u.m_pNewPack->GetPropsChangedAfterTick( u.m_pFromSnapshot->m_nTickCount, checkProps, ARRAYSIZE( checkProps ) );
  426. if ( nCheckProps == -1 )
  427. {
  428. // check failed, we have to recalc delta props based on from & to snapshot
  429. // that should happen only in HLTV/Replay demo playback mode, this code is really expensive
  430. const void *pOldData, *pNewData;
  431. int nOldBits, nNewBits;
  432. if ( u.m_pOldPack->IsCompressed() )
  433. {
  434. pOldData = u.m_pServer->UncompressPackedEntity( u.m_pOldPack, nOldBits );
  435. }
  436. else
  437. {
  438. pOldData = u.m_pOldPack->GetData();
  439. nOldBits = u.m_pOldPack->GetNumBits();
  440. }
  441. if ( u.m_pNewPack->IsCompressed() )
  442. {
  443. pNewData = u.m_pServer->UncompressPackedEntity( u.m_pNewPack, nNewBits );
  444. }
  445. else
  446. {
  447. pNewData = u.m_pNewPack->GetData();
  448. nNewBits = u.m_pNewPack->GetNumBits();
  449. }
  450. nCheckProps = SendTable_CalcDelta(
  451. u.m_pOldPack->m_pServerClass->m_pTable,
  452. pOldData,
  453. nOldBits,
  454. pNewData,
  455. nNewBits,
  456. checkProps,
  457. ARRAYSIZE( checkProps ),
  458. u.m_nNewEntity
  459. );
  460. }
  461. #ifndef NO_VCR
  462. if ( vcr_verbose.GetInt() )
  463. {
  464. VCRGenericValueVerify( "checkProps", checkProps, sizeof( checkProps[0] ) * nCheckProps );
  465. }
  466. #endif
  467. if ( nCheckProps > 0 )
  468. {
  469. // Write a header.
  470. SV_WriteDeltaHeader( u, u.m_nNewEntity, FHDR_ZERO );
  471. #if defined( DEBUG_NETWORKING )
  472. int startBit = u.m_pBuf->GetNumBitsWritten();
  473. #endif
  474. SV_WritePropsFromPackedEntity( u, checkProps, nCheckProps );
  475. #if defined( DEBUG_NETWORKING )
  476. int endBit = u.m_pBuf->GetNumBitsWritten();
  477. TRACE_PACKET( ( " Delta Bits (%d) = %d (%d bytes)\n", u.m_nNewEntity, (endBit - startBit), ( (endBit - startBit) + 7 ) / 8 ) );
  478. #endif
  479. // If the numbers are the same, then the entity was in the old and new packet.
  480. // Just delta compress the differences.
  481. u.m_UpdateType = DeltaEnt;
  482. }
  483. else
  484. {
  485. #ifndef _X360
  486. if ( !u.m_bCullProps )
  487. {
  488. if ( hltv )
  489. {
  490. // no bits changed, PreserveEnt
  491. hltv->m_DeltaCache.AddDeltaBits( u.m_nNewEntity, u.m_pFromSnapshot->m_nTickCount, 0, NULL );
  492. }
  493. #if defined( REPLAY_ENABLED )
  494. if ( replay )
  495. {
  496. // no bits changed, PreserveEnt
  497. replay->m_DeltaCache.AddDeltaBits( u.m_nNewEntity, u.m_pFromSnapshot->m_nTickCount, 0, NULL );
  498. }
  499. #endif
  500. }
  501. #endif
  502. u.m_UpdateType = PreserveEnt;
  503. }
  504. }
  505. static inline ServerClass* GetEntServerClass(edict_t *pEdict)
  506. {
  507. return pEdict->GetNetworkable()->GetServerClass();
  508. }
  509. static inline void SV_WriteEnterPVS( CEntityWriteInfo &u )
  510. {
  511. TRACE_PACKET(( " SV Enter PVS (%d) %s\n", u.m_nNewEntity, u.m_pNewPack->m_pServerClass->m_pNetworkName ) );
  512. SV_WriteDeltaHeader( u, u.m_nNewEntity, FHDR_ENTERPVS );
  513. Assert( u.m_nNewEntity < u.m_pToSnapshot->m_nNumEntities );
  514. CFrameSnapshotEntry *entry = &u.m_pToSnapshot->m_pEntities[u.m_nNewEntity];
  515. ServerClass *pClass = entry->m_pClass;
  516. if ( !pClass )
  517. {
  518. Host_Error("SV_CreatePacketEntities: GetEntServerClass failed for ent %d.\n", u.m_nNewEntity);
  519. }
  520. TRACE_PACKET(( " SV Enter Class %s\n", pClass->m_pNetworkName ) );
  521. if ( pClass->m_ClassID >= u.m_pServer->serverclasses )
  522. {
  523. ConMsg( "pClass->m_ClassID(%i) >= %i\n", pClass->m_ClassID, u.m_pServer->serverclasses );
  524. Assert( 0 );
  525. }
  526. u.m_pBuf->WriteUBitLong( pClass->m_ClassID, u.m_pServer->serverclassbits );
  527. // Write some of the serial number's bits.
  528. u.m_pBuf->WriteUBitLong( entry->m_nSerialNumber, NUM_NETWORKED_EHANDLE_SERIAL_NUMBER_BITS );
  529. // Get the baseline.
  530. // Since the ent is in the fullpack, then it must have either a static or an instance baseline.
  531. PackedEntity *pBaseline = u.m_bAsDelta ? framesnapshotmanager->GetPackedEntity( u.m_pBaseline, u.m_nNewEntity ) : NULL;
  532. const void *pFromData;
  533. int nFromBits;
  534. if ( pBaseline && (pBaseline->m_pServerClass == u.m_pNewPack->m_pServerClass) )
  535. {
  536. Assert( !pBaseline->IsCompressed() );
  537. pFromData = pBaseline->GetData();
  538. nFromBits = pBaseline->GetNumBits();
  539. }
  540. else
  541. {
  542. // Since the ent is in the fullpack, then it must have either a static or an instance baseline.
  543. int nFromBytes;
  544. if ( !u.m_pServer->GetClassBaseline( pClass, &pFromData, &nFromBytes ) )
  545. {
  546. Error( "SV_WriteEnterPVS: missing instance baseline for '%s'.", pClass->m_pNetworkName );
  547. }
  548. ErrorIfNot( pFromData,
  549. ("SV_WriteEnterPVS: missing pFromData for '%s'.", pClass->m_pNetworkName)
  550. );
  551. nFromBits = nFromBytes * 8; // NOTE: this isn't the EXACT number of bits but that's ok since it's
  552. // only used to detect if we overran the buffer (and if we do, it's probably
  553. // by more than 7 bits).
  554. }
  555. if ( u.m_pTo->from_baseline )
  556. {
  557. // remember that we sent this entity as full update from entity baseline
  558. u.m_pTo->from_baseline->Set( u.m_nNewEntity );
  559. }
  560. const void *pToData;
  561. int nToBits;
  562. if ( u.m_pNewPack->IsCompressed() )
  563. {
  564. pToData = u.m_pServer->UncompressPackedEntity( u.m_pNewPack, nToBits );
  565. }
  566. else
  567. {
  568. pToData = u.m_pNewPack->GetData();
  569. nToBits = u.m_pNewPack->GetNumBits();
  570. }
  571. /*if ( server->IsHLTV() || server->IsReplay() )
  572. {*/
  573. // send all changed properties when entering PVS (no SendProxy culling since we may use it as baseline
  574. u.m_nFullProps += SendTable_WriteAllDeltaProps( pClass->m_pTable, pFromData, nFromBits,
  575. pToData, nToBits, u.m_pNewPack->m_nEntityIndex, u.m_pBuf );
  576. /*}
  577. else
  578. {
  579. // remove all props that are excluded for this client
  580. u.m_nFullProps += SV_CalcDeltaAndWriteProps( u, pFromData, nFromBits, u.m_pNewPack );
  581. }*/
  582. if ( u.m_nNewEntity == u.m_nOldEntity )
  583. u.NextOldEntity(); // this was a entity recreate
  584. u.NextNewEntity();
  585. }
  586. static inline void SV_WriteLeavePVS( CEntityWriteInfo &u )
  587. {
  588. int headerflags = FHDR_LEAVEPVS;
  589. bool deleteentity = false;
  590. if ( u.m_bAsDelta )
  591. {
  592. deleteentity = SV_NeedsExplicitDestroy( u.m_nOldEntity, u.m_pFromSnapshot, u.m_pToSnapshot );
  593. }
  594. if ( deleteentity )
  595. {
  596. // Mark that we handled deletion of this index
  597. u.m_DeletionFlags.Set( u.m_nOldEntity );
  598. headerflags |= FHDR_DELETE;
  599. }
  600. TRACE_PACKET( ( " SV Leave PVS (%d) %s %s\n", u.m_nOldEntity,
  601. deleteentity ? "deleted" : "left pvs",
  602. u.m_pOldPack->m_pServerClass->m_pNetworkName ) );
  603. SV_WriteDeltaHeader( u, u.m_nOldEntity, headerflags );
  604. u.NextOldEntity();
  605. }
  606. static inline void SV_WriteDeltaEnt( CEntityWriteInfo &u )
  607. {
  608. TRACE_PACKET( ( " SV Delta PVS (%d %d) %s\n", u.m_nNewEntity, u.m_nOldEntity, u.m_pOldPack->m_pServerClass->m_pNetworkName ) );
  609. // NOTE: it was already written in DetermineUpdateType. By doing it this way, we avoid an expensive
  610. // (non-byte-aligned) copy of the data.
  611. u.NextOldEntity();
  612. u.NextNewEntity();
  613. }
  614. static inline void SV_PreserveEnt( CEntityWriteInfo &u )
  615. {
  616. TRACE_PACKET( ( " SV Preserve PVS (%d) %s\n", u.m_nOldEntity, u.m_pOldPack->m_pServerClass->m_pNetworkName ) );
  617. // updateType is preserveEnt. The client will detect this because our next entity will have a newnum
  618. // that is greater than oldnum, in which case the client just keeps the current entity alive.
  619. u.NextOldEntity();
  620. u.NextNewEntity();
  621. }
  622. static inline void SV_WriteEntityUpdate( CEntityWriteInfo &u )
  623. {
  624. switch( u.m_UpdateType )
  625. {
  626. case EnterPVS:
  627. {
  628. SV_WriteEnterPVS( u );
  629. }
  630. break;
  631. case LeavePVS:
  632. {
  633. SV_WriteLeavePVS( u );
  634. }
  635. break;
  636. case DeltaEnt:
  637. {
  638. SV_WriteDeltaEnt( u );
  639. }
  640. break;
  641. case PreserveEnt:
  642. {
  643. SV_PreserveEnt( u );
  644. }
  645. break;
  646. }
  647. }
  648. static inline int SV_WriteDeletions( CEntityWriteInfo &u )
  649. {
  650. if( !u.m_bAsDelta )
  651. return 0;
  652. int nNumDeletions = 0;
  653. CFrameSnapshot *pFromSnapShot = u.m_pFromSnapshot;
  654. CFrameSnapshot *pToSnapShot = u.m_pToSnapshot;
  655. int nLast = MAX( pFromSnapShot->m_nNumEntities, pToSnapShot->m_nNumEntities );
  656. for ( int i = 0; i < nLast; i++ )
  657. {
  658. // Packet update didn't clear it out expressly
  659. if ( u.m_DeletionFlags.Get( i ) )
  660. continue;
  661. // If the entity is marked to transmit in the u.m_pTo, then it can never be destroyed by the m_iExplicitDeleteSlots
  662. // Another possible fix would be to clear any slots in the explicit deletes list that were actually occupied when a snapshot was taken
  663. if ( u.m_pTo->transmit_entity.Get(i) )
  664. continue;
  665. // Looks like it should be gone
  666. bool bNeedsExplicitDelete = SV_NeedsExplicitDestroy( i, pFromSnapShot, pToSnapShot );
  667. if ( !bNeedsExplicitDelete && u.m_pTo )
  668. {
  669. bNeedsExplicitDelete = ( pToSnapShot->m_iExplicitDeleteSlots.Find(i) != pToSnapShot->m_iExplicitDeleteSlots.InvalidIndex() );
  670. // We used to do more stuff here as a sanity check, but I don't think it was necessary since the only thing that would unset the bould would be a "recreate" in the same slot which is
  671. // already implied by the u.m_pTo->transmit_entity.Get(i) check
  672. }
  673. // Check conditions
  674. if ( bNeedsExplicitDelete )
  675. {
  676. TRACE_PACKET( ( " SV Explicit Destroy (%d)\n", i ) );
  677. u.m_pBuf->WriteOneBit(1);
  678. u.m_pBuf->WriteUBitLong( i, MAX_EDICT_BITS );
  679. ++nNumDeletions;
  680. }
  681. }
  682. // No more entities..
  683. u.m_pBuf->WriteOneBit(0);
  684. return nNumDeletions;
  685. }
  686. /*
  687. =============
  688. WritePacketEntities
  689. Computes either a compressed, or uncompressed delta buffer for the client.
  690. Returns the size IN BITS of the message buffer created.
  691. =============
  692. */
  693. void CBaseServer::WriteDeltaEntities( CBaseClient *client, CClientFrame *to, CClientFrame *from, bf_write &pBuf )
  694. {
  695. VPROF_BUDGET( "CBaseServer::WriteDeltaEntities", VPROF_BUDGETGROUP_OTHER_NETWORKING );
  696. // Setup the CEntityWriteInfo structure.
  697. CEntityWriteInfo u;
  698. u.m_pBuf = &pBuf;
  699. u.m_pTo = to;
  700. u.m_pToSnapshot = to->GetSnapshot();
  701. u.m_pBaseline = client->m_pBaseline;
  702. u.m_nFullProps = 0;
  703. u.m_pServer = this;
  704. u.m_nClientEntity = client->m_nEntityIndex;
  705. #ifndef _XBOX
  706. if ( IsHLTV() || IsReplay() )
  707. {
  708. // cull props only on master proxy
  709. u.m_bCullProps = sv.IsActive();
  710. }
  711. else
  712. #endif
  713. {
  714. u.m_bCullProps = true; // always cull props for players
  715. }
  716. if ( from != NULL )
  717. {
  718. u.m_bAsDelta = true;
  719. u.m_pFrom = from;
  720. u.m_pFromSnapshot = from->GetSnapshot();
  721. Assert( u.m_pFromSnapshot );
  722. }
  723. else
  724. {
  725. u.m_bAsDelta = false;
  726. u.m_pFrom = NULL;
  727. u.m_pFromSnapshot = NULL;
  728. }
  729. u.m_nHeaderCount = 0;
  730. // u.m_nTotalGap = 0;
  731. // u.m_nTotalGapCount = 0;
  732. // set from_baseline pointer if this snapshot may become a baseline update
  733. if ( client->m_nBaselineUpdateTick == -1 )
  734. {
  735. client->m_BaselinesSent.ClearAll();
  736. to->from_baseline = &client->m_BaselinesSent;
  737. }
  738. // Write the header, TODO use class SVC_PacketEntities
  739. TRACE_PACKET(( "WriteDeltaEntities (%d)\n", u.m_pToSnapshot->m_nNumEntities ));
  740. u.m_pBuf->WriteUBitLong( svc_PacketEntities, NETMSG_TYPE_BITS );
  741. u.m_pBuf->WriteUBitLong( u.m_pToSnapshot->m_nNumEntities, MAX_EDICT_BITS );
  742. if ( u.m_bAsDelta )
  743. {
  744. u.m_pBuf->WriteOneBit( 1 ); // use delta sequence
  745. u.m_pBuf->WriteLong( u.m_pFrom->tick_count ); // This is the sequence # that we are updating from.
  746. }
  747. else
  748. {
  749. u.m_pBuf->WriteOneBit( 0 ); // use baseline
  750. }
  751. u.m_pBuf->WriteUBitLong ( client->m_nBaselineUsed, 1 ); // tell client what baseline we are using
  752. // Store off current position
  753. bf_write savepos = *u.m_pBuf;
  754. // Save room for number of headers to parse, too
  755. u.m_pBuf->WriteUBitLong ( 0, MAX_EDICT_BITS+DELTASIZE_BITS+1 );
  756. int startbit = u.m_pBuf->GetNumBitsWritten();
  757. bool bIsTracing = client->IsTracing();
  758. if ( bIsTracing )
  759. {
  760. client->TraceNetworkData( pBuf, "Delta Entities Overhead" );
  761. }
  762. // Don't work too hard if we're using the optimized single-player mode.
  763. if ( !g_pLocalNetworkBackdoor )
  764. {
  765. // Iterate through the in PVS bitfields until we find an entity
  766. // that was either in the old pack or the new pack
  767. u.NextOldEntity();
  768. u.NextNewEntity();
  769. while ( (u.m_nOldEntity != ENTITY_SENTINEL) || (u.m_nNewEntity != ENTITY_SENTINEL) )
  770. {
  771. u.m_pNewPack = (u.m_nNewEntity != ENTITY_SENTINEL) ? framesnapshotmanager->GetPackedEntity( u.m_pToSnapshot, u.m_nNewEntity ) : NULL;
  772. u.m_pOldPack = (u.m_nOldEntity != ENTITY_SENTINEL) ? framesnapshotmanager->GetPackedEntity( u.m_pFromSnapshot, u.m_nOldEntity ) : NULL;
  773. int nEntityStartBit = pBuf.GetNumBitsWritten();
  774. // Figure out how we want to write this entity.
  775. SV_DetermineUpdateType( u );
  776. SV_WriteEntityUpdate( u );
  777. if ( !bIsTracing )
  778. continue;
  779. switch ( u.m_UpdateType )
  780. {
  781. default:
  782. case PreserveEnt:
  783. break;
  784. case EnterPVS:
  785. {
  786. char const *eString = sv.edicts[ u.m_pNewPack->m_nEntityIndex ].GetNetworkable()->GetClassName();
  787. client->TraceNetworkData( pBuf, "enter [%s]", eString );
  788. ETWMark1I( eString, pBuf.GetNumBitsWritten() - nEntityStartBit );
  789. }
  790. break;
  791. case LeavePVS:
  792. {
  793. // Note, can't use GetNetworkable() since the edict has been freed at this point
  794. char const *eString = u.m_pOldPack->m_pServerClass->m_pNetworkName;
  795. client->TraceNetworkData( pBuf, "leave [%s]", eString );
  796. ETWMark1I( eString, pBuf.GetNumBitsWritten() - nEntityStartBit );
  797. }
  798. break;
  799. case DeltaEnt:
  800. {
  801. char const *eString = sv.edicts[ u.m_pOldPack->m_nEntityIndex ].GetNetworkable()->GetClassName();
  802. client->TraceNetworkData( pBuf, "delta [%s]", eString );
  803. ETWMark1I( eString, pBuf.GetNumBitsWritten() - nEntityStartBit );
  804. }
  805. break;
  806. }
  807. }
  808. // Now write out the express deletions
  809. int nNumDeletions = SV_WriteDeletions( u );
  810. if ( bIsTracing )
  811. {
  812. client->TraceNetworkData( pBuf, "Delta: [%d] deletions", nNumDeletions );
  813. }
  814. }
  815. // get number of written bits
  816. int length = u.m_pBuf->GetNumBitsWritten() - startbit;
  817. // go back to header and fill in correct length now
  818. savepos.WriteUBitLong( u.m_nHeaderCount, MAX_EDICT_BITS );
  819. savepos.WriteUBitLong( length, DELTASIZE_BITS );
  820. bool bUpdateBaseline = ( (client->m_nBaselineUpdateTick == -1) &&
  821. (u.m_nFullProps > 0 || !u.m_bAsDelta) );
  822. if ( bUpdateBaseline && u.m_pBaseline )
  823. {
  824. // tell client to use this snapshot as baseline update
  825. savepos.WriteOneBit( 1 );
  826. client->m_nBaselineUpdateTick = to->tick_count;
  827. }
  828. else
  829. {
  830. savepos.WriteOneBit( 0 );
  831. }
  832. if ( bIsTracing )
  833. {
  834. client->TraceNetworkData( pBuf, "Delta Finish" );
  835. }
  836. }