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.

2241 lines
66 KiB

  1. //========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "prediction.h"
  9. #include "igamemovement.h"
  10. #include "prediction_private.h"
  11. #include "ivrenderview.h"
  12. #include "iinput.h"
  13. #include "usercmd.h"
  14. #include <vgui_controls/Controls.h>
  15. #include <vgui/ISurface.h>
  16. #include <vgui/IScheme.h>
  17. #include "hud.h"
  18. #include "iclientvehicle.h"
  19. #include "in_buttons.h"
  20. #include "con_nprint.h"
  21. #include "hud_pdump.h"
  22. #include "datacache/imdlcache.h"
  23. #ifdef HL2_CLIENT_DLL
  24. #include "c_basehlplayer.h"
  25. #endif
  26. #ifdef PORTAL2
  27. #include "c_portal_player.h"
  28. #endif
  29. #include "tier0/vprof.h"
  30. // memdbgon must be the last include file in a .cpp file!!!
  31. #include "tier0/memdbgon.h"
  32. IPredictionSystem *IPredictionSystem::g_pPredictionSystems = NULL;
  33. #if !defined( NO_ENTITY_PREDICTION )
  34. extern ConVar cl_predictphysics;
  35. ConVar cl_predictweapons ( "cl_predictweapons","1", FCVAR_USERINFO | FCVAR_NOT_CONNECTED, "Perform client side prediction of weapon effects." );
  36. ConVar cl_lagcompensation ( "cl_lagcompensation","1", FCVAR_USERINFO | FCVAR_NOT_CONNECTED, "Perform server side lag compensation of weapon firing events." );
  37. ConVar cl_showerror ( "cl_showerror", "0", FCVAR_RELEASE, "Show prediction errors, 2 for above plus detailed field deltas." );
  38. static ConVar cl_idealpitchscale ( "cl_idealpitchscale", "0.8", FCVAR_ARCHIVE );
  39. static ConVar cl_predictionlist ( "cl_predictionlist", "0", FCVAR_CHEAT, "Show which entities are predicting\n" );
  40. static ConVar cl_predictionentitydump( "cl_pdump", "-1", FCVAR_CHEAT, "Dump info about this entity to screen." );
  41. static ConVar cl_predictionentitydumpbyclass( "cl_pclass", "", FCVAR_CHEAT, "Dump entity by prediction classname." );
  42. static ConVar cl_pred_optimize( "cl_pred_optimize", "2", 0, "Optimize for not copying data if didn't receive a network update (1), and also for not repredicting if there were no errors (2)." );
  43. static ConVar cl_pred_doresetlatch( "cl_pred_doresetlatch", "1", 0 );
  44. //-----------------------------------------------------------------------------
  45. // Purpose:
  46. //-----------------------------------------------------------------------------
  47. void InvalidateEFlagsRecursive( C_BaseEntity *pEnt, int nDirtyFlags, int nChildFlags = 0 )
  48. {
  49. pEnt->AddEFlags( nDirtyFlags );
  50. nDirtyFlags |= nChildFlags;
  51. for (CBaseEntity *pChild = pEnt->FirstMoveChild(); pChild; pChild = pChild->NextMovePeer())
  52. {
  53. InvalidateEFlagsRecursive( pChild, nDirtyFlags );
  54. }
  55. }
  56. #endif
  57. extern IGameMovement *g_pGameMovement;
  58. extern CMoveData *g_pMoveData;
  59. void COM_Log( const char *pszFile, PRINTF_FORMAT_STRING const char *fmt, ...) FMTFUNCTION( 2, 3 ); // Log a debug message to specified file ( if pszFile == NULL uses c:\\hllog.txt )
  60. void PhysicsSimulate( void );
  61. #if defined( PORTAL )
  62. ConVar cl_predicted_movement_uses_uninterpolated_physics( "cl_predicted_movement_uses_uninterpolated_physics", "1" );
  63. extern void MoveUnpredictedPhysicsNearPlayerToNetworkedPosition( CBasePlayer *pPlayer );
  64. #endif
  65. //-----------------------------------------------------------------------------
  66. // Purpose:
  67. //-----------------------------------------------------------------------------
  68. CPrediction::CPrediction( void ) : m_SavedVars( true )
  69. {
  70. #if !defined( NO_ENTITY_PREDICTION )
  71. m_bInPrediction = false;
  72. m_nPreviousStartFrame = -1;
  73. m_nIncomingPacketNumber = 0;
  74. m_bPlayerOriginTypedescriptionSearched = false;
  75. m_bEnginePaused = false;
  76. m_pPDumpPanel = NULL;
  77. m_flLastServerWorldTimeStamp = -1.0f;
  78. #endif
  79. }
  80. CPrediction::~CPrediction( void )
  81. {
  82. }
  83. void CPrediction::Init( void )
  84. {
  85. #if !defined( NO_ENTITY_PREDICTION )
  86. m_bOldCLPredictValue = cl_predict->GetBool();
  87. m_pPDumpPanel = GetPDumpPanel();
  88. #endif
  89. }
  90. void CPrediction::Shutdown( void )
  91. {
  92. }
  93. //-----------------------------------------------------------------------------
  94. // Purpose:
  95. //-----------------------------------------------------------------------------
  96. void CPrediction::CheckError( int nSlot, C_BasePlayer *player, int commands_acknowledged )
  97. {
  98. #if !defined( NO_ENTITY_PREDICTION )
  99. Vector origin;
  100. Vector delta;
  101. float len;
  102. static int pos[ MAX_SPLITSCREEN_PLAYERS ];
  103. // Not in the game yet
  104. if ( !engine->IsInGame() )
  105. return;
  106. // Not running prediction
  107. if ( !cl_predict->GetInt() )
  108. return;
  109. if ( !player )
  110. return;
  111. // Not predictable yet (flush entity packet?)
  112. if ( !player->IsIntermediateDataAllocated() )
  113. return;
  114. origin = player->GetNetworkOrigin();
  115. const void *slot = player->GetPredictedFrame( commands_acknowledged - 1 );
  116. if ( !slot )
  117. return;
  118. if ( !m_bPlayerOriginTypedescriptionSearched )
  119. {
  120. m_bPlayerOriginTypedescriptionSearched = true;
  121. #ifndef PREDICT_ORIGIN_SPLIT
  122. const typedescription_t *td = CPredictionCopy::FindFlatFieldByName( "m_vecNetworkOrigin", player->GetPredDescMap() );
  123. if ( td )
  124. {
  125. m_PlayerOriginTypeDescription.AddToTail( td );
  126. }
  127. #else
  128. const typedescription_t *td = CPredictionCopy::FindFlatFieldByName( "m_vecNetworkOrigin.x", player->GetPredDescMap() );
  129. if ( td )
  130. {
  131. m_PlayerOriginTypeDescription.AddToTail( td );
  132. }
  133. td = CPredictionCopy::FindFlatFieldByName( "m_vecNetworkOrigin.y", player->GetPredDescMap() );
  134. if ( td )
  135. {
  136. m_PlayerOriginTypeDescription.AddToTail( td );
  137. }
  138. td = CPredictionCopy::FindFlatFieldByName( "m_vecNetworkOrigin.z", player->GetPredDescMap() );
  139. if ( td )
  140. {
  141. m_PlayerOriginTypeDescription.AddToTail( td );
  142. }
  143. if( m_PlayerOriginTypeDescription.Count() != 3 )
  144. {
  145. m_PlayerOriginTypeDescription.RemoveAll();
  146. return;
  147. }
  148. #endif
  149. }
  150. if ( !m_PlayerOriginTypeDescription.Count() )
  151. return;
  152. Vector predicted_origin;
  153. // Find the origin field in the database
  154. // Splitting m_vecNetworkOrigin into component fields for prediction *
  155. #ifndef PREDICT_ORIGIN_SPLIT
  156. Q_memcpy( (Vector *)&predicted_origin, (Vector *)( (byte *)slot + m_PlayerOriginTypeDescription[ 0 ]->flatOffset[ TD_OFFSET_PACKED ] ), sizeof( Vector ) );
  157. #else
  158. for ( int i = 0; i < 3; ++i )
  159. {
  160. Q_memcpy( (float *)&predicted_origin[ i ], (float *)( (byte *)slot + m_PlayerOriginTypeDescription[ i ]->flatOffset[ TD_OFFSET_PACKED ] ), sizeof( float ) );
  161. }
  162. #endif
  163. // Compare what the server returned with what we had predicted it to be
  164. VectorSubtract ( predicted_origin, origin, delta );
  165. len = VectorLength( delta );
  166. if (len > MAX_PREDICTION_ERROR )
  167. {
  168. // A teleport or something, clear out error
  169. len = 0;
  170. }
  171. else
  172. {
  173. if ( len > MIN_PREDICTION_EPSILON )
  174. {
  175. player->NotePredictionError( delta );
  176. if ( cl_showerror.GetInt() >= 1 )
  177. {
  178. con_nprint_t np;
  179. np.fixed_width_font = true;
  180. np.color[0] = 1.0f;
  181. np.color[1] = 0.95f;
  182. np.color[2] = 0.7f;
  183. np.index = 4 + nSlot * 10 + ( ++pos[ nSlot ] % 10 );
  184. np.time_to_live = 3.0f;
  185. engine->Con_NXPrintf( &np, "%d len(%6.3f) (%6.3f %6.3f %6.3f)", nSlot, len, delta.x, delta.y, delta.z );
  186. }
  187. }
  188. }
  189. #endif
  190. }
  191. //-----------------------------------------------------------------------------
  192. // Purpose:
  193. //-----------------------------------------------------------------------------
  194. void CPrediction::ShutdownPredictables( void )
  195. {
  196. #if !defined( NO_ENTITY_PREDICTION )
  197. int shutdown_count = 0;
  198. int release_count = 0;
  199. for ( int nSlot = 0; nSlot < MAX_SPLITSCREEN_PLAYERS; ++nSlot )
  200. {
  201. // Transfer intermediate data from other predictables
  202. int c = GetPredictables( nSlot )->GetPredictableCount();
  203. for ( int i = c - 1; i >= 0 ; i-- )
  204. {
  205. C_BaseEntity *ent = GetPredictables( nSlot )->GetPredictable( i );
  206. if ( !ent )
  207. continue;
  208. // Shutdown predictables
  209. if ( ent->GetPredictable() )
  210. {
  211. ent->ShutdownPredictable();
  212. shutdown_count++;
  213. }
  214. // Otherwise, release client created entities
  215. else
  216. {
  217. ent->Release();
  218. release_count++;
  219. }
  220. }
  221. // All gone now...
  222. Assert( GetPredictables( nSlot )->GetPredictableCount() == 0 );
  223. }
  224. if ( ( release_count > 0 ) ||
  225. ( shutdown_count > 0 ) )
  226. {
  227. DevMsg( "Shutdown %i predictable entities and %i client-created entities\n",
  228. shutdown_count,
  229. release_count );
  230. }
  231. #endif
  232. }
  233. //-----------------------------------------------------------------------------
  234. // Purpose:
  235. //-----------------------------------------------------------------------------
  236. void CPrediction::ReinitPredictables( void )
  237. {
  238. #if !defined( NO_ENTITY_PREDICTION )
  239. // Go through all entities and init any eligible ones
  240. int i;
  241. int c = ClientEntityList().GetHighestEntityIndex();
  242. for ( i = 0; i <= c; i++ )
  243. {
  244. C_BaseEntity *e = ClientEntityList().GetBaseEntity( i );
  245. if ( !e )
  246. continue;
  247. if ( e->GetPredictable() )
  248. continue;
  249. e->CheckInitPredictable( "ReinitPredictables" );
  250. }
  251. FOR_EACH_VALID_SPLITSCREEN_PLAYER( nSlot )
  252. {
  253. Msg( "%d: Reinitialized %i predictable entities\n",
  254. nSlot, GetPredictables( nSlot )->GetPredictableCount() );
  255. }
  256. #endif
  257. }
  258. //-----------------------------------------------------------------------------
  259. // Purpose:
  260. //-----------------------------------------------------------------------------
  261. void CPrediction::OnReceivedUncompressedPacket( void )
  262. {
  263. #if !defined( NO_ENTITY_PREDICTION )
  264. m_nPreviousStartFrame = -1;
  265. for ( int i = 0 ; i < MAX_SPLITSCREEN_PLAYERS; ++i )
  266. {
  267. Split_t &split = m_Split[ i ];
  268. split.m_nCommandsPredicted = 0;
  269. split.m_nServerCommandsAcknowledged = 0;
  270. split.m_nLastCommandAcknowledged = 0;
  271. }
  272. #endif
  273. }
  274. //-----------------------------------------------------------------------------
  275. // Purpose:
  276. // Input : commands_acknowledged -
  277. // current_world_update_packet -
  278. // Output : void CPrediction::PreEntityPacketReceived
  279. //-----------------------------------------------------------------------------
  280. void CPrediction::PreEntityPacketReceived ( int commands_acknowledged, int current_world_update_packet, int server_ticks_elapsed )
  281. {
  282. #if !defined( NO_ENTITY_PREDICTION )
  283. #if defined( _DEBUG )
  284. char sz[ 32 ];
  285. Q_snprintf( sz, sizeof( sz ), "preentitypacket%d", commands_acknowledged );
  286. PREDICTION_TRACKVALUECHANGESCOPE( sz );
  287. #endif
  288. VPROF( "CPrediction::PreEntityPacketReceived" );
  289. // Cache off incoming packet #
  290. m_nIncomingPacketNumber = current_world_update_packet;
  291. C_BaseEntity::s_nIncomingPacketCommandsAcknowledged = commands_acknowledged;
  292. // Don't screw up memory of current player from history buffers if not filling in history buffers
  293. // during prediction!!!
  294. if ( !cl_predict->GetInt() )
  295. {
  296. ShutdownPredictables();
  297. return;
  298. }
  299. FOR_EACH_VALID_SPLITSCREEN_PLAYER( nSlot )
  300. {
  301. C_BasePlayer *current = C_BasePlayer::GetLocalPlayer( nSlot );
  302. // No local player object?
  303. if ( !current )
  304. continue;
  305. // Transfer intermediate data from other predictables
  306. int c = GetPredictables( nSlot )->GetPredictableCount();
  307. int i;
  308. for ( i = 0; i < c; i++ )
  309. {
  310. C_BaseEntity *ent = GetPredictables( nSlot )->GetPredictable( i );
  311. if ( !ent )
  312. continue;
  313. if ( !ent->GetPredictable() )
  314. continue;
  315. if ( (commands_acknowledged != server_ticks_elapsed) && ent->PredictionIsPhysicallySimulated() )
  316. {
  317. ent->ShiftIntermediateData_TickAdjust( server_ticks_elapsed - commands_acknowledged, m_Split[nSlot].m_nCommandsPredicted );
  318. m_Split[nSlot].m_bPerformedTickShift = true;
  319. }
  320. ent->PreEntityPacketReceived( commands_acknowledged );
  321. ent->OnPostRestoreData();
  322. }
  323. }
  324. #endif
  325. }
  326. //-----------------------------------------------------------------------------
  327. // Purpose: Called for every packet received( could be multiple times per frame)
  328. //-----------------------------------------------------------------------------
  329. void CPrediction::PostEntityPacketReceived( void )
  330. {
  331. #if !defined( NO_ENTITY_PREDICTION )
  332. PREDICTION_TRACKVALUECHANGESCOPE( "postentitypacket" );
  333. VPROF( "CPrediction::PostEntityPacketReceived" );
  334. C_BaseEntity::s_nIncomingPacketCommandsAcknowledged = -1;
  335. // Don't screw up memory of current player from history buffers if not filling in history buffers
  336. // during prediction!!!
  337. if ( !cl_predict->GetInt() )
  338. return;
  339. FOR_EACH_VALID_SPLITSCREEN_PLAYER( nSlot )
  340. {
  341. C_BasePlayer *current = C_BasePlayer::GetLocalPlayer( nSlot );
  342. // No local player object?
  343. if ( !current )
  344. continue;
  345. int c = GetPredictables( nSlot )->GetPredictableCount();
  346. // Transfer intermediate data from other predictables
  347. int i;
  348. for ( i = 0; i < c; i++ )
  349. {
  350. C_BaseEntity *ent = GetPredictables( nSlot )->GetPredictable( i );
  351. if ( !ent )
  352. continue;
  353. if ( !ent->GetPredictable() )
  354. continue;
  355. // Always mark as changed
  356. if ( AddDataChangeEvent( ent, DATA_UPDATE_DATATABLE_CHANGED, &ent->m_DataChangeEventRef ) )
  357. {
  358. ent->OnPreDataChanged( DATA_UPDATE_DATATABLE_CHANGED );
  359. }
  360. ent->PostEntityPacketReceived();
  361. }
  362. }
  363. #endif
  364. }
  365. //-----------------------------------------------------------------------------
  366. // Purpose:
  367. // Input : *ent -
  368. // Output : static bool
  369. //-----------------------------------------------------------------------------
  370. bool CPrediction::ShouldDumpEntity( C_BaseEntity *ent )
  371. {
  372. #if !defined( NO_ENTITY_PREDICTION )
  373. int dump_entity = cl_predictionentitydump.GetInt();
  374. if ( dump_entity != -1 )
  375. {
  376. bool dump = false;
  377. if ( ent->entindex() == -1 )
  378. {
  379. dump = ( dump_entity == ent->entindex() ) ? true : false;
  380. }
  381. else
  382. {
  383. dump = ( ent->entindex() == dump_entity ) ? true : false;
  384. }
  385. if ( !dump )
  386. {
  387. return false;
  388. }
  389. }
  390. else
  391. {
  392. if ( cl_predictionentitydumpbyclass.GetString()[ 0 ] == 0 )
  393. return false;
  394. if ( !FClassnameIs( ent, cl_predictionentitydumpbyclass.GetString() ) )
  395. return false;
  396. }
  397. return true;
  398. #else
  399. return false;
  400. #endif
  401. }
  402. void CPrediction::ShowPredictionListEntry( int listRow, int showlist, C_BaseEntity *ent, int &totalsize, int &totalsize_intermediate )
  403. {
  404. char sz[ 32 ];
  405. if ( ent->entindex() == -1 )
  406. {
  407. Q_snprintf( sz, sizeof( sz ), "handle %u", (unsigned int)ent->GetClientHandle().ToInt() );
  408. }
  409. else
  410. {
  411. Q_snprintf( sz, sizeof( sz ), "%i", ent->entindex() );
  412. }
  413. int oIndex = 0;
  414. if ( ent->GetOwnerEntity() )
  415. {
  416. oIndex = ent->GetOwnerEntity()->entindex();
  417. }
  418. else if ( ent->IsPlayer() )
  419. {
  420. oIndex = ent->entindex();
  421. }
  422. else
  423. {
  424. C_BaseViewModel *pVM = ToBaseViewModel( ent );
  425. if ( pVM && pVM->GetOwner() )
  426. {
  427. oIndex = pVM->GetOwner()->entindex();
  428. }
  429. }
  430. con_nprint_t np;
  431. np.fixed_width_font = true;
  432. np.color[0] = 0.8f;
  433. np.color[1] = 1.0f;
  434. np.color[2] = 1.0f;
  435. np.time_to_live = 2.0f;
  436. np.index = listRow;
  437. if ( showlist >= 2 )
  438. {
  439. int size = GetClassMap().GetClassSize( ent->GetClassname() );
  440. int intermediate_size = ent->GetIntermediateDataSize() * ( MULTIPLAYER_BACKUP + 1 );
  441. engine->Con_NXPrintf( &np, "%15s %30s(%d) (%5i / %5i bytes): %15s",
  442. sz,
  443. ent->GetClassname(),
  444. oIndex,
  445. size,
  446. intermediate_size,
  447. ent->GetPredictable() ? "predicted" : "client created" );
  448. totalsize += size;
  449. totalsize_intermediate += intermediate_size;
  450. }
  451. else
  452. {
  453. engine->Con_NXPrintf( &np, "%15s %30s(%d): %15s",
  454. sz,
  455. ent->GetClassname(),
  456. oIndex,
  457. ent->GetPredictable() ? "predicted" : "client created" );
  458. }
  459. }
  460. void CPrediction::FinishPredictionList( int listRow, int showlist, int totalsize, int totalsize_intermediate )
  461. {
  462. if ( !showlist )
  463. return;
  464. if ( showlist > 1 )
  465. {
  466. con_nprint_t np;
  467. np.fixed_width_font = true;
  468. np.color[0] = 0.8f;
  469. np.color[1] = 1.0f;
  470. np.color[2] = 1.0f;
  471. np.time_to_live = 2.0f;
  472. np.index = listRow++;
  473. char sz1[32];
  474. char sz2[32];
  475. Q_strncpy( sz1, Q_pretifymem( (float)totalsize ), sizeof( sz1 ) );
  476. Q_strncpy( sz2, Q_pretifymem( (float)totalsize_intermediate ), sizeof( sz2 ) );
  477. engine->Con_NXPrintf( &np, "%15s %27s (%s / %s) %14s",
  478. "totals:",
  479. "",
  480. sz1,
  481. sz2,
  482. "" );
  483. }
  484. // Zero out rest of list
  485. while ( listRow < 20 )
  486. {
  487. engine->Con_NPrintf( listRow++, "" );
  488. }
  489. }
  490. void CPrediction::CheckPredictConvar()
  491. {
  492. if ( cl_predict->GetBool() != m_bOldCLPredictValue )
  493. {
  494. if ( !m_bOldCLPredictValue )
  495. {
  496. ReinitPredictables();
  497. }
  498. for ( int i = 0 ; i < MAX_SPLITSCREEN_PLAYERS; ++i )
  499. {
  500. Split_t &split = m_Split[ i ];
  501. split.m_nCommandsPredicted = 0;
  502. split.m_nServerCommandsAcknowledged = 0;
  503. split.m_nLastCommandAcknowledged = 0;
  504. }
  505. m_nPreviousStartFrame = -1;
  506. }
  507. m_bOldCLPredictValue = cl_predict->GetBool();
  508. }
  509. ConVar cl_prediction_error_timestamps( "cl_prediction_error_timestamps", "0" );
  510. //-----------------------------------------------------------------------------
  511. // Purpose: Called at the end of the frame if any packets were received
  512. // Input : error_check -
  513. // last_predicted -
  514. //-----------------------------------------------------------------------------
  515. void CPrediction::PostNetworkDataReceived( int commands_acknowledged )
  516. {
  517. #if !defined( NO_ENTITY_PREDICTION )
  518. VPROF( "CPrediction::PostNetworkDataReceived" );
  519. bool error_check = ( commands_acknowledged > 0 ) ? true : false;
  520. #if defined( _DEBUG )
  521. char sz[ 32 ];
  522. Q_snprintf( sz, sizeof( sz ), "postnetworkdata%d", commands_acknowledged );
  523. PREDICTION_TRACKVALUECHANGESCOPE( sz );
  524. #endif
  525. //Msg( "%i/%i ack %i commands/slot\n",
  526. // gpGlobals->framecount,
  527. // gpGlobals->tickcount,
  528. // commands_acknowledged - 1 );
  529. bool entityDumped = false;
  530. bool bPredict = cl_predict->GetBool();
  531. int showlist = cl_predictionlist.GetInt();
  532. int listRow = 0;
  533. FOR_EACH_VALID_SPLITSCREEN_PLAYER( nSlot )
  534. {
  535. Split_t &split = m_Split[ nSlot ];
  536. split.m_nServerCommandsAcknowledged += commands_acknowledged;
  537. split.m_bPreviousAckHadErrors = false;
  538. split.m_bPreviousAckErrorTriggersFullLatchReset = false;
  539. split.m_EntsWithPredictionErrorsInLastAck.RemoveAll();
  540. if ( bPredict )
  541. {
  542. // Don't screw up memory of current player from history buffers if not filling in history buffers during prediction!!!
  543. int totalsize = 0;
  544. int totalsize_intermediate = 0;
  545. // Build list of all predictables
  546. int c = GetPredictables( nSlot )->GetPredictableCount();
  547. bool *bHadErrors = (bool *)stackalloc( sizeof( bool ) * c );
  548. // Transfer intermediate data from other predictables
  549. int i;
  550. for ( i = 0; i < c; i++ )
  551. {
  552. C_BaseEntity *ent = GetPredictables( nSlot )->GetPredictable( i );
  553. if ( !ent )
  554. continue;
  555. if ( !ent->GetPredictable() )
  556. continue;
  557. bHadErrors[i] = ent->PostNetworkDataReceived( split.m_nServerCommandsAcknowledged );
  558. if ( bHadErrors[i] )
  559. {
  560. split.m_bPreviousAckHadErrors = true;
  561. split.m_bPreviousAckErrorTriggersFullLatchReset |= ent->PredictionErrorShouldResetLatchedForAllPredictables();
  562. split.m_EntsWithPredictionErrorsInLastAck.AddToTail( ent );
  563. }
  564. if ( !showlist )
  565. {
  566. if ( error_check &&
  567. !entityDumped &&
  568. m_pPDumpPanel &&
  569. ShouldDumpEntity( ent ) )
  570. {
  571. entityDumped = true;
  572. m_pPDumpPanel->DumpEntity( ent, split.m_nServerCommandsAcknowledged );
  573. }
  574. continue;
  575. }
  576. ShowPredictionListEntry( listRow, showlist, ent, totalsize, totalsize_intermediate );
  577. listRow++;
  578. }
  579. //Give entities with predicted fields that are not networked a chance to fix their current values for those fields.
  580. //We do this in two passes. One pass to fix the fields, then another to save off the changes after they've all finished (to handle interdependancies, portals)
  581. if( split.m_bPreviousAckHadErrors )
  582. {
  583. //give each predicted entity a chance to fix up its non-networked predicted fields
  584. for ( i = 0; i < c; i++ )
  585. {
  586. C_BaseEntity *ent = GetPredictables( nSlot )->GetPredictable( i );
  587. if ( !ent )
  588. continue;
  589. if ( !ent->GetPredictable() )
  590. continue;
  591. ent->HandlePredictionError( bHadErrors[i] );
  592. }
  593. //save off any changes
  594. for ( i = 0; i < c; i++ )
  595. {
  596. C_BaseEntity *ent = GetPredictables( nSlot )->GetPredictable( i );
  597. if ( !ent )
  598. continue;
  599. if ( !ent->GetPredictable() )
  600. continue;
  601. ent->SaveData( "PostNetworkDataReceived() Ack Errors", C_BaseEntity::SLOT_ORIGINALDATA, PC_EVERYTHING );
  602. }
  603. }
  604. for ( i = c; --i >= 0; ) //go backwards to maintain ordering on shutdown
  605. {
  606. C_BaseEntity *ent = GetPredictables( nSlot )->GetPredictable( i );
  607. if ( !ent )
  608. continue;
  609. if ( !ent->GetPredictable() )
  610. continue;
  611. ent->CheckShutdownPredictable( "CPrediction::PostNetworkDataReceived" );
  612. }
  613. FinishPredictionList( listRow, showlist, totalsize, totalsize_intermediate );
  614. if ( error_check )
  615. {
  616. C_BasePlayer *current = C_BasePlayer::GetLocalPlayer( nSlot );
  617. if ( !current )
  618. continue;
  619. CheckError( nSlot, current, split.m_nServerCommandsAcknowledged );
  620. }
  621. }
  622. // Can also look at regular entities
  623. int dumpentindex = cl_predictionentitydump.GetInt();
  624. if ( m_pPDumpPanel && error_check && !entityDumped && dumpentindex != -1 )
  625. {
  626. int last_entity = ClientEntityList().GetHighestEntityIndex();
  627. if ( dumpentindex >= 0 && dumpentindex <= last_entity )
  628. {
  629. C_BaseEntity *ent = ClientEntityList().GetBaseEntity( dumpentindex );
  630. if ( ent )
  631. {
  632. m_pPDumpPanel->DumpEntity( ent, split.m_nServerCommandsAcknowledged );
  633. entityDumped = true;
  634. }
  635. }
  636. }
  637. if( split.m_bPreviousAckHadErrors && cl_prediction_error_timestamps.GetBool() )
  638. {
  639. Warning( "Prediction errors occurred at %i %f\n", gpGlobals->tickcount, gpGlobals->curtime );
  640. }
  641. }
  642. CheckPredictConvar();
  643. if ( m_pPDumpPanel && error_check && !entityDumped )
  644. {
  645. m_pPDumpPanel->Clear();
  646. }
  647. #endif
  648. }
  649. //-----------------------------------------------------------------------------
  650. // Purpose: Prepare for running prediction code
  651. // Input : *ucmd -
  652. // *from -
  653. // *pHelper -
  654. // &moveInput -
  655. //-----------------------------------------------------------------------------
  656. void CPrediction::SetupMove( C_BasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move )
  657. {
  658. #if !defined( NO_ENTITY_PREDICTION )
  659. VPROF( "CPrediction::SetupMove" );
  660. move->m_bFirstRunOfFunctions = IsFirstTimePredicted();
  661. move->m_bGameCodeMovedPlayer = false;
  662. if ( player->GetPreviouslyPredictedOrigin() != player->GetNetworkOrigin() )
  663. {
  664. move->m_bGameCodeMovedPlayer = true;
  665. }
  666. move->m_nPlayerHandle = player->GetClientHandle();
  667. move->m_vecVelocity = player->GetAbsVelocity();
  668. move->SetAbsOrigin( player->GetNetworkOrigin() );
  669. move->m_vecOldAngles = move->m_vecAngles;
  670. move->m_nOldButtons = player->m_Local.m_nOldButtons;
  671. move->m_flClientMaxSpeed = player->m_flMaxspeed;
  672. move->m_vecAngles = ucmd->viewangles;
  673. move->m_vecViewAngles = ucmd->viewangles;
  674. move->m_nImpulseCommand = ucmd->impulse;
  675. move->m_nButtons = ucmd->buttons;
  676. CBaseEntity *pMoveParent = player->GetMoveParent();
  677. if (!pMoveParent)
  678. {
  679. move->m_vecAbsViewAngles = move->m_vecViewAngles;
  680. }
  681. else
  682. {
  683. matrix3x4_t viewToParent, viewToWorld;
  684. AngleMatrix( move->m_vecViewAngles, viewToParent );
  685. ConcatTransforms( pMoveParent->EntityToWorldTransform(), viewToParent, viewToWorld );
  686. MatrixAngles( viewToWorld, move->m_vecAbsViewAngles );
  687. }
  688. // Ingore buttons for movement if at controls
  689. if (player->GetFlags() & FL_ATCONTROLS)
  690. {
  691. move->m_flForwardMove = 0;
  692. move->m_flSideMove = 0;
  693. move->m_flUpMove = 0;
  694. }
  695. else
  696. {
  697. move->m_flForwardMove = ucmd->forwardmove;
  698. move->m_flSideMove = ucmd->sidemove;
  699. move->m_flUpMove = ucmd->upmove;
  700. }
  701. IClientVehicle *pVehicle = player->GetVehicle();
  702. if (pVehicle)
  703. {
  704. pVehicle->SetupMove( player, ucmd, pHelper, move );
  705. }
  706. // Copy constraint information
  707. if ( player->m_hConstraintEntity )
  708. move->m_vecConstraintCenter = player->m_hConstraintEntity->GetAbsOrigin();
  709. else
  710. move->m_vecConstraintCenter = player->m_vecConstraintCenter;
  711. move->m_flConstraintRadius = player->m_flConstraintRadius;
  712. move->m_flConstraintWidth = player->m_flConstraintWidth;
  713. move->m_flConstraintSpeedFactor = player->m_flConstraintSpeedFactor;
  714. #ifdef HL2_CLIENT_DLL
  715. // Convert to HL2 data.
  716. C_BaseHLPlayer *pHLPlayer = static_cast<C_BaseHLPlayer*>( player );
  717. Assert( pHLPlayer );
  718. CHLMoveData *pHLMove = static_cast<CHLMoveData*>( move );
  719. Assert( pHLMove );
  720. pHLMove->m_bIsSprinting = pHLPlayer->IsSprinting();
  721. #endif
  722. g_pGameMovement->SetupMovementBounds( move );
  723. #endif
  724. }
  725. //-----------------------------------------------------------------------------
  726. // Purpose: Finish running prediction code
  727. // Input : &move -
  728. // *to -
  729. //-----------------------------------------------------------------------------
  730. void CPrediction::FinishMove( C_BasePlayer *player, CUserCmd *ucmd, CMoveData *move )
  731. {
  732. #if !defined( NO_ENTITY_PREDICTION )
  733. VPROF( "CPrediction::FinishMove" );
  734. player->m_RefEHandle = move->m_nPlayerHandle;
  735. player->SetAbsVelocity( move->m_vecVelocity );
  736. player->m_vecNetworkOrigin = move->GetAbsOrigin();
  737. player->SetPreviouslyPredictedOrigin( move->GetAbsOrigin() );
  738. player->m_Local.m_nOldButtons = move->m_nButtons;
  739. player->m_flMaxspeed = move->m_flClientMaxSpeed;
  740. m_hLastGround = player->GetGroundEntity();
  741. player->SetLocalOrigin( move->GetAbsOrigin() );
  742. IClientVehicle *pVehicle = player->GetVehicle();
  743. if (pVehicle)
  744. {
  745. pVehicle->FinishMove( player, ucmd, move );
  746. }
  747. // Sanity checks
  748. if ( player->m_hConstraintEntity )
  749. Assert( move->m_vecConstraintCenter == player->m_hConstraintEntity->GetAbsOrigin() );
  750. else
  751. Assert( move->m_vecConstraintCenter == player->m_vecConstraintCenter );
  752. Assert( move->m_flConstraintRadius == player->m_flConstraintRadius );
  753. Assert( move->m_flConstraintWidth == player->m_flConstraintWidth );
  754. Assert( move->m_flConstraintSpeedFactor == player->m_flConstraintSpeedFactor );
  755. #endif
  756. }
  757. //-----------------------------------------------------------------------------
  758. // Purpose: Called before any movement processing
  759. // Input : *player -
  760. // *cmd -
  761. //-----------------------------------------------------------------------------
  762. void CPrediction::StartCommand( C_BasePlayer *player, CUserCmd *cmd )
  763. {
  764. #if !defined( NO_ENTITY_PREDICTION )
  765. VPROF( "CPrediction::StartCommand" );
  766. #if defined( USE_PREDICTABLEID )
  767. CPredictableId::ResetInstanceCounters();
  768. #endif
  769. player->m_pCurrentCommand = cmd;
  770. player->m_LastCmd = *cmd;
  771. C_BaseEntity::SetPredictionRandomSeed( cmd );
  772. C_BaseEntity::SetPredictionPlayer( player );
  773. #endif
  774. }
  775. //-----------------------------------------------------------------------------
  776. // Purpose: Called after any movement processing
  777. // Input : *player -
  778. //-----------------------------------------------------------------------------
  779. void CPrediction::FinishCommand( C_BasePlayer *player )
  780. {
  781. #if !defined( NO_ENTITY_PREDICTION )
  782. VPROF( "CPrediction::FinishCommand" );
  783. player->m_pCurrentCommand = NULL;
  784. C_BaseEntity::SetPredictionRandomSeed( NULL );
  785. C_BaseEntity::SetPredictionPlayer( NULL );
  786. #endif
  787. }
  788. //-----------------------------------------------------------------------------
  789. // Purpose: Called before player thinks
  790. // Input : *player -
  791. // thinktime -
  792. //-----------------------------------------------------------------------------
  793. void CPrediction::RunPreThink( C_BasePlayer *player )
  794. {
  795. #if !defined( NO_ENTITY_PREDICTION )
  796. VPROF( "CPrediction::RunPreThink" );
  797. // Run think functions on the player
  798. if ( !player->PhysicsRunThink() )
  799. return;
  800. // Called every frame to let game rules do any specific think logic for the player
  801. // FIXME: Do we need to set up a client side version of the gamerules???
  802. // g_pGameRules->PlayerThink( player );
  803. player->PreThink();
  804. #endif
  805. }
  806. //-----------------------------------------------------------------------------
  807. // Purpose: Runs the PLAYER's thinking code if time. There is some play in the exact time the think
  808. // function will be called, because it is called before any movement is done
  809. // in a frame. Not used for pushmove objects, because they must be exact.
  810. // Returns false if the entity removed itself.
  811. // Input : *ent -
  812. // frametime -
  813. // clienttimebase -
  814. // Output : void CPlayerMove::RunThink
  815. //-----------------------------------------------------------------------------
  816. void CPrediction::RunThink (C_BasePlayer *player, double frametime )
  817. {
  818. #if !defined( NO_ENTITY_PREDICTION )
  819. VPROF( "CPrediction::RunThink" );
  820. int thinktick = player->GetNextThinkTick();
  821. if ( thinktick <= 0 || thinktick > player->m_nTickBase )
  822. return;
  823. player->SetNextThink( TICK_NEVER_THINK );
  824. // Think
  825. player->Think();
  826. #endif
  827. }
  828. //-----------------------------------------------------------------------------
  829. // Purpose: Called after player movement
  830. // Input : *player -
  831. // thinktime -
  832. // frametime -
  833. //-----------------------------------------------------------------------------
  834. void CPrediction::RunPostThink( C_BasePlayer *player )
  835. {
  836. #if !defined( NO_ENTITY_PREDICTION )
  837. VPROF( "CPrediction::RunPostThink" );
  838. // Run post-think
  839. player->PostThink();
  840. #endif
  841. }
  842. //-----------------------------------------------------------------------------
  843. // Purpose: Checks if the player is standing on a moving entity and adjusts velocity and
  844. // basevelocity appropriately
  845. // Input : *player -
  846. // frametime -
  847. //-----------------------------------------------------------------------------
  848. void CPrediction::CheckMovingGround( C_BasePlayer *player, double frametime )
  849. {
  850. CBaseEntity *groundentity;
  851. if ( player->GetFlags() & FL_ONGROUND )
  852. {
  853. groundentity = player->GetGroundEntity();
  854. if ( groundentity && ( groundentity->GetFlags() & FL_CONVEYOR) )
  855. {
  856. Vector vecNewVelocity;
  857. groundentity->GetGroundVelocityToApply( vecNewVelocity );
  858. if ( player->GetFlags() & FL_BASEVELOCITY )
  859. {
  860. vecNewVelocity += player->GetBaseVelocity();
  861. }
  862. player->SetBaseVelocity( vecNewVelocity );
  863. player->AddFlag( FL_BASEVELOCITY );
  864. }
  865. }
  866. if ( !( player->GetFlags() & FL_BASEVELOCITY ) )
  867. {
  868. // Apply momentum (add in half of the previous frame of velocity first)
  869. player->ApplyAbsVelocityImpulse( (1.0 + ( frametime * 0.5 )) * player->GetBaseVelocity() );
  870. player->SetBaseVelocity( vec3_origin );
  871. }
  872. player->RemoveFlag( FL_BASEVELOCITY );
  873. }
  874. //-----------------------------------------------------------------------------
  875. // Purpose: Predicts a single movement command for player
  876. // Input : *moveHelper -
  877. // *player -
  878. // *u -
  879. //-----------------------------------------------------------------------------
  880. void CPrediction::RunCommand( C_BasePlayer *player, CUserCmd *ucmd, IMoveHelper *moveHelper )
  881. {
  882. #if !defined( NO_ENTITY_PREDICTION )
  883. VPROF( "CPrediction::RunCommand" );
  884. #if defined( _DEBUG )
  885. char sz[ 32 ];
  886. Q_snprintf( sz, sizeof( sz ), "runcommand%04d", ucmd->command_number );
  887. PREDICTION_TRACKVALUECHANGESCOPE( sz );
  888. #endif
  889. #ifdef PORTAL2
  890. assert_cast<CPortal_Player*>( player )->PreventCrouchJump( ucmd );
  891. #endif
  892. StartCommand( player, ucmd );
  893. // Set globals appropriately
  894. gpGlobals->curtime = player->m_nTickBase * TICK_INTERVAL;
  895. gpGlobals->frametime = m_bEnginePaused ? 0 : TICK_INTERVAL;
  896. // Add and subtract buttons we're forcing on the player
  897. ucmd->buttons |= player->m_afButtonForced;
  898. // ucmd->buttons &= ~player->m_afButtonDisabled; // MAY WANT TO DO THIS LATER!!!
  899. g_pGameMovement->StartTrackPredictionErrors( player );
  900. // TODO
  901. // TODO: Check for impulse predicted?
  902. // Do weapon selection
  903. if ( ucmd->weaponselect != 0 )
  904. {
  905. C_BaseCombatWeapon *weapon = ToBaseCombatWeapon( CBaseEntity::Instance( ucmd->weaponselect ) );
  906. if ( weapon )
  907. {
  908. player->SelectItem( weapon->GetName(), ucmd->weaponsubtype );
  909. }
  910. }
  911. // Latch in impulse.
  912. IClientVehicle *pVehicle = player->GetVehicle();
  913. if ( ucmd->impulse )
  914. {
  915. // Discard impulse commands unless the vehicle allows them.
  916. // FIXME: UsingStandardWeapons seems like a bad filter for this.
  917. // The flashlight is an impulse command, for example.
  918. if ( !pVehicle || player->UsingStandardWeaponsInVehicle() )
  919. {
  920. player->m_nImpulse = ucmd->impulse;
  921. }
  922. }
  923. // Get button states
  924. player->UpdateButtonState( ucmd->buttons );
  925. // TODO
  926. CheckMovingGround( player, gpGlobals->frametime );
  927. // TODO
  928. // g_pMoveData->m_vecOldAngles = player->pl.v_angle;
  929. // Copy from command to player unless game .dll has set angle using fixangle
  930. // if ( !player->pl.fixangle )
  931. {
  932. player->SetLocalViewAngles( ucmd->viewangles );
  933. }
  934. // Call standard client pre-think
  935. RunPreThink( player );
  936. // Call Think if one is set
  937. RunThink( player, TICK_INTERVAL );
  938. // Setup input.
  939. {
  940. SetupMove( player, ucmd, moveHelper, g_pMoveData );
  941. }
  942. {
  943. VPROF_BUDGET( "CPrediction::ProcessMovement", "CPrediction::ProcessMovement" );
  944. // RUN MOVEMENT
  945. if ( !pVehicle )
  946. {
  947. Assert( g_pGameMovement );
  948. g_pGameMovement->ProcessMovement( player, g_pMoveData );
  949. }
  950. else
  951. {
  952. pVehicle->ProcessMovement( player, g_pMoveData );
  953. }
  954. }
  955. FinishMove( player, ucmd, g_pMoveData );
  956. // Let server invoke any needed impact functions
  957. VPROF_SCOPE_BEGIN( "moveHelper->ProcessImpacts(cl)" );
  958. moveHelper->ProcessImpacts();
  959. VPROF_SCOPE_END();
  960. RunPostThink( player );
  961. g_pGameMovement->FinishTrackPredictionErrors( player );
  962. FinishCommand( player );
  963. g_pGameMovement->Reset(); // fixes a crash: when loading highlights twice or after previously loaded map, there was a dirty player pointer in game movement
  964. if( !m_bEnginePaused && gpGlobals->frametime > 0 )
  965. {
  966. player->m_nTickBase++;
  967. }
  968. #endif
  969. }
  970. //-----------------------------------------------------------------------------
  971. // Purpose: In the forward direction, creates rays straight down and determines the
  972. // height of the 'floor' hit for each forward test. Then, if the samples show that the
  973. // player is about to enter an up/down slope, sets *idealpitch to look up or down that slope
  974. // as appropriate
  975. //-----------------------------------------------------------------------------
  976. void CPrediction::SetIdealPitch ( int nSlot, C_BasePlayer *player, const Vector& origin, const QAngle& angles, const Vector& viewheight )
  977. {
  978. #if !defined( NO_ENTITY_PREDICTION )
  979. Vector forward;
  980. Vector top, bottom;
  981. float floor_height[MAX_FORWARD];
  982. int i, j;
  983. int step, dir, steps;
  984. trace_t tr;
  985. if ( player->GetGroundEntity() == NULL )
  986. return;
  987. // Don't do this on the 360..
  988. if ( IsGameConsole() )
  989. return;
  990. AngleVectors( angles, &forward );
  991. forward[2] = 0;
  992. MDLCACHE_CRITICAL_SECTION();
  993. // Now move forward by 36, 48, 60, etc. units from the eye position and drop lines straight down
  994. // 160 or so units to see what's below
  995. for (i=0 ; i<MAX_FORWARD ; i++)
  996. {
  997. VectorMA( origin, (i+3)*12, forward, top );
  998. top[2] += viewheight[ 2 ];
  999. VectorCopy( top, bottom );
  1000. bottom[2] -= 160;
  1001. UTIL_TraceLine( top, bottom, MASK_SOLID, NULL, COLLISION_GROUP_PLAYER_MOVEMENT, &tr );
  1002. // looking at a wall, leave ideal the way it was
  1003. if ( tr.allsolid )
  1004. return;
  1005. // near a dropoff/ledge
  1006. if ( tr.fraction == 1 )
  1007. return;
  1008. floor_height[i] = top[2] + tr.fraction*( bottom[2] - top[2] );
  1009. }
  1010. dir = 0;
  1011. steps = 0;
  1012. for (j=1 ; j<i ; j++)
  1013. {
  1014. step = floor_height[j] - floor_height[j-1];
  1015. if (step > -ON_EPSILON && step < ON_EPSILON)
  1016. continue;
  1017. if (dir && ( step-dir > ON_EPSILON || step-dir < -ON_EPSILON ) )
  1018. return; // mixed changes
  1019. steps++;
  1020. dir = step;
  1021. }
  1022. Split_t &split = m_Split[ nSlot ];
  1023. if (!dir)
  1024. {
  1025. split.m_flIdealPitch = 0;
  1026. return;
  1027. }
  1028. if (steps < 2)
  1029. return;
  1030. split.m_flIdealPitch = -dir * cl_idealpitchscale.GetFloat();
  1031. #endif
  1032. }
  1033. //-----------------------------------------------------------------------------
  1034. // Purpose: Walk backward through predictables looking for ClientCreated entities
  1035. // such as projectiles which were
  1036. // 1) not actually ack'd by the server or
  1037. // 2) were ack'd and made dormant and can now safely be removed
  1038. // Input : last_command_packet -
  1039. //-----------------------------------------------------------------------------
  1040. void CPrediction::RemoveStalePredictedEntities( int nSlot, int sequence_number )
  1041. {
  1042. #if !defined( NO_ENTITY_PREDICTION ) && defined( USE_PREDICTABLEID )
  1043. VPROF( "CPrediction::RemoveStalePredictedEntities" );
  1044. int oldest_allowable_command = sequence_number;
  1045. // Walk backward due to deletion from UtlVector
  1046. int c = GetPredictables( nSlot )->GetPredictableCount();
  1047. int i;
  1048. for ( i = c - 1; i >= 0; i-- )
  1049. {
  1050. C_BaseEntity *ent = GetPredictables( nSlot )->GetPredictable( i );
  1051. if ( !ent )
  1052. continue;
  1053. // Don't do anything to truly predicted things (like player and weapons )
  1054. if ( ent->GetPredictable() )
  1055. continue;
  1056. // What's left should be things like projectiles that are just waiting to be "linked"
  1057. // to their server counterpart and deleted
  1058. Assert( ent->IsClientCreated() );
  1059. if ( !ent->IsClientCreated() )
  1060. continue;
  1061. // Snag the PredictionContext
  1062. PredictionContext *ctx = ent->m_pPredictionContext;
  1063. if ( !ctx )
  1064. {
  1065. continue;
  1066. }
  1067. // If it was ack'd then the server sent us the entity.
  1068. // Leave it unless it wasn't made dormant this frame, in
  1069. // which case it can be removed now
  1070. if ( ent->m_PredictableID.GetAcknowledged() )
  1071. {
  1072. // Hasn't become dormant yet!!!
  1073. if ( !ent->IsDormantPredictable() )
  1074. {
  1075. Assert( 0 );
  1076. continue;
  1077. }
  1078. // Still gets to live till next frame
  1079. if ( ent->BecameDormantThisPacket() )
  1080. continue;
  1081. C_BaseEntity *serverEntity = ctx->m_hServerEntity;
  1082. if ( serverEntity )
  1083. {
  1084. // Notify that it's going to go away
  1085. serverEntity->OnPredictedEntityRemove( true, ent );
  1086. }
  1087. }
  1088. else
  1089. {
  1090. // Check context to see if it's too old?
  1091. int command_entity_creation_happened = ctx->m_nCreationCommandNumber;
  1092. // Give it more time to live...not time to kill it yet
  1093. if ( command_entity_creation_happened > oldest_allowable_command )
  1094. continue;
  1095. // If the client predicted the KILLME flag it's possible
  1096. // that entity had such a short life that it actually
  1097. // never was sent to us. In that case, just let it die a silent death
  1098. if ( !ent->IsEFlagSet( EFL_KILLME ) )
  1099. {
  1100. if ( cl_showerror.GetInt() != 0 )
  1101. {
  1102. // It's bogus, server doesn't have a match, destroy it:
  1103. Msg( "Removing unack'ed predicted entity: %s created %s(%i) id == %s : %p\n",
  1104. ent->GetClassname(),
  1105. ctx->m_pszCreationModule,
  1106. ctx->m_nCreationLineNumber,
  1107. ent->m_PredictableID.Describe(),
  1108. ent );
  1109. }
  1110. }
  1111. // FIXME: Do we need an OnPredictedEntityRemove call with an "it's not valid"
  1112. // flag of some kind
  1113. }
  1114. // This will remove it from predictables list and will also free the entity, etc.
  1115. ent->Release();
  1116. }
  1117. #endif
  1118. }
  1119. //-----------------------------------------------------------------------------
  1120. // Purpose:
  1121. //-----------------------------------------------------------------------------
  1122. void CPrediction::RestoreOriginalEntityState( int nSlot )
  1123. {
  1124. #if !defined( NO_ENTITY_PREDICTION )
  1125. VPROF( "CPrediction::RestoreOriginalEntityState" );
  1126. PREDICTION_TRACKVALUECHANGESCOPE( "restore" );
  1127. Assert( C_BaseEntity::IsAbsRecomputationsEnabled() );
  1128. // Transfer intermediate data from other predictables
  1129. int c = GetPredictables( nSlot )->GetPredictableCount();
  1130. for ( int i = 0; i < c; ++i )
  1131. {
  1132. C_BaseEntity *ent = GetPredictables( nSlot )->GetPredictable( i );
  1133. if ( !ent || !ent->GetPredictable() )
  1134. continue;
  1135. ent->RestoreData( "RestoreOriginalEntityState", C_BaseEntity::SLOT_ORIGINALDATA, PC_EVERYTHING );
  1136. ent->OnPostRestoreData();
  1137. }
  1138. #endif
  1139. }
  1140. void CPrediction::ResetSimulationTick()
  1141. {
  1142. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  1143. int nSlot = GET_ACTIVE_SPLITSCREEN_SLOT();
  1144. // Make sure simulation occurs at most once per entity per usercmd
  1145. for (int i = 0; i < GetPredictables( nSlot )->GetPredictableCount(); i++ )
  1146. {
  1147. C_BaseEntity *entity = GetPredictables( nSlot )->GetPredictable( i );
  1148. if ( entity && entity->GetSplitUserPlayerPredictionSlot() == nSlot )
  1149. {
  1150. entity->m_nSimulationTick = -1;
  1151. }
  1152. }
  1153. }
  1154. //-----------------------------------------------------------------------------
  1155. // Purpose:
  1156. // Input : current_command -
  1157. // curtime -
  1158. // *cmd -
  1159. // *tcmd -
  1160. // *localPlayer -
  1161. //-----------------------------------------------------------------------------
  1162. void CPrediction::RunSimulation( int current_command, float curtime, CUserCmd *cmd, C_BasePlayer *localPlayer )
  1163. {
  1164. #if !defined( NO_ENTITY_PREDICTION )
  1165. VPROF( "CPrediction::RunSimulation" );
  1166. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  1167. int nSlot = GET_ACTIVE_SPLITSCREEN_SLOT();
  1168. Assert( localPlayer );
  1169. C_CommandContext *ctx = localPlayer->GetCommandContext();
  1170. Assert( ctx );
  1171. ctx->needsprocessing = true;
  1172. ctx->cmd = *cmd;
  1173. ctx->command_number = current_command;
  1174. IPredictionSystem::SuppressEvents( !IsFirstTimePredicted() );
  1175. ResetSimulationTick();
  1176. // Don't used cached numpredictables since entities can be created mid-prediction by the player
  1177. for ( int i = 0; i < GetPredictables( nSlot )->GetPredictableCount(); i++ )
  1178. {
  1179. // Always reset
  1180. gpGlobals->curtime = curtime;
  1181. gpGlobals->frametime = m_bEnginePaused ? 0 : TICK_INTERVAL;
  1182. C_BaseEntity *entity = GetPredictables( nSlot )->GetPredictable( i );
  1183. if ( !entity )
  1184. continue;
  1185. if ( entity->GetSplitUserPlayerPredictionSlot() != nSlot )
  1186. continue;
  1187. bool islocal = ( localPlayer == entity ) ? true : false;
  1188. // Local player simulates first, if this assert fires then the predictables list isn't sorted
  1189. // correctly (or we started predicting C_World???)
  1190. if ( islocal && !IsValidSplitScreenSlot( i ) )
  1191. continue;
  1192. // Player can't be this so cull other entities here
  1193. if ( entity->GetFlags() & FL_STATICPROP )
  1194. {
  1195. continue;
  1196. }
  1197. // Player is not actually in the m_SimulatedByThisPlayer list, of course
  1198. if ( entity->IsPlayerSimulated() )
  1199. {
  1200. continue;
  1201. }
  1202. if ( AddDataChangeEvent( entity, DATA_UPDATE_DATATABLE_CHANGED, &entity->m_DataChangeEventRef ) )
  1203. {
  1204. entity->OnPreDataChanged( DATA_UPDATE_DATATABLE_CHANGED );
  1205. }
  1206. // Certain entities can be created locally and if so created, should be
  1207. // simulated until a network update arrives
  1208. if ( entity->IsClientCreated() )
  1209. {
  1210. // Only simulate these on new usercmds
  1211. if ( !IsFirstTimePredicted() )
  1212. continue;
  1213. entity->PhysicsSimulate();
  1214. }
  1215. else
  1216. {
  1217. entity->PhysicsSimulate();
  1218. }
  1219. // Don't update last networked data here!!!
  1220. entity->OnLatchInterpolatedVariables( LATCH_SIMULATION_VAR | LATCH_ANIMATION_VAR | INTERPOLATE_OMIT_UPDATE_LAST_NETWORKED );
  1221. }
  1222. // Only call the physics update for the entire physics system if we support predicted physics.
  1223. if ( cl_predictphysics.GetBool() )
  1224. {
  1225. PhysicsSimulate();
  1226. }
  1227. // Always reset after running command
  1228. IPredictionSystem::SuppressEvents( false );
  1229. #endif
  1230. }
  1231. //-----------------------------------------------------------------------------
  1232. // Purpose:
  1233. //-----------------------------------------------------------------------------
  1234. void CPrediction::Untouch( int nSlot )
  1235. {
  1236. #if !defined( NO_ENTITY_PREDICTION )
  1237. int numpredictables = GetPredictables( nSlot )->GetPredictableCount();
  1238. // Loop through all entities again, checking their untouch if flagged to do so
  1239. int i;
  1240. for ( i = 0; i < numpredictables; i++ )
  1241. {
  1242. C_BaseEntity *entity = GetPredictables( nSlot )->GetPredictable( i );
  1243. if ( !entity )
  1244. continue;
  1245. if ( !entity->GetCheckUntouch() )
  1246. continue;
  1247. entity->PhysicsCheckForEntityUntouch();
  1248. }
  1249. #endif
  1250. }
  1251. void CPrediction::StorePredictionResults( int nSlot, int predicted_frame )
  1252. {
  1253. #if !defined( NO_ENTITY_PREDICTION )
  1254. VPROF( "CPrediction::StorePredictionResults" );
  1255. PREDICTION_TRACKVALUECHANGESCOPE( "save" );
  1256. int c = GetPredictables( nSlot )->GetPredictableCount();
  1257. // Now save off all of the results
  1258. for ( int i = 0; i < c; ++i )
  1259. {
  1260. C_BaseEntity *entity = GetPredictables( nSlot )->GetPredictable( i );
  1261. if ( !entity )
  1262. continue;
  1263. // Certain entities can be created locally and if so created, should be
  1264. // simulated until a network update arrives
  1265. if ( !entity->GetPredictable() )
  1266. continue;
  1267. // FIXME: The lack of this call inexplicably actually creates prediction errors
  1268. InvalidateEFlagsRecursive( entity, EFL_DIRTY_ABSTRANSFORM | EFL_DIRTY_ABSVELOCITY | EFL_DIRTY_ABSANGVELOCITY );
  1269. entity->SaveData( "StorePredictionResults", predicted_frame, PC_EVERYTHING );
  1270. //if we're keeping first frame results, copy them now
  1271. if( m_Split[ nSlot ].m_bFirstTimePredicted && (entity->m_pIntermediateData_FirstPredicted[0] != NULL) )
  1272. {
  1273. entity->m_nIntermediateData_FirstPredictedShiftMarker = predicted_frame + 1;
  1274. memcpy( entity->m_pIntermediateData_FirstPredicted[predicted_frame + 1], entity->m_pIntermediateData[predicted_frame], entity->GetPredDescMap()->m_nPackedSize );
  1275. }
  1276. }
  1277. #endif
  1278. }
  1279. //-----------------------------------------------------------------------------
  1280. // Purpose:
  1281. // Input : slots_to_remove -
  1282. // previous_last_slot -
  1283. //-----------------------------------------------------------------------------
  1284. void CPrediction::ShiftIntermediateDataForward( int nSlot, int slots_to_remove, int number_of_commands_run )
  1285. {
  1286. #if !defined( NO_ENTITY_PREDICTION )
  1287. VPROF( "CPrediction::ShiftIntermediateDataForward" );
  1288. PREDICTION_TRACKVALUECHANGESCOPE( "shift" );
  1289. if ( !C_BasePlayer::HasAnyLocalPlayer() )
  1290. return;
  1291. // Don't screw up memory of current player from history buffers if not filling in history buffers
  1292. // during prediction!!!
  1293. if ( !cl_predict->GetInt() )
  1294. return;
  1295. int c = GetPredictables( nSlot )->GetPredictableCount();
  1296. int i;
  1297. for ( i = 0; i < c; i++ )
  1298. {
  1299. C_BaseEntity *ent = GetPredictables( nSlot )->GetPredictable( i );
  1300. if ( !ent )
  1301. continue;
  1302. if ( !ent->GetPredictable() )
  1303. continue;
  1304. ent->ShiftIntermediateDataForward( slots_to_remove, number_of_commands_run );
  1305. }
  1306. #endif
  1307. }
  1308. //-----------------------------------------------------------------------------
  1309. // Purpose:
  1310. // Input : slots_to_remove -
  1311. //-----------------------------------------------------------------------------
  1312. void CPrediction::ShiftFirstPredictedIntermediateDataForward( int nSlot, int slots_to_remove )
  1313. {
  1314. #if !defined( NO_ENTITY_PREDICTION )
  1315. if( (slots_to_remove == 0) || (slots_to_remove >= MULTIPLAYER_BACKUP) )
  1316. return;
  1317. VPROF( "CPrediction::ShiftFirstPredictedIntermediateDataForward" );
  1318. PREDICTION_TRACKVALUECHANGESCOPE( "shift" );
  1319. if ( !C_BasePlayer::HasAnyLocalPlayer() )
  1320. return;
  1321. // Don't screw up memory of current player from history buffers if not filling in history buffers
  1322. // during prediction!!!
  1323. if ( !cl_predict->GetInt() )
  1324. return;
  1325. int c = GetPredictables( nSlot )->GetPredictableCount();
  1326. int i;
  1327. for ( i = 0; i < c; i++ )
  1328. {
  1329. C_BaseEntity *ent = GetPredictables( nSlot )->GetPredictable( i );
  1330. if ( !ent )
  1331. continue;
  1332. if ( !ent->GetPredictable() )
  1333. continue;
  1334. ent->ShiftFirstPredictedIntermediateDataForward( slots_to_remove );
  1335. }
  1336. #endif
  1337. }
  1338. //-----------------------------------------------------------------------------
  1339. // Purpose:
  1340. // Input : predicted_frame -
  1341. //-----------------------------------------------------------------------------
  1342. void CPrediction::RestoreEntityToPredictedFrame( int nSlot, int predicted_frame )
  1343. {
  1344. #if !defined( NO_ENTITY_PREDICTION )
  1345. VPROF( "CPrediction::RestoreEntityToPredictedFrame" );
  1346. PREDICTION_TRACKVALUECHANGESCOPE( "restoretopred" );
  1347. if ( !C_BasePlayer::GetLocalPlayer( nSlot ) )
  1348. return;
  1349. // Don't screw up memory of current player from history buffers if not filling in history buffers
  1350. // during prediction!!!
  1351. if ( !cl_predict->GetInt() )
  1352. return;
  1353. int c = GetPredictables( nSlot )->GetPredictableCount();
  1354. int i;
  1355. for ( i = 0; i < c; i++ )
  1356. {
  1357. C_BaseEntity *ent = GetPredictables( nSlot )->GetPredictable( i );
  1358. if ( !ent )
  1359. continue;
  1360. if ( !ent->GetPredictable() )
  1361. continue;
  1362. ent->RestoreData( "RestoreEntityToPredictedFrame", predicted_frame, PC_EVERYTHING );
  1363. ent->OnPostRestoreData();
  1364. }
  1365. #endif
  1366. }
  1367. //-----------------------------------------------------------------------------
  1368. // Purpose: Computes starting destination for intermediate prediction data results and
  1369. // does any fixups required by network optimization
  1370. // Input : received_new_world_update -
  1371. // incoming_acknowledged -
  1372. // Output : int
  1373. //-----------------------------------------------------------------------------
  1374. int CPrediction::ComputeFirstCommandToExecute( int nSlot, bool received_new_world_update, int incoming_acknowledged, int outgoing_command )
  1375. {
  1376. int destination_slot = 1;
  1377. #if !defined( NO_ENTITY_PREDICTION )
  1378. int skipahead = 0;
  1379. Split_t &split = m_Split[ nSlot ];
  1380. // If we didn't receive a new update ( or we received an update that didn't ack any new CUserCmds --
  1381. // so for the player it should be just like receiving no update ), just jump right up to the very
  1382. // last command we created for this very frame since we probably wouldn't have had any errors without
  1383. // being notified by the server of such a case.
  1384. // NOTE: received_new_world_update only gets set to false if cl_pred_optimize >= 1
  1385. if ( !received_new_world_update || !split.m_nServerCommandsAcknowledged )
  1386. {
  1387. if( !split.m_bPerformedTickShift )
  1388. {
  1389. // this is where we would normally start
  1390. int start = incoming_acknowledged + 1;
  1391. // outgoing_command is where we really want to start
  1392. skipahead = MAX( 0, ( outgoing_command - start ) );
  1393. // Don't start past the last predicted command, though, or we'll get prediction errors
  1394. skipahead = MIN( skipahead, split.m_nCommandsPredicted );
  1395. // Always restore since otherwise we might start prediction using an "interpolated" value instead of a purely predicted value
  1396. RestoreEntityToPredictedFrame( nSlot, skipahead - 1 );
  1397. //Msg( "%i/%i no world, skip to %i restore from slot %i\n",
  1398. // gpGlobals->framecount,
  1399. // gpGlobals->tickcount,
  1400. // skipahead,
  1401. // skipahead - 1 );
  1402. }
  1403. }
  1404. else
  1405. {
  1406. // Otherwise, there is a second optimization, wherein if we did receive an update, but no
  1407. // values differed (or were outside their epsilon) and the server actually acknowledged running
  1408. // one or more commands, then we can revert the entity to the predicted state from last frame,
  1409. // shift the # of commands worth of intermediate state off of front the intermediate state array, and
  1410. // only predict the usercmd from the latest render frame.
  1411. if ( cl_pred_optimize.GetInt() >= 2 &&
  1412. !split.m_bPreviousAckHadErrors &&
  1413. split.m_nCommandsPredicted > 0 &&
  1414. split.m_nServerCommandsAcknowledged <= split.m_nCommandsPredicted &&
  1415. !split.m_bPerformedTickShift )
  1416. {
  1417. // Copy all of the previously predicted data back into entity so we can skip repredicting it
  1418. // This is the final slot that we previously predicted
  1419. RestoreEntityToPredictedFrame( nSlot, split.m_nCommandsPredicted - 1 );
  1420. // Shift intermediate state blocks down by # of commands ack'd
  1421. ShiftIntermediateDataForward( nSlot, split.m_nServerCommandsAcknowledged, split.m_nCommandsPredicted );
  1422. // Only predict new commands (note, this should be the same number that we could compute
  1423. // above based on outgoing_command - incoming_acknowledged - 1
  1424. skipahead = ( split.m_nCommandsPredicted - split.m_nServerCommandsAcknowledged );
  1425. //Msg( "%i/%i optimize2, skip to %i restore from slot %i\n",
  1426. // gpGlobals->framecount,
  1427. // gpGlobals->tickcount,
  1428. // skipahead,
  1429. // split.m_nCommandsPredicted - 1 );
  1430. }
  1431. else
  1432. {
  1433. if( split.m_bPreviousAckHadErrors )
  1434. {
  1435. int count = GetPredictables( nSlot )->GetPredictableCount();
  1436. for ( int i = 0; i < count; i++ )
  1437. {
  1438. C_BaseEntity *ent = GetPredictables( nSlot )->GetPredictable( i );
  1439. if ( !ent )
  1440. continue;
  1441. ent->m_bEverHadPredictionErrorsForThisCommand = true; //this bool will get pulled forward until a new command is predicted for the first time
  1442. }
  1443. }
  1444. if ( ( split.m_bPreviousAckHadErrors && cl_pred_doresetlatch.GetBool() ) ||
  1445. cl_pred_doresetlatch.GetInt() == 2 )
  1446. {
  1447. // Both players should have == time base, etc.
  1448. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer( nSlot );
  1449. // If an entity gets a prediction error, then we want to clear out its interpolated variables
  1450. // so we don't mix different samples at the same timestamps. We subtract 1 tick interval here because
  1451. // if we don't, we'll have 3 interpolation entries with the same timestamp as this predicted
  1452. // frame, so we won't be able to interpolate (which leads to jerky movement in the player when
  1453. // ANY entity like your gun gets a prediction error).
  1454. float flPrev = gpGlobals->curtime;
  1455. gpGlobals->curtime = pLocalPlayer->GetTimeBase() - TICK_INTERVAL;
  1456. if( split.m_bPreviousAckErrorTriggersFullLatchReset || (cl_pred_doresetlatch.GetInt() == 2) )
  1457. {
  1458. for ( int i = 0; i < GetPredictables( nSlot )->GetPredictableCount(); i++ )
  1459. {
  1460. C_BaseEntity *entity = GetPredictables( nSlot )->GetPredictable( i );
  1461. if ( entity )
  1462. {
  1463. entity->ResetLatched();
  1464. }
  1465. }
  1466. }
  1467. else
  1468. {
  1469. //individual latch resets
  1470. for ( int i = 0; i < split.m_EntsWithPredictionErrorsInLastAck.Count(); i++ )
  1471. {
  1472. C_BaseEntity *entity = split.m_EntsWithPredictionErrorsInLastAck[i];
  1473. if( entity )
  1474. {
  1475. //ensure it's still in our predictable list
  1476. for ( int j = 0; j < GetPredictables( nSlot )->GetPredictableCount(); j++ )
  1477. {
  1478. if( entity == GetPredictables( nSlot )->GetPredictable( j ) )
  1479. {
  1480. entity->ResetLatched();
  1481. break;
  1482. }
  1483. }
  1484. }
  1485. }
  1486. }
  1487. gpGlobals->curtime = flPrev;
  1488. }
  1489. }
  1490. }
  1491. ShiftFirstPredictedIntermediateDataForward( nSlot, split.m_nServerCommandsAcknowledged );
  1492. destination_slot += skipahead;
  1493. // Always reset these values now that we handled them
  1494. split.m_nCommandsPredicted = 0;
  1495. split.m_bPreviousAckHadErrors = false;
  1496. split.m_nServerCommandsAcknowledged = 0;
  1497. split.m_bPerformedTickShift = false;
  1498. #endif
  1499. return destination_slot;
  1500. }
  1501. //-----------------------------------------------------------------------------
  1502. // Actually does the prediction work, returns false if an error occurred
  1503. //-----------------------------------------------------------------------------
  1504. bool CPrediction::PerformPrediction( int nSlot, C_BasePlayer *localPlayer, bool received_new_world_update, int incoming_acknowledged, int outgoing_command )
  1505. {
  1506. MDLCACHE_CRITICAL_SECTION();
  1507. #if !defined( NO_ENTITY_PREDICTION )
  1508. VPROF( "CPrediction::PerformPrediction" );
  1509. Assert( localPlayer );
  1510. // This makes sure that we are allowed to sample the world when it may not be ready to be sampled
  1511. Assert( C_BaseEntity::IsAbsQueriesValid() );
  1512. Assert( C_BaseEntity::IsAbsRecomputationsEnabled() );
  1513. // Start at command after last one server has processed and
  1514. // go until we get to targettime or we run out of new commands
  1515. int i = ComputeFirstCommandToExecute( nSlot, received_new_world_update, incoming_acknowledged, outgoing_command );
  1516. Assert( i >= 1 );
  1517. // This is a hack to get the CTriggerAutoGameMovement auto duck triggers to correctly deal with prediction.
  1518. // Here we just untouch any triggers the player was touching (since we might have teleported the origin
  1519. // backward from it's previous position) and then re-touch any triggers it's currently in
  1520. #if !defined( PORTAL2 ) //portal2 coop likes trigger touch behavior consistent with serverside trigger touch behavior
  1521. localPlayer->SetCheckUntouch( true );
  1522. localPlayer->PhysicsCheckForEntityUntouch();
  1523. #endif
  1524. localPlayer->PhysicsTouchTriggers();
  1525. // undo interpolation changes for entities we stand on
  1526. C_BaseEntity *ground = localPlayer->GetGroundEntity();
  1527. while ( ground && ground->entindex() > 0 )
  1528. {
  1529. ground->MoveToLastReceivedPosition();
  1530. ground = ground->GetMoveParent();
  1531. }
  1532. #if defined( PORTAL )
  1533. if( cl_predicted_movement_uses_uninterpolated_physics.GetBool() )
  1534. {
  1535. //if we're going to treat physics objects as immovable solids on the client, they might as well be immovable solids in the place the server told us to put them
  1536. //otherwise interpolation effectively teleports it backwards without the need (or support) to push entities backwards with it.
  1537. //If you happen to be pushing a physics object, this will make movement traces freak out as we start in solid.
  1538. MoveUnpredictedPhysicsNearPlayerToNetworkedPosition( localPlayer );
  1539. }
  1540. #endif
  1541. Split_t &split = m_Split[ nSlot ];
  1542. physenv->DoneReferencingPreviousCommands( incoming_acknowledged - 1 );
  1543. bool bTooMany = outgoing_command - incoming_acknowledged >= MULTIPLAYER_BACKUP;
  1544. while ( !bTooMany )
  1545. {
  1546. // Incoming_acknowledged is the last usercmd the server acknowledged having acted upon
  1547. int current_command = incoming_acknowledged + i;
  1548. // We've caught up to the current command.
  1549. if ( current_command > outgoing_command )
  1550. break;
  1551. CUserCmd *cmd = input->GetUserCmd( nSlot, current_command );
  1552. if ( !cmd )
  1553. {
  1554. bTooMany = true;
  1555. break;
  1556. }
  1557. Assert( i < MULTIPLAYER_BACKUP );
  1558. // Is this the first time predicting this
  1559. split.m_bFirstTimePredicted = !cmd->hasbeenpredicted;
  1560. #if defined( KEEP_COMMAND_REPREDICTION_COUNT )
  1561. split.m_Debug_RepredictionCount = cmd->debug_RepredictionCount;
  1562. #endif
  1563. // Set globals appropriately
  1564. float curtime = ( localPlayer->m_nTickBase ) * TICK_INTERVAL;
  1565. if( physenv->IsPredicted() )
  1566. {
  1567. physenv->SetPredictionCommandNum( current_command );
  1568. if( (m_Split[ nSlot ].m_nCommandsPredicted == 0) && (i == 1) )
  1569. {
  1570. if( !m_Split[ nSlot ].m_bFirstTimePredicted )
  1571. {
  1572. for ( int j = 0; j < GetPredictables( nSlot )->GetPredictableCount(); j++ )
  1573. {
  1574. C_BaseEntity *entity = GetPredictables( nSlot )->GetPredictable( j );
  1575. if( entity->m_bEverHadPredictionErrorsForThisCommand )
  1576. {
  1577. // Always reset
  1578. gpGlobals->curtime = curtime;
  1579. gpGlobals->frametime = m_bEnginePaused ? 0 : TICK_INTERVAL;
  1580. const byte *predictedFrame = (const byte *)entity->GetFirstPredictedFrame( 0 );
  1581. entity->VPhysicsCompensateForPredictionErrors( predictedFrame );
  1582. }
  1583. }
  1584. }
  1585. //else - if lag is so low that we only predict every command once, do we need to keep around old data to base our corrections on?
  1586. }
  1587. }
  1588. if( !cmd->hasbeenpredicted )
  1589. {
  1590. int count = GetPredictables( nSlot )->GetPredictableCount();
  1591. for ( int i = 0; i < count; ++i )
  1592. {
  1593. C_BaseEntity *entity = GetPredictables( nSlot )->GetPredictable( i );
  1594. if( entity )
  1595. {
  1596. entity->m_bEverHadPredictionErrorsForThisCommand = false;
  1597. }
  1598. }
  1599. }
  1600. RunSimulation( current_command, curtime, cmd, localPlayer );
  1601. gpGlobals->curtime = curtime;
  1602. gpGlobals->frametime = m_bEnginePaused ? 0 : TICK_INTERVAL;
  1603. // Call untouch on any entities no longer predicted to be touching
  1604. Untouch( nSlot );
  1605. // Store intermediate data into appropriate slot
  1606. StorePredictionResults( nSlot, i - 1 ); // Note that I starts at 1
  1607. split.m_nCommandsPredicted = i;
  1608. if ( current_command == outgoing_command )
  1609. {
  1610. localPlayer->m_nFinalPredictedTick = localPlayer->m_nTickBase;
  1611. }
  1612. // Mark that we issued any needed sounds, of not done already
  1613. cmd->hasbeenpredicted = true;
  1614. #if defined( KEEP_COMMAND_REPREDICTION_COUNT )
  1615. ++cmd->debug_RepredictionCount;
  1616. #endif
  1617. // Copy the state over.
  1618. i++;
  1619. }
  1620. // Somehow we looped past the end of the list (severe lag), don't predict at all
  1621. return !bTooMany;
  1622. #endif
  1623. return true;
  1624. }
  1625. //-----------------------------------------------------------------------------
  1626. // Purpose:
  1627. // Input : startframe -
  1628. // validframe -
  1629. // incoming_acknowledged -
  1630. // outgoing_command -
  1631. //-----------------------------------------------------------------------------
  1632. void CPrediction::Update( int startframe, bool validframe,
  1633. int incoming_acknowledged, int outgoing_command )
  1634. {
  1635. #if !defined( NO_ENTITY_PREDICTION )
  1636. VPROF_BUDGET( "CPrediction::Update", VPROF_BUDGETGROUP_PREDICTION );
  1637. m_bEnginePaused = engine->IsPaused();
  1638. bool received_new_world_update = true;
  1639. // HACK!
  1640. float flTimeStamp = engine->GetLastTimeStamp();
  1641. bool bTimeStampChanged = m_flLastServerWorldTimeStamp != flTimeStamp;
  1642. m_flLastServerWorldTimeStamp = flTimeStamp;
  1643. // Still starting at same frame, so make sure we don't do extra prediction ,etc.
  1644. if ( ( m_nPreviousStartFrame == startframe ) &&
  1645. cl_pred_optimize.GetBool() &&
  1646. cl_predict->GetInt() && bTimeStampChanged )
  1647. {
  1648. received_new_world_update = false;
  1649. }
  1650. m_nPreviousStartFrame = startframe;
  1651. // Save off current timer values, etc.
  1652. m_SavedVars = *gpGlobals;
  1653. FOR_EACH_VALID_SPLITSCREEN_PLAYER( nSlot )
  1654. {
  1655. ACTIVE_SPLITSCREEN_PLAYER_GUARD( nSlot );
  1656. _Update( nSlot, received_new_world_update, validframe, incoming_acknowledged, outgoing_command );
  1657. }
  1658. // Restore current timer values, etc.
  1659. *gpGlobals = m_SavedVars;
  1660. #endif
  1661. }
  1662. //-----------------------------------------------------------------------------
  1663. // Do the dirty deed of predicting the local player
  1664. //-----------------------------------------------------------------------------
  1665. void CPrediction::_Update( int nSlot, bool received_new_world_update, bool validframe,
  1666. int incoming_acknowledged, int outgoing_command )
  1667. {
  1668. #if !defined( NO_ENTITY_PREDICTION )
  1669. QAngle viewangles;
  1670. C_BasePlayer *localPlayer = C_BasePlayer::GetLocalPlayer( nSlot );
  1671. if ( !localPlayer )
  1672. return;
  1673. m_Split[nSlot].m_nLastCommandAcknowledged = incoming_acknowledged;
  1674. // Always using current view angles no matter what
  1675. // NOTE: ViewAngles are always interpreted as being *relative* to the player
  1676. engine->GetViewAngles( viewangles );
  1677. localPlayer->SetLocalAngles( viewangles );
  1678. if ( !validframe )
  1679. {
  1680. return;
  1681. }
  1682. // If we are not doing prediction, copy authoritative value into velocity and angle.
  1683. if ( !cl_predict->GetInt() )
  1684. {
  1685. // When not predicting, we at least must make sure the player
  1686. // view angles match the view angles...
  1687. localPlayer->SetLocalViewAngles( viewangles );
  1688. return;
  1689. }
  1690. // This is cheesy, but if we have entities that are parented to attachments on other entities, then
  1691. // it'll wind up needing to get a bone transform.
  1692. {
  1693. C_BaseAnimating::AutoAllowBoneAccess boneaccess( true, true );
  1694. // Invalidate bone cache on predictables
  1695. int c = GetPredictables( nSlot )->GetPredictableCount();
  1696. for ( int i = 0; i < c; ++i )
  1697. {
  1698. C_BaseEntity *ent = GetPredictables( nSlot )->GetPredictable( i );
  1699. if ( !ent ||
  1700. !ent->GetBaseAnimating() ||
  1701. !ent->GetPredictable() )
  1702. continue;
  1703. static_cast< C_BaseAnimating * >( ent )->InvalidateBoneCache();
  1704. }
  1705. // Remove any purely client predicted entities that were left "dangling" because the
  1706. // server didn't acknowledge them or which can now safely be removed
  1707. RemoveStalePredictedEntities( nSlot, incoming_acknowledged );
  1708. // Restore objects back to "pristine" state from last network/world state update
  1709. if ( received_new_world_update )
  1710. {
  1711. RestoreOriginalEntityState( nSlot );
  1712. }
  1713. m_bInPrediction = true;
  1714. bool bValid = PerformPrediction( nSlot, localPlayer, received_new_world_update, incoming_acknowledged, outgoing_command );
  1715. m_bInPrediction = false;
  1716. if ( !bValid )
  1717. {
  1718. return;
  1719. }
  1720. }
  1721. // Overwrite predicted angles with the actual view angles
  1722. localPlayer->SetLocalAngles( viewangles );
  1723. // This allows us to sample the world when it may not be ready to be sampled
  1724. Assert( C_BaseEntity::IsAbsQueriesValid() );
  1725. #ifndef CSTRIKE15 // this doesn't seem like it's applicable to the local cstrike player?
  1726. SetIdealPitch( nSlot, localPlayer, localPlayer->GetLocalOrigin(), localPlayer->GetLocalAngles(), localPlayer->m_vecViewOffset );
  1727. #endif
  1728. #endif
  1729. }
  1730. //-----------------------------------------------------------------------------
  1731. // Purpose:
  1732. // Output : Returns true on success, false on failure.
  1733. //-----------------------------------------------------------------------------
  1734. bool CPrediction::IsFirstTimePredicted( void ) const
  1735. {
  1736. #if !defined( NO_ENTITY_PREDICTION )
  1737. return m_Split[ GET_ACTIVE_SPLITSCREEN_SLOT() ].m_bFirstTimePredicted;
  1738. #else
  1739. return false;
  1740. #endif
  1741. }
  1742. #if defined( KEEP_COMMAND_REPREDICTION_COUNT )
  1743. unsigned int CPrediction::GetRepredictionCount( void ) const
  1744. {
  1745. #if !defined( NO_ENTITY_PREDICTION )
  1746. return m_Split[ GET_ACTIVE_SPLITSCREEN_SLOT() ].m_Debug_RepredictionCount;
  1747. #else
  1748. return 0;
  1749. #endif
  1750. }
  1751. #endif
  1752. //-----------------------------------------------------------------------------
  1753. // Purpose: For verifying/fixing operations that don't save/load in a datatable very well
  1754. // Output : Returns the how many commands the server has processed and sent results for
  1755. //-----------------------------------------------------------------------------
  1756. int CPrediction::GetLastAcknowledgedCommandNumber( void ) const
  1757. {
  1758. #if !defined( NO_ENTITY_PREDICTION )
  1759. return m_Split[ GET_ACTIVE_SPLITSCREEN_SLOT() ].m_nLastCommandAcknowledged;
  1760. #else
  1761. return 0;
  1762. #endif
  1763. }
  1764. //-----------------------------------------------------------------------------
  1765. // Purpose:
  1766. // Input : org -
  1767. //-----------------------------------------------------------------------------
  1768. void CPrediction::GetViewOrigin( Vector& org )
  1769. {
  1770. C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
  1771. if ( !player )
  1772. {
  1773. org.Init();
  1774. }
  1775. else
  1776. {
  1777. org = player->GetLocalOrigin();
  1778. }
  1779. }
  1780. //-----------------------------------------------------------------------------
  1781. // Purpose:
  1782. // Input : org -
  1783. //-----------------------------------------------------------------------------
  1784. void CPrediction::SetViewOrigin( Vector& org )
  1785. {
  1786. C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
  1787. if ( !player )
  1788. return;
  1789. player->SetLocalOrigin( org );
  1790. player->m_vecNetworkOrigin = org;
  1791. player->m_iv_vecOrigin.Reset( gpGlobals->curtime );
  1792. }
  1793. //-----------------------------------------------------------------------------
  1794. // Purpose:
  1795. // Input : ang -
  1796. //-----------------------------------------------------------------------------
  1797. void CPrediction::GetViewAngles( QAngle& ang )
  1798. {
  1799. C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
  1800. if ( !player )
  1801. {
  1802. ang.Init();
  1803. }
  1804. else
  1805. {
  1806. ang = player->GetLocalAngles();
  1807. }
  1808. }
  1809. //-----------------------------------------------------------------------------
  1810. // Purpose:
  1811. // Input : ang -
  1812. //-----------------------------------------------------------------------------
  1813. void CPrediction::SetViewAngles( QAngle& ang )
  1814. {
  1815. C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
  1816. if ( !player )
  1817. return;
  1818. player->SetViewAngles( ang );
  1819. player->m_iv_angRotation.Reset( gpGlobals->curtime );
  1820. }
  1821. //-----------------------------------------------------------------------------
  1822. // Purpose:
  1823. // Input : ang -
  1824. //-----------------------------------------------------------------------------
  1825. void CPrediction::GetLocalViewAngles( QAngle& ang )
  1826. {
  1827. C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
  1828. if ( !player )
  1829. {
  1830. ang.Init();
  1831. }
  1832. else
  1833. {
  1834. ang = player->pl.v_angle;
  1835. }
  1836. }
  1837. //-----------------------------------------------------------------------------
  1838. // Purpose:
  1839. // Input : ang -
  1840. //-----------------------------------------------------------------------------
  1841. void CPrediction::SetLocalViewAngles( QAngle& ang )
  1842. {
  1843. C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
  1844. if ( !player )
  1845. return;
  1846. player->SetLocalViewAngles( ang );
  1847. }
  1848. #if !defined( NO_ENTITY_PREDICTION )
  1849. //-----------------------------------------------------------------------------
  1850. // Purpose: For determining that predicted creation entities are un-acked and should
  1851. // be deleted
  1852. // Output : int
  1853. //-----------------------------------------------------------------------------
  1854. int CPrediction::GetIncomingPacketNumber( void ) const
  1855. {
  1856. return m_nIncomingPacketNumber;
  1857. }
  1858. #endif
  1859. //-----------------------------------------------------------------------------
  1860. // Purpose:
  1861. // Output : Returns true on success, false on failure.
  1862. //-----------------------------------------------------------------------------
  1863. bool CPrediction::InPrediction( void ) const
  1864. {
  1865. #if !defined( NO_ENTITY_PREDICTION )
  1866. return m_bInPrediction;
  1867. #else
  1868. return false;
  1869. #endif
  1870. }
  1871. float CPrediction::GetSavedTime() const
  1872. {
  1873. return m_SavedVars.curtime;
  1874. }
  1875. #if (PREDICTION_ERROR_CHECK_LEVEL > 0)
  1876. bool _Easy_DiffPrint_InternalConditions( C_BaseEntity *pEntity )
  1877. {
  1878. return (pEntity->GetPredictable() && prediction->InPrediction());
  1879. }
  1880. #endif