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.

993 lines
25 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #ifndef SWDS
  7. #include "screen.h"
  8. #include "cl_main.h"
  9. #include "iprediction.h"
  10. #include "proto_oob.h"
  11. #include "demo.h"
  12. #include "tier0/icommandline.h"
  13. #include "ispatialpartitioninternal.h"
  14. #include "GameEventManager.h"
  15. #include "cdll_engine_int.h"
  16. #include "voice.h"
  17. #include "host_cmd.h"
  18. #include "server.h"
  19. #include "convar.h"
  20. #include "dt_recv_eng.h"
  21. #include "dt_common_eng.h"
  22. #include "LocalNetworkBackdoor.h"
  23. #include "vox.h"
  24. #include "sound.h"
  25. #include "r_efx.h"
  26. #include "r_local.h"
  27. #include "decal_private.h"
  28. #include "vgui_baseui_interface.h"
  29. #include "host_state.h"
  30. #include "cl_ents_parse.h"
  31. #include "eiface.h"
  32. #include "server.h"
  33. #include "cl_demoactionmanager.h"
  34. #include "decal.h"
  35. #include "r_decal.h"
  36. #include "materialsystem/imaterial.h"
  37. #include "EngineSoundInternal.h"
  38. #include "ivideomode.h"
  39. #include "download.h"
  40. #include "GameUI/IGameUI.h"
  41. #include "cl_demo.h"
  42. #include "cdll_engine_int.h"
  43. #if defined( REPLAY_ENABLED )
  44. #include "replay/ienginereplay.h"
  45. #include "replay_internal.h"
  46. #endif
  47. #include "audio_pch.h"
  48. #if defined ( _X360 )
  49. #include "matchmaking.h"
  50. #endif
  51. // memdbgon must be the last include file in a .cpp file!!!
  52. #include "tier0/memdbgon.h"
  53. extern IVEngineClient *engineClient;
  54. extern CNetworkStringTableContainer *networkStringTableContainerClient;
  55. extern CNetworkStringTableContainer *networkStringTableContainerServer;
  56. static ConVar cl_allowupload ( "cl_allowupload", "1", FCVAR_ARCHIVE, "Client uploads customization files" );
  57. static ConVar cl_voice_filter( "cl_voice_filter", "", 0, "Filter voice by name substring" ); // filter incoming voice data
  58. static ConVar *replay_voice_during_playback = NULL;
  59. extern ConCommand quit;
  60. void CClientState::ConnectionClosing( const char * reason )
  61. {
  62. // if connected, shut down host
  63. if ( m_nSignonState > SIGNONSTATE_NONE )
  64. {
  65. ConMsg( "Disconnect: %s.\n", reason );
  66. if ( !Q_stricmp( reason, INVALID_STEAM_TICKET )
  67. || !Q_stricmp( reason, INVALID_STEAM_LOGON_TICKET_CANCELED ) )
  68. {
  69. g_eSteamLoginFailure = STEAMLOGINFAILURE_BADTICKET;
  70. }
  71. else if ( !Q_stricmp( reason, INVALID_STEAM_LOGON_NOT_CONNECTED ) )
  72. {
  73. g_eSteamLoginFailure = STEAMLOGINFAILURE_NOSTEAMLOGIN;
  74. }
  75. else if ( !Q_stricmp( reason, INVALID_STEAM_LOGGED_IN_ELSEWHERE ) )
  76. {
  77. g_eSteamLoginFailure = STEAMLOGINFAILURE_LOGGED_IN_ELSEWHERE;
  78. }
  79. else if ( !Q_stricmp( reason, INVALID_STEAM_VACBANSTATE ) )
  80. {
  81. g_eSteamLoginFailure = STEAMLOGINFAILURE_VACBANNED;
  82. }
  83. else
  84. {
  85. g_eSteamLoginFailure = STEAMLOGINFAILURE_NONE;
  86. }
  87. if ( reason && reason[0] == '#' )
  88. {
  89. COM_ExplainDisconnection( true, reason );
  90. }
  91. else
  92. {
  93. COM_ExplainDisconnection( true, "Disconnect: %s.\n", reason );
  94. }
  95. SCR_EndLoadingPlaque();
  96. Host_Disconnect( true, reason );
  97. }
  98. }
  99. void CClientState::ConnectionCrashed( const char * reason )
  100. {
  101. // if connected, shut down host
  102. if ( m_nSignonState > SIGNONSTATE_NONE )
  103. {
  104. DebuggerBreakIfDebugging_StagingOnly();
  105. COM_ExplainDisconnection( true, "Disconnect: %s.\n", reason );
  106. SCR_EndLoadingPlaque();
  107. Host_EndGame ( true, "%s", reason );
  108. }
  109. }
  110. void CClientState::FileRequested(const char *fileName, unsigned int transferID)
  111. {
  112. ConMsg( "File '%s' requested from server %s.\n", fileName, m_NetChannel->GetAddress() );
  113. if ( !cl_allowupload.GetBool() )
  114. {
  115. ConMsg( "File uploading disabled.\n" );
  116. m_NetChannel->DenyFile( fileName, transferID );
  117. return;
  118. }
  119. // TODO check if file valid for uploading
  120. m_NetChannel->SendFile( fileName, transferID );
  121. }
  122. void CClientState::FileReceived( const char * fileName, unsigned int transferID )
  123. {
  124. #ifndef _XBOX
  125. // check if the client donwload manager requested this file
  126. CL_FileReceived( fileName, transferID );
  127. // notify client dll
  128. if ( g_ClientDLL )
  129. {
  130. g_ClientDLL->FileReceived( fileName, transferID );
  131. }
  132. #endif
  133. }
  134. void CClientState::FileDenied(const char *fileName, unsigned int transferID )
  135. {
  136. #ifndef _XBOX
  137. // check if the file download manager requested that file
  138. CL_FileDenied( fileName, transferID );
  139. #endif
  140. }
  141. void CClientState::FileSent( const char *fileName, unsigned int transferID )
  142. {
  143. }
  144. void CClientState::PacketStart( int incoming_sequence, int outgoing_acknowledged )
  145. {
  146. // Ack'd incoming messages.
  147. m_nCurrentSequence = incoming_sequence;
  148. command_ack = outgoing_acknowledged;
  149. }
  150. void CClientState::PacketEnd()
  151. {
  152. //
  153. // we don't know if it is ok to save a demo message until
  154. // after we have parsed the frame
  155. //
  156. // Play any sounds we received this packet
  157. CL_DispatchSounds();
  158. // Did we get any messages this tick (i.e., did we call PreEntityPacketReceived)?
  159. if ( GetServerTickCount() != m_nDeltaTick )
  160. return;
  161. // How many commands total did we run this frame
  162. int commands_acknowledged = command_ack - last_command_ack;
  163. // COM_Log( "cl.log", "Server ack'd %i commands this frame\n", commands_acknowledged );
  164. //Msg( "%i/%i CL_PostReadMessages: last ack %i most recent %i acked %i commands\n",
  165. // host_framecount, cl.tickcount,
  166. // cl.last_command_ack,
  167. // cl.netchan->outgoing_sequence - 1,
  168. // commands_acknowledged );
  169. // Highest command parsed from messages
  170. last_command_ack = command_ack;
  171. // Let prediction copy off pristine data and report any errors, etc.
  172. g_pClientSidePrediction->PostNetworkDataReceived( commands_acknowledged );
  173. #ifndef _XBOX
  174. demoaction->DispatchEvents();
  175. #endif
  176. }
  177. #undef CreateEvent
  178. void CClientState::Disconnect( const char *pszReason, bool bShowMainMenu )
  179. {
  180. #if defined( REPLAY_ENABLED )
  181. if ( g_pClientReplayContext && IsConnected() )
  182. {
  183. g_pClientReplayContext->OnClientSideDisconnect();
  184. }
  185. #endif
  186. CBaseClientState::Disconnect( pszReason, bShowMainMenu );
  187. #ifndef _X360
  188. IGameEvent *event = g_GameEventManager.CreateEvent( "client_disconnect" );
  189. if ( event )
  190. {
  191. if ( !pszReason )
  192. pszReason = "";
  193. event->SetString( "message", pszReason );
  194. g_GameEventManager.FireEventClientSide( event );
  195. }
  196. #endif
  197. // stop any demo activities
  198. #ifndef _XBOX
  199. demoplayer->StopPlayback();
  200. demorecorder->StopRecording();
  201. #endif
  202. S_StopAllSounds( true );
  203. R_DecalTermAll();
  204. if ( m_nMaxClients > 1 )
  205. {
  206. if ( EngineVGui()->IsConsoleVisible() == false )
  207. {
  208. // start progress bar immediately for multiplayer level transitions
  209. EngineVGui()->EnabledProgressBarForNextLoad();
  210. }
  211. }
  212. CL_ClearState();
  213. #ifndef _XBOX
  214. // End any in-progress downloads
  215. CL_HTTPStop_f();
  216. #endif
  217. // stop loading progress bar
  218. if (bShowMainMenu)
  219. {
  220. SCR_EndLoadingPlaque();
  221. }
  222. // notify game ui dll of out-of-in-game status
  223. EngineVGui()->NotifyOfServerDisconnect();
  224. if (bShowMainMenu && !engineClient->IsDrawingLoadingImage() && (cl.demonum == -1))
  225. {
  226. // we're not in the middle of loading something, so show the UI
  227. if ( EngineVGui() )
  228. {
  229. EngineVGui()->ActivateGameUI();
  230. }
  231. }
  232. HostState_OnClientDisconnected();
  233. // if we played a demo from the startdemos list, play next one
  234. if (cl.demonum != -1)
  235. {
  236. CL_NextDemo();
  237. }
  238. }
  239. bool CClientState::ProcessTick( NET_Tick *msg )
  240. {
  241. int tick = msg->m_nTick;
  242. m_NetChannel->SetRemoteFramerate( msg->m_flHostFrameTime, msg->m_flHostFrameTimeStdDeviation );
  243. m_ClockDriftMgr.SetServerTick( tick );
  244. // Remember this for GetLastTimeStamp().
  245. m_flLastServerTickTime = tick * host_state.interval_per_tick;
  246. // Use the server tick while reading network data (used for interpolation samples, etc).
  247. g_ClientGlobalVariables.tickcount = tick;
  248. g_ClientGlobalVariables.curtime = tick * host_state.interval_per_tick;
  249. g_ClientGlobalVariables.frametime = (tick - oldtickcount) * host_state.interval_per_tick; // We used to call GetFrameTime() here, but 'insimulation' is always
  250. // true so we have this code right in here to keep it simple.
  251. return true;
  252. }
  253. bool CClientState::ProcessStringCmd( NET_StringCmd *msg )
  254. {
  255. return CBaseClientState::ProcessStringCmd( msg );
  256. }
  257. bool CClientState::ProcessServerInfo( SVC_ServerInfo *msg )
  258. {
  259. // Reset client state
  260. CL_ClearState();
  261. if ( !CBaseClientState::ProcessServerInfo( msg ) )
  262. {
  263. Disconnect( "CBaseClientState::ProcessServerInfo failed", true );
  264. return false;
  265. }
  266. #ifndef _XBOX
  267. if ( demoplayer->IsPlayingBack() )
  268. {
  269. // Because a server doesn't run during
  270. // demoplayback, but the decal system relies on this...
  271. m_nServerCount = gHostSpawnCount;
  272. }
  273. else
  274. {
  275. // tell demo recorder that new map is loaded and we are receiving
  276. // it's signon data (will be written into extra demo header file)
  277. demorecorder->SetSignonState( SIGNONSTATE_NEW );
  278. }
  279. #endif
  280. // is server a HLTV proxy ?
  281. ishltv = msg->m_bIsHLTV;
  282. #if defined( REPLAY_ENABLED )
  283. // is server a replay proxy ?
  284. isreplay = msg->m_bIsReplay;
  285. #endif
  286. // The MD5 of the server map must match the MD5 of the client map. or else
  287. // the client is probably cheating.
  288. V_memcpy( serverMD5.bits, msg->m_nMapMD5.bits, MD5_DIGEST_LENGTH );
  289. // Multiplayer game?
  290. if ( m_nMaxClients > 1 )
  291. {
  292. if ( mp_decals.GetInt() < r_decals.GetInt() )
  293. {
  294. r_decals.SetValue( mp_decals.GetInt() );
  295. }
  296. }
  297. g_ClientGlobalVariables.maxClients = m_nMaxClients;
  298. g_ClientGlobalVariables.network_protocol = msg->m_nProtocol;
  299. #ifdef SHARED_NET_STRING_TABLES
  300. // use same instance of StringTableContainer as the server does
  301. m_StringTableContainer = networkStringTableContainerServer;
  302. CL_HookClientStringTables();
  303. #else
  304. // use own instance of StringTableContainer
  305. m_StringTableContainer = networkStringTableContainerClient;
  306. #endif
  307. CL_ReallocateDynamicData( m_nMaxClients );
  308. if ( sv.IsPaused() )
  309. {
  310. if ( msg->m_fTickInterval != host_state.interval_per_tick )
  311. {
  312. Host_Error( "Expecting interval_per_tick %f, got %f\n",
  313. host_state.interval_per_tick, msg->m_fTickInterval );
  314. return false;
  315. }
  316. }
  317. else
  318. {
  319. host_state.interval_per_tick = msg->m_fTickInterval;
  320. }
  321. // Re-init hud video, especially if we changed game directories
  322. ClientDLL_HudVidInit();
  323. // Don't verify the map and player .mdl crc's until after any missing resources have
  324. // been downloaded. This will still occur before requesting the rest of the signon.
  325. gHostSpawnCount = m_nServerCount;
  326. videomode->MarkClientViewRectDirty(); // leave intermission full screen
  327. return true;
  328. }
  329. bool CClientState::ProcessClassInfo( SVC_ClassInfo *msg )
  330. {
  331. if ( msg->m_bCreateOnClient )
  332. {
  333. #ifndef _XBOX
  334. if ( !demoplayer->IsPlayingBack() )
  335. #endif
  336. {
  337. // Create all of the send tables locally
  338. DataTable_CreateClientTablesFromServerTables();
  339. // Now create all of the server classes locally, too
  340. DataTable_CreateClientClassInfosFromServerClasses( this );
  341. // store the current data tables in demo file to make sure
  342. // they are the same during playback
  343. #ifndef _XBOX
  344. demorecorder->RecordServerClasses( serverGameDLL->GetAllServerClasses() );
  345. #endif
  346. }
  347. LinkClasses(); // link server and client classes
  348. }
  349. else
  350. {
  351. CBaseClientState::ProcessClassInfo( msg );
  352. }
  353. #ifdef DEDICATED
  354. bool bAllowMismatches = false;
  355. #else
  356. bool bAllowMismatches = ( demoplayer && demoplayer->IsPlayingBack() );
  357. #endif // DEDICATED
  358. if ( !RecvTable_CreateDecoders( serverGameDLL->GetStandardSendProxies(), bAllowMismatches ) ) // create receive table decoders
  359. {
  360. Host_EndGame( true, "CL_ParseClassInfo_EndClasses: CreateDecoders failed.\n" );
  361. return false;
  362. }
  363. #ifndef _XBOX
  364. if ( !demoplayer->IsPlayingBack() )
  365. #endif
  366. {
  367. CLocalNetworkBackdoor::InitFastCopy();
  368. }
  369. return true;
  370. }
  371. bool CClientState::ProcessSetPause( SVC_SetPause *msg )
  372. {
  373. CBaseClientState::ProcessSetPause( msg );
  374. return true;
  375. }
  376. bool CClientState::ProcessSetPauseTimed( SVC_SetPauseTimed *msg )
  377. {
  378. CBaseClientState::ProcessSetPauseTimed( msg );
  379. return true;
  380. }
  381. bool CClientState::ProcessVoiceInit( SVC_VoiceInit *msg )
  382. {
  383. #if !defined( NO_VOICE )//#ifndef _XBOX
  384. if ( msg->m_szVoiceCodec[0] == 0 )
  385. {
  386. Voice_Deinit();
  387. }
  388. else
  389. {
  390. Voice_Init( msg->m_szVoiceCodec, msg->m_nSampleRate );
  391. }
  392. #endif
  393. return true;
  394. }
  395. ConVar voice_debugfeedback( "voice_debugfeedback", "0" );
  396. bool CClientState::ProcessVoiceData( SVC_VoiceData *msg )
  397. {
  398. char chReceived[4096];
  399. int bitsRead = msg->m_DataIn.ReadBitsClamped( chReceived, msg->m_nLength );
  400. #if defined ( _X360 )
  401. DWORD dwLength = msg->m_nLength;
  402. XUID xuid = msg->m_xuid;
  403. Audio_GetXVoice()->PlayIncomingVoiceData( xuid, (byte*)chReceived, dwLength );
  404. if ( voice_debugfeedback.GetBool() )
  405. {
  406. Msg( "Received voice from: %d\n", msg->m_nFromClient + 1 );
  407. }
  408. return true;
  409. #endif
  410. #if !defined( NO_VOICE )//#ifndef _XBOX
  411. int iEntity = msg->m_nFromClient + 1;
  412. if ( iEntity == (m_nPlayerSlot + 1) )
  413. {
  414. Voice_LocalPlayerTalkingAck();
  415. }
  416. player_info_t playerinfo;
  417. engineClient->GetPlayerInfo( iEntity, &playerinfo );
  418. if ( Q_strlen( cl_voice_filter.GetString() ) > 0 && Q_strstr( playerinfo.name, cl_voice_filter.GetString() ) == NULL )
  419. return true;
  420. #if defined( REPLAY_ENABLED )
  421. extern IEngineClientReplay *g_pEngineClientReplay;
  422. bool bInReplay = engineClient->IsPlayingDemo() && g_pEngineClientReplay && g_pEngineClientReplay->IsPlayingReplayDemo();
  423. if ( replay_voice_during_playback == NULL )
  424. {
  425. replay_voice_during_playback = g_pCVar->FindVar( "replay_voice_during_playback" );
  426. Assert( replay_voice_during_playback != NULL );
  427. }
  428. // Don't play back voice data during replay unless the client specified it to.
  429. if ( bInReplay && replay_voice_during_playback && !replay_voice_during_playback->GetBool() )
  430. return true;
  431. #endif
  432. // Data length can be zero when the server is just acking a client's voice data.
  433. if ( bitsRead == 0 )
  434. return true;
  435. if ( !Voice_Enabled() )
  436. {
  437. return true;
  438. }
  439. // Have we already initialized the channels for this guy?
  440. int nChannel = Voice_GetChannel( iEntity );
  441. if ( nChannel == VOICE_CHANNEL_ERROR )
  442. {
  443. // Create a channel in the voice engine and a channel in the sound engine for this guy.
  444. nChannel = Voice_AssignChannel( iEntity, msg->m_bProximity );
  445. if ( nChannel == VOICE_CHANNEL_ERROR )
  446. {
  447. // If they used -nosound, then it's not a problem.
  448. if ( S_IsInitted() )
  449. ConDMsg("ProcessVoiceData: Voice_AssignChannel failed for client %d!\n", iEntity-1);
  450. return true;
  451. }
  452. }
  453. // Give the voice engine the data (it in turn gives it to the mixer for the sound engine).
  454. Voice_AddIncomingData( nChannel, chReceived, Bits2Bytes( bitsRead ), m_nCurrentSequence );
  455. #endif
  456. return true;
  457. };
  458. bool CClientState::ProcessPrefetch( SVC_Prefetch *msg )
  459. {
  460. char const *soundname = cl.GetSoundName( msg->m_nSoundIndex );
  461. if ( soundname && soundname [ 0 ] )
  462. {
  463. EngineSoundClient()->PrefetchSound( soundname );
  464. }
  465. return true;
  466. }
  467. void CClientState::ProcessSoundsWithProtoVersion( SVC_Sounds *msg, CUtlVector< SoundInfo_t > &sounds, int nProtoVersion )
  468. {
  469. SoundInfo_t defaultSound; defaultSound.SetDefault();
  470. SoundInfo_t *pDeltaSound = &defaultSound;
  471. // Max is 32 in multiplayer and 255 in singleplayer
  472. // Reserve this memory up front so it doesn't realloc under pDeltaSound pointing at it
  473. sounds.EnsureCapacity( 256 );
  474. for ( int i = 0; i < msg->m_nNumSounds; i++ )
  475. {
  476. int nSound = sounds.AddToTail();
  477. SoundInfo_t *pSound = &(sounds[ nSound ]);
  478. pSound->ReadDelta( pDeltaSound, msg->m_DataIn, nProtoVersion );
  479. pDeltaSound = pSound; // copy delta values
  480. if ( msg->m_bReliableSound )
  481. {
  482. // client is incrementing the reliable sequence numbers itself
  483. m_nSoundSequence = ( m_nSoundSequence + 1 ) & SOUND_SEQNUMBER_MASK;
  484. Assert ( pSound->nSequenceNumber == 0 );
  485. pSound->nSequenceNumber = m_nSoundSequence;
  486. }
  487. }
  488. }
  489. bool CClientState::ProcessSounds( SVC_Sounds *msg )
  490. {
  491. if ( msg->m_DataIn.IsOverflowed() )
  492. {
  493. // Overflowed before we even started! There's nothing we can do with this buffer.
  494. return false;
  495. }
  496. CUtlVector< SoundInfo_t > sounds;
  497. int startbit = msg->m_DataIn.GetNumBitsRead();
  498. // Process with the reported proto version
  499. ProcessSoundsWithProtoVersion( msg, sounds, g_ClientGlobalVariables.network_protocol );
  500. int nRelativeBitsRead = msg->m_DataIn.GetNumBitsRead() - startbit;
  501. if ( msg->m_nLength != nRelativeBitsRead || msg->m_DataIn.IsOverflowed() )
  502. {
  503. // The number of bits read is not what we expect!
  504. sounds.RemoveAll();
  505. int nFallbackProtocol = 0;
  506. // If the demo file thinks it's version 18 or 19, it might actually be the other.
  507. // This is a work around for when we broke compatibility Halloween 2011.
  508. // -Jeep
  509. if ( g_ClientGlobalVariables.network_protocol == PROTOCOL_VERSION_18 )
  510. {
  511. nFallbackProtocol = PROTOCOL_VERSION_19;
  512. }
  513. else if ( g_ClientGlobalVariables.network_protocol == PROTOCOL_VERSION_19 )
  514. {
  515. nFallbackProtocol = PROTOCOL_VERSION_18;
  516. }
  517. if ( nFallbackProtocol != 0 )
  518. {
  519. // Roll back our buffer to before we read those bits and wipe the overflow flag
  520. msg->m_DataIn.Reset();
  521. msg->m_DataIn.Seek( startbit );
  522. // Try again with the fallback version
  523. ProcessSoundsWithProtoVersion( msg, sounds, nFallbackProtocol );
  524. nRelativeBitsRead = msg->m_DataIn.GetNumBitsRead() - startbit;
  525. }
  526. }
  527. if ( msg->m_nLength == nRelativeBitsRead )
  528. {
  529. // Now that we know the bits were read correctly, add all the sounds
  530. for ( int i = 0; i < sounds.Count(); ++i )
  531. {
  532. // Add all received sounds to sorted queue (sounds may arrive in multiple messages),
  533. // will be processed after all packets have been completely parsed
  534. CL_AddSound( sounds[ i ] );
  535. }
  536. // read the correct number of bits
  537. return true;
  538. }
  539. // Wipe the overflow flag and set the buffer to how much we expected to read
  540. msg->m_DataIn.Reset();
  541. msg->m_DataIn.Seek( startbit + msg->m_nLength );
  542. // didn't read the correct number of bits with either proto version attempt
  543. return false;
  544. }
  545. bool CClientState::ProcessFixAngle( SVC_FixAngle *msg )
  546. {
  547. for (int i=0 ; i<3 ; i++)
  548. {
  549. // Clamp between -180 and 180
  550. if (msg->m_Angle[i]>180)
  551. {
  552. msg->m_Angle[i] -= 360;
  553. }
  554. }
  555. if ( msg->m_bRelative )
  556. {
  557. // Update running counter
  558. addangletotal += msg->m_Angle[YAW];
  559. AddAngle a;
  560. a.total = addangletotal;
  561. a.starttime = m_flLastServerTickTime;
  562. addangle.AddToTail( a );
  563. }
  564. else
  565. {
  566. viewangles = msg->m_Angle;
  567. }
  568. return true;
  569. }
  570. bool CClientState::ProcessCrosshairAngle( SVC_CrosshairAngle *msg )
  571. {
  572. g_ClientDLL->SetCrosshairAngle( msg->m_Angle );
  573. return true;
  574. }
  575. bool CClientState::ProcessBSPDecal( SVC_BSPDecal *msg )
  576. {
  577. model_t * model;
  578. if ( msg->m_nEntityIndex )
  579. {
  580. model = GetModel( msg->m_nModelIndex );
  581. }
  582. else
  583. {
  584. model = host_state.worldmodel;
  585. if ( !model )
  586. {
  587. Warning( "ProcessBSPDecal: Trying to project on world before host_state.worldmodel is set!!!\n" );
  588. }
  589. }
  590. if ( model == NULL )
  591. {
  592. IMaterial *mat = Draw_DecalMaterial( msg->m_nDecalTextureIndex );
  593. char const *matname = "???";
  594. if ( mat )
  595. {
  596. matname = mat->GetName();
  597. }
  598. Warning( "Warning! Static BSP decal (%s), on NULL model index %i for entity index %i.\n",
  599. matname,
  600. msg->m_nModelIndex,
  601. msg->m_nEntityIndex );
  602. return true;
  603. }
  604. if (r_decals.GetInt())
  605. {
  606. g_pEfx->DecalShoot(
  607. msg->m_nDecalTextureIndex,
  608. msg->m_nEntityIndex,
  609. model,
  610. vec3_origin,
  611. vec3_angle,
  612. msg->m_Pos,
  613. NULL,
  614. msg->m_bLowPriority ? 0 : FDECAL_PERMANENT );
  615. }
  616. return true;
  617. }
  618. bool CClientState::ProcessGameEvent(SVC_GameEvent *msg)
  619. {
  620. tmZoneFiltered( TELEMETRY_LEVEL0, 50, TMZF_NONE, "%s", __FUNCTION__ );
  621. int startbit = msg->m_DataIn.GetNumBitsRead();
  622. IGameEvent *event = g_GameEventManager.UnserializeEvent( &msg->m_DataIn );
  623. int length = msg->m_DataIn.GetNumBitsRead() - startbit;
  624. if ( length != msg->m_nLength )
  625. {
  626. DevMsg("CClientState::ProcessGameEvent: KeyValue length mismatch.\n" );
  627. return true;
  628. }
  629. if ( !event )
  630. {
  631. DevMsg("CClientState::ProcessGameEvent: UnserializeKeyValue failed.\n" );
  632. return true;
  633. }
  634. g_GameEventManager.FireEventClientSide( event );
  635. return true;
  636. }
  637. bool CClientState::ProcessUserMessage(SVC_UserMessage *msg)
  638. {
  639. // buffer for incoming user message
  640. ALIGN4 byte userdata[ MAX_USER_MSG_DATA ] ALIGN4_POST = { 0 };
  641. bf_read userMsg( "UserMessage(read)", userdata, sizeof( userdata ) );
  642. int bitsRead = msg->m_DataIn.ReadBitsClamped( userdata, msg->m_nLength );
  643. userMsg.StartReading( userdata, Bits2Bytes( bitsRead ) );
  644. // dispatch message to client.dll
  645. if ( !g_ClientDLL->DispatchUserMessage( msg->m_nMsgType, userMsg ) )
  646. {
  647. ConMsg( "Couldn't dispatch user message (%i)\n", msg->m_nMsgType );
  648. return false;
  649. }
  650. return true;
  651. }
  652. bool CClientState::ProcessEntityMessage(SVC_EntityMessage *msg)
  653. {
  654. // Look up entity
  655. IClientNetworkable *entity = entitylist->GetClientNetworkable( msg->m_nEntityIndex );
  656. if ( !entity )
  657. {
  658. // message was send to use, even we don't have this entity TODO change that on server side
  659. return true;
  660. }
  661. // route to entity
  662. MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );
  663. // buffer for incoming user message
  664. ALIGN4 byte entityData[ MAX_ENTITY_MSG_DATA ] ALIGN4_POST = { 0 };
  665. bf_read entMsg( "EntityMessage(read)", entityData, sizeof( entityData ) );
  666. int bitsRead = msg->m_DataIn.ReadBitsClamped( entityData, msg->m_nLength );
  667. entMsg.StartReading( entityData, Bits2Bytes( bitsRead ) );
  668. entity->ReceiveMessage( msg->m_nClassID, entMsg );
  669. return true;
  670. }
  671. bool CClientState::ProcessPacketEntities( SVC_PacketEntities *msg )
  672. {
  673. if ( !msg->m_bIsDelta )
  674. {
  675. // Delta too old or is initial message
  676. #ifndef _XBOX
  677. // we can start recording now that we've received an uncompressed packet
  678. demorecorder->SetSignonState( SIGNONSTATE_FULL );
  679. #endif
  680. // Tell prediction that we're recreating entities due to an uncompressed packet arriving
  681. if ( g_pClientSidePrediction )
  682. {
  683. g_pClientSidePrediction->OnReceivedUncompressedPacket();
  684. }
  685. }
  686. else
  687. {
  688. if ( m_nDeltaTick == -1 )
  689. {
  690. // we requested a full update but still got a delta compressed packet. ignore it.
  691. return true;
  692. }
  693. // Preprocessing primarily does client prediction. So if we're processing deltas--do it
  694. // otherwise, we're about to be told exactly what the state of everything is--so skip it.
  695. CL_PreprocessEntities(); // setup client prediction
  696. }
  697. TRACE_PACKET(( "CL Receive (%d <-%d)\n", m_nCurrentSequence, msg->m_nDeltaFrom ));
  698. TRACE_PACKET(( "CL Num Ents (%d)\n", msg->m_nUpdatedEntries ));
  699. if ( g_pLocalNetworkBackdoor )
  700. {
  701. if ( m_nSignonState == SIGNONSTATE_SPAWN )
  702. {
  703. // We are done with signon sequence.
  704. SetSignonState( SIGNONSTATE_FULL, m_nServerCount );
  705. }
  706. // ignore message, all entities are transmitted using fast local memcopy routines
  707. m_nDeltaTick = GetServerTickCount();
  708. return true;
  709. }
  710. if ( !CL_ProcessPacketEntities ( msg ) )
  711. return false;
  712. return CBaseClientState::ProcessPacketEntities( msg );
  713. }
  714. bool CClientState::ProcessTempEntities( SVC_TempEntities *msg )
  715. {
  716. bool bReliable = false;
  717. float fire_time = cl.GetTime();
  718. #ifndef _XBOX
  719. // delay firing temp ents by cl_interp in multiplayer or demoplayback
  720. if ( cl.m_nMaxClients > 1 || demoplayer->IsPlayingBack() )
  721. {
  722. float flInterpAmount = GetClientInterpAmount();
  723. fire_time += flInterpAmount;
  724. }
  725. #endif
  726. if ( msg->m_nNumEntries == 0 )
  727. {
  728. bReliable = true;
  729. msg->m_nNumEntries = 1;
  730. }
  731. int flags = bReliable ? FEV_RELIABLE : 0;
  732. // Don't actually queue unreliable events if playing a demo and skipping ahead
  733. #ifndef _XBOX
  734. if ( !bReliable && demoplayer->IsSkipping() )
  735. {
  736. return true;
  737. }
  738. #endif
  739. bf_read &buffer = msg->m_DataIn; // shortcut
  740. int classID = -1;
  741. void *from = NULL;
  742. C_ServerClassInfo *pServerClass = NULL;
  743. ClientClass *pClientClass = NULL;
  744. ALIGN4 unsigned char data[CEventInfo::MAX_EVENT_DATA] ALIGN4_POST;
  745. bf_write toBuf( data, sizeof(data) );
  746. CEventInfo *ei = NULL;
  747. for (int i = 0; i < msg->m_nNumEntries; i++ )
  748. {
  749. float delay = 0.0f;
  750. if ( buffer.ReadOneBit() )
  751. {
  752. delay = (float)buffer.ReadSBitLong( 8 ) / 100.0f;
  753. }
  754. toBuf.Reset();
  755. if ( buffer.ReadOneBit() )
  756. {
  757. from = NULL; // full update
  758. classID = buffer.ReadUBitLong( m_nServerClassBits ); // classID
  759. // Look up the client class, etc.
  760. // Match the server classes to the client classes.
  761. pServerClass = m_pServerClasses ? &m_pServerClasses[ classID - 1 ] : NULL;
  762. if ( !pServerClass )
  763. {
  764. DevMsg("CL_QueueEvent: missing server class info for %i.\n", classID - 1 );
  765. return false;
  766. }
  767. // See if the client .dll has a handler for this class
  768. pClientClass = FindClientClass( pServerClass->m_ClassName );
  769. if ( !pClientClass || !pClientClass->m_pRecvTable )
  770. {
  771. DevMsg("CL_QueueEvent: missing client receive table for %s.\n", pServerClass->m_ClassName );
  772. return false;
  773. }
  774. RecvTable_MergeDeltas( pClientClass->m_pRecvTable, NULL, &buffer, &toBuf );
  775. }
  776. else
  777. {
  778. Assert( ei );
  779. unsigned int buffer_size = PAD_NUMBER( Bits2Bytes( ei->bits ), 4 );
  780. bf_read fromBuf( ei->pData, buffer_size );
  781. RecvTable_MergeDeltas( pClientClass->m_pRecvTable, &fromBuf, &buffer, &toBuf );
  782. }
  783. // Add a slot
  784. ei = &cl.events[ cl.events.AddToTail() ];
  785. Assert( ei );
  786. int size = Bits2Bytes(toBuf.GetNumBitsWritten() );
  787. ei->classID = classID;
  788. ei->fire_delay = fire_time + delay;
  789. ei->flags = flags;
  790. ei->pClientClass = pClientClass;
  791. ei->bits = toBuf.GetNumBitsWritten();
  792. // deltaBitsReader.ReadNextPropIndex reads uint32s, so make sure we alloc in 4-byte chunks.
  793. ei->pData = new byte[ ALIGN_VALUE( size, 4 ) ]; // copy raw data
  794. Q_memcpy( ei->pData, data, size );
  795. }
  796. return true;
  797. }
  798. #endif // swds