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.

2213 lines
62 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // 4-23-98
  6. // JOHN: implementation of interface between client-side DLL and game engine.
  7. // The cdll shouldn't have to know anything about networking or file formats.
  8. // This file is Win32-dependant
  9. //
  10. //=============================================================================//
  11. #include "client_pch.h"
  12. #include "getintersectingsurfaces_struct.h"
  13. #include "gl_model_private.h"
  14. #include "surfinfo.h"
  15. #include "vstdlib/random.h"
  16. #include "cdll_int.h"
  17. #include "cmodel_engine.h"
  18. #include "tmessage.h"
  19. #include "console.h"
  20. #include "snd_audio_source.h"
  21. #include <vgui_controls/Controls.h>
  22. #include <vgui/IInput.h>
  23. #include "iengine.h"
  24. #include "keys.h"
  25. #include "con_nprint.h"
  26. #include "tier0/vprof.h"
  27. #include "sound.h"
  28. #include "gl_rmain.h"
  29. #include "proto_version.h"
  30. #include "client_class.h"
  31. #include "gl_rsurf.h"
  32. #include "server.h"
  33. #include "r_local.h"
  34. #include "lightcache.h"
  35. #include "gl_matsysiface.h"
  36. #include "materialsystem/imaterialsystemhardwareconfig.h"
  37. #include "materialsystem/materialsystem_config.h"
  38. #include "materialsystem/imaterial.h"
  39. #include "materialsystem/imaterialvar.h"
  40. #include "materialsystem/itexture.h"
  41. #include "istudiorender.h"
  42. #include "l_studio.h"
  43. #include "voice.h"
  44. #include "enginestats.h"
  45. #include "testscriptmgr.h"
  46. #include "r_areaportal.h"
  47. #include "host.h"
  48. #include "host_cmd.h"
  49. #include "vox.h"
  50. #include "iprediction.h"
  51. #include "icliententitylist.h"
  52. #include "eiface.h"
  53. #include "ivguicenterprint.h"
  54. #include "engine/IClientLeafSystem.h"
  55. #include "dt_recv_eng.h"
  56. #include <vgui/IVGui.h>
  57. #include "sys_dll.h"
  58. #include "vphysics_interface.h"
  59. #include "materialsystem/imesh.h"
  60. #include "IOcclusionSystem.h"
  61. #include "filesystem_engine.h"
  62. #include "tier0/icommandline.h"
  63. #include "client_textmessage.h"
  64. #include "host_saverestore.h"
  65. #include "cl_main.h"
  66. #include "demo.h"
  67. #include "appframework/ilaunchermgr.h"
  68. #include "vgui_baseui_interface.h"
  69. #include "LocalNetworkBackdoor.h"
  70. #include "lightcache.h"
  71. #include "vgui/ISystem.h"
  72. #include "ivideomode.h"
  73. #include "icolorcorrectiontools.h"
  74. #include "toolframework/itoolframework.h"
  75. #include "engine/view_sharedv1.h"
  76. #include "view.h"
  77. #include "game/client/iclientrendertargets.h"
  78. #include "tier2/tier2.h"
  79. #include "matchmaking.h"
  80. #include "inputsystem/iinputsystem.h"
  81. #include "iachievementmgr.h"
  82. #include "profile.h"
  83. #include "cl_steamauth.h"
  84. #include "download.h"
  85. #include "replay/iclientreplay.h"
  86. #include "demofile.h"
  87. #include "igame.h"
  88. #include "iclientvirtualreality.h"
  89. #include "sourcevr/isourcevirtualreality.h"
  90. #include "cl_check_process.h"
  91. #include "enginethreads.h"
  92. #if defined( REPLAY_ENABLED )
  93. #include "replay_internal.h"
  94. #include "replay/replaylib.h"
  95. #endif
  96. // memdbgon must be the last include file in a .cpp file!!!
  97. #include "tier0/memdbgon.h"
  98. //-----------------------------------------------------------------------------
  99. // forward declarations
  100. //-----------------------------------------------------------------------------
  101. IMaterial* BrushModel_GetLightingAndMaterial( const Vector &start,
  102. const Vector &end, Vector &diffuseLightColor, Vector &baseColor );
  103. const char *Key_NameForBinding( const char *pBinding );
  104. void CL_GetBackgroundLevelName( char *pszBackgroundName, int bufSize, bool bMapName );
  105. CreateInterfaceFn g_ClientFactory = NULL;
  106. extern CGlobalVars g_ServerGlobalVariables;
  107. //-----------------------------------------------------------------------------
  108. // globals
  109. //-----------------------------------------------------------------------------
  110. CSysModule *g_ClientDLLModule = NULL; // also used by materialproxyfactory.cpp
  111. bool g_bClientGameDLLGreaterThanV13;
  112. void AddIntersectingLeafSurfaces( mleaf_t *pLeaf, GetIntersectingSurfaces_Struct *pStruct )
  113. {
  114. SurfaceHandle_t *pHandle = &host_state.worldbrush->marksurfaces[pLeaf->firstmarksurface];
  115. for ( int iSurf=0; iSurf < pLeaf->nummarksurfaces; iSurf++ )
  116. {
  117. SurfaceHandle_t surfID = pHandle[iSurf];
  118. ASSERT_SURF_VALID( surfID );
  119. if ( MSurf_Flags(surfID) & SURFDRAW_SKY )
  120. continue;
  121. // Make sure we haven't already processed this one.
  122. bool foundSurf = false;
  123. for(int iTest=0; iTest < pStruct->m_nSetInfos; iTest++)
  124. {
  125. if(pStruct->m_pInfos[iTest].m_pEngineData == (void *)surfID)
  126. {
  127. foundSurf = true;
  128. break;
  129. }
  130. }
  131. if ( foundSurf )
  132. continue;
  133. // Make sure there's output room.
  134. if(pStruct->m_nSetInfos >= pStruct->m_nMaxInfos)
  135. return;
  136. SurfInfo *pOut = &pStruct->m_pInfos[pStruct->m_nSetInfos];
  137. pOut->m_nVerts = 0;
  138. pOut->m_pEngineData = (void *)surfID;
  139. // Build vertex list and bounding box.
  140. Vector vMin( 1000000.0f, 1000000.0f, 1000000.0f);
  141. Vector vMax(-1000000.0f, -1000000.0f, -1000000.0f);
  142. for(int iVert=0; iVert < MSurf_VertCount( surfID ); iVert++)
  143. {
  144. int vertIndex = pStruct->m_pModel->brush.pShared->vertindices[MSurf_FirstVertIndex( surfID ) + iVert];
  145. pOut->m_Verts[pOut->m_nVerts] = pStruct->m_pModel->brush.pShared->vertexes[vertIndex].position;
  146. vMin = vMin.Min(pOut->m_Verts[pOut->m_nVerts]);
  147. vMax = vMax.Max(pOut->m_Verts[pOut->m_nVerts]);
  148. ++pOut->m_nVerts;
  149. if(pOut->m_nVerts >= MAX_SURFINFO_VERTS)
  150. break;
  151. }
  152. // See if the sphere intersects the box.
  153. int iDim=0;
  154. for(; iDim < 3; iDim++)
  155. {
  156. if(((*pStruct->m_pCenter)[iDim]+pStruct->m_Radius) < vMin[iDim] ||
  157. ((*pStruct->m_pCenter)[iDim]-pStruct->m_Radius) > vMax[iDim])
  158. {
  159. break;
  160. }
  161. }
  162. if(iDim == 3)
  163. {
  164. // (Couldn't reject the sphere in the loop above).
  165. pOut->m_Plane = MSurf_GetForwardFacingPlane( surfID );
  166. ++pStruct->m_nSetInfos;
  167. }
  168. }
  169. }
  170. void GetIntersectingSurfaces_R(
  171. GetIntersectingSurfaces_Struct *pStruct,
  172. mnode_t *pNode
  173. )
  174. {
  175. if(pStruct->m_nSetInfos >= pStruct->m_nMaxInfos)
  176. return;
  177. // Ok, this is a leaf. Check its surfaces.
  178. if(pNode->contents >= 0)
  179. {
  180. mleaf_t *pLeaf = (mleaf_t*)pNode;
  181. if(pStruct->m_bOnlyVisible && pStruct->m_pCenterPVS)
  182. {
  183. if(pLeaf->cluster < 0)
  184. return;
  185. if(!(pStruct->m_pCenterPVS[pLeaf->cluster>>3] & (1 << (pLeaf->cluster&7))))
  186. return;
  187. }
  188. // First, add tris from displacements.
  189. for ( int i = 0; i < pLeaf->dispCount; i++ )
  190. {
  191. IDispInfo *pDispInfo = MLeaf_Disaplcement( pLeaf, i );
  192. pDispInfo->GetIntersectingSurfaces( pStruct );
  193. }
  194. // Next, add brush tris.
  195. AddIntersectingLeafSurfaces( pLeaf, pStruct );
  196. return;
  197. }
  198. // Recurse.
  199. float dot;
  200. cplane_t *plane = pNode->plane;
  201. if ( plane->type < 3 )
  202. {
  203. dot = (*pStruct->m_pCenter)[plane->type] - plane->dist;
  204. }
  205. else
  206. {
  207. dot = pStruct->m_pCenter->Dot(plane->normal) - plane->dist;
  208. }
  209. // Recurse into child nodes.
  210. if(dot > -pStruct->m_Radius)
  211. GetIntersectingSurfaces_R(pStruct, pNode->children[SIDE_FRONT]);
  212. if(dot < pStruct->m_Radius)
  213. GetIntersectingSurfaces_R(pStruct, pNode->children[SIDE_BACK]);
  214. }
  215. //-----------------------------------------------------------------------------
  216. // slow routine to draw a physics model
  217. // NOTE: very slow code!!! just for debugging!
  218. //-----------------------------------------------------------------------------
  219. void DebugDrawPhysCollide( const CPhysCollide *pCollide, IMaterial *pMaterial, matrix3x4_t& transform, const color32 &color, bool drawAxes )
  220. {
  221. if ( !pMaterial )
  222. {
  223. pMaterial = materials->FindMaterial("shadertest/wireframevertexcolor", TEXTURE_GROUP_OTHER);
  224. }
  225. CMatRenderContextPtr pRenderContext( materials );
  226. Vector *outVerts;
  227. int vertCount = physcollision->CreateDebugMesh( pCollide, &outVerts );
  228. if ( vertCount )
  229. {
  230. IMesh *pMesh = pRenderContext->GetDynamicMesh( true, NULL, NULL, pMaterial );
  231. CMeshBuilder meshBuilder;
  232. meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, vertCount/3 );
  233. for ( int j = 0; j < vertCount; j++ )
  234. {
  235. Vector out;
  236. VectorTransform( outVerts[j].Base(), transform, out.Base() );
  237. meshBuilder.Position3fv( out.Base() );
  238. meshBuilder.Color4ub( color.r, color.g, color.b, color.a );
  239. meshBuilder.TexCoord2f( 0, 0, 0 );
  240. meshBuilder.AdvanceVertex();
  241. }
  242. meshBuilder.End();
  243. pMesh->Draw();
  244. }
  245. physcollision->DestroyDebugMesh( vertCount, outVerts );
  246. // draw the axes
  247. if ( drawAxes )
  248. {
  249. Vector xaxis(10,0,0), yaxis(0,10,0), zaxis(0,0,10);
  250. Vector center;
  251. Vector out;
  252. MatrixGetColumn( transform, 3, center );
  253. IMesh *pMesh = pRenderContext->GetDynamicMesh( true, NULL, NULL, pMaterial );
  254. CMeshBuilder meshBuilder;
  255. meshBuilder.Begin( pMesh, MATERIAL_LINES, 3 );
  256. // X
  257. meshBuilder.Position3fv( center.Base() );
  258. meshBuilder.Color4ub( 255, 0, 0, 255 );
  259. meshBuilder.TexCoord2f( 0, 0, 0 );
  260. meshBuilder.AdvanceVertex();
  261. VectorTransform( xaxis.Base(), transform, out.Base() );
  262. meshBuilder.Position3fv( out.Base() );
  263. meshBuilder.Color4ub( 255, 0, 0, 255 );
  264. meshBuilder.TexCoord2f( 0, 0, 0 );
  265. meshBuilder.AdvanceVertex();
  266. // Y
  267. meshBuilder.Position3fv( center.Base() );
  268. meshBuilder.Color4ub( 0, 255, 0, 255 );
  269. meshBuilder.TexCoord2f( 0, 0, 0 );
  270. meshBuilder.AdvanceVertex();
  271. VectorTransform( yaxis.Base(), transform, out.Base() );
  272. meshBuilder.Position3fv( out.Base() );
  273. meshBuilder.Color4ub( 0, 255, 0, 255 );
  274. meshBuilder.TexCoord2f( 0, 0, 0 );
  275. meshBuilder.AdvanceVertex();
  276. // Z
  277. meshBuilder.Position3fv( center.Base() );
  278. meshBuilder.Color4ub( 0, 0, 255, 255 );
  279. meshBuilder.TexCoord2f( 0, 0, 0 );
  280. meshBuilder.AdvanceVertex();
  281. VectorTransform( zaxis.Base(), transform, out.Base() );
  282. meshBuilder.Position3fv( out.Base() );
  283. meshBuilder.Color4ub( 0, 0, 255, 255 );
  284. meshBuilder.TexCoord2f( 0, 0, 0 );
  285. meshBuilder.AdvanceVertex();
  286. meshBuilder.End();
  287. pMesh->Draw();
  288. }
  289. }
  290. //-----------------------------------------------------------------------------
  291. //
  292. // implementation of IVEngineHud
  293. //
  294. //-----------------------------------------------------------------------------
  295. // UNDONE: Move this to hud export code, subsume previous functions
  296. class CEngineClient : public IVEngineClient
  297. {
  298. public:
  299. CEngineClient();
  300. int GetIntersectingSurfaces(
  301. const model_t *model,
  302. const Vector &vCenter,
  303. const float radius,
  304. const bool bOnlyVisible,
  305. SurfInfo *pInfos,
  306. const int nMaxInfos);
  307. Vector GetLightForPoint(const Vector &pos, bool bClamp);
  308. Vector GetLightForPointFast(const Vector &pos, bool bClamp);
  309. const char *ParseFile( const char *data, char *token, int maxlen );
  310. virtual bool CopyLocalFile( const char *source, const char *destination );
  311. void GetScreenSize( int& w, int &h );
  312. void ServerCmd( const char *szCmdString, bool bReliable );
  313. void ClientCmd( const char *szCmdString );
  314. void ClientCmd_Unrestricted( const char *szCmdString );
  315. void SetRestrictServerCommands( bool bRestrict );
  316. void SetRestrictClientCommands( bool bRestrict );
  317. bool GetPlayerInfo( int ent_num, player_info_t *pinfo );
  318. client_textmessage_t *TextMessageGet( const char *pName );
  319. bool Con_IsVisible( void );
  320. int GetLocalPlayer( void );
  321. float GetLastTimeStamp( void );
  322. const model_t *LoadModel( const char *pName, bool bProp );
  323. void UnloadModel( const model_t *model, bool bProp );
  324. CSentence *GetSentence( CAudioSource *pAudioSource );
  325. float GetSentenceLength( CAudioSource *pAudioSource );
  326. bool IsStreaming( CAudioSource *pAudioSource ) const;
  327. void AddPhonemeFile( const char *pszPhonemeFile );
  328. // FIXME, move entirely to client .dll
  329. void GetViewAngles( QAngle& va );
  330. void SetViewAngles( QAngle& va );
  331. int GetMaxClients( void );
  332. void Key_Event( ButtonCode_t key, int down );
  333. const char *Key_LookupBinding( const char *pBinding );
  334. const char *Key_LookupBindingExact( const char *pBinding );
  335. const char *Key_BindingForKey( ButtonCode_t code );
  336. void StartKeyTrapMode( void );
  337. bool CheckDoneKeyTrapping( ButtonCode_t &key );
  338. bool IsInGame( void );
  339. bool IsConnected( void );
  340. bool IsDrawingLoadingImage( void );
  341. void Con_NPrintf( int pos, const char *fmt, ... );
  342. void Con_NXPrintf( const struct con_nprint_s *info, const char *fmt, ... );
  343. IMaterial *TraceLineMaterialAndLighting( const Vector &start, const Vector &end,
  344. Vector &diffuseLightColor, Vector &baseColor );
  345. int IsBoxVisible( const Vector& mins, const Vector& maxs );
  346. int IsBoxInViewCluster( const Vector& mins, const Vector& maxs );
  347. float Time();
  348. void Sound_ExtraUpdate( void );
  349. bool CullBox ( const Vector& mins, const Vector& maxs );
  350. const char *GetGameDirectory( void );
  351. const VMatrix& WorldToScreenMatrix();
  352. const VMatrix& WorldToViewMatrix();
  353. // Loads a game lump off disk
  354. int GameLumpVersion( int lumpId ) const;
  355. int GameLumpSize( int lumpId ) const;
  356. bool LoadGameLump( int lumpId, void* pBuffer, int size );
  357. // Returns the number of leaves in the level
  358. int LevelLeafCount() const;
  359. virtual ISpatialQuery* GetBSPTreeQuery();
  360. // Convert texlight to gamma...
  361. virtual void LinearToGamma( float* linear, float* gamma );
  362. // Get the lightstyle value
  363. virtual float LightStyleValue( int style );
  364. virtual void DrawPortals();
  365. // Computes light due to dynamic lighting at a point
  366. // If the normal isn't specified, then it'll return the maximum lighting
  367. virtual void ComputeDynamicLighting( Vector const& pt, Vector const* pNormal, Vector& color );
  368. // Computes light due to dynamic lighting at a point
  369. // If the normal isn't specified, then it'll return the maximum lighting
  370. // If pBoxColors is specified (it's an array of 6), then it'll copy the light contribution at each box side.
  371. virtual void ComputeLighting( const Vector& pt, const Vector* pNormal, bool bClamp, Vector& color, Vector *pBoxColors );
  372. // Returns the color of the ambient light
  373. virtual void GetAmbientLightColor( Vector& color );
  374. // Returns the dx support level
  375. virtual int GetDXSupportLevel();
  376. virtual bool SupportsHDR();
  377. virtual void Mat_Stub( IMaterialSystem *pMatSys );
  378. // menu display
  379. virtual void GetChapterName( char *pchBuff, int iMaxLength );
  380. virtual char const *GetLevelName( void );
  381. virtual int GetLevelVersion( void );
  382. virtual bool IsLevelMainMenuBackground( void );
  383. virtual void GetMainMenuBackgroundName( char *dest, int destlen );
  384. // Occlusion system control
  385. virtual void SetOcclusionParameters( const OcclusionParams_t &params );
  386. //-----------------------------------------------------------------------------
  387. // Purpose: Takes a trackerID and returns which player slot that user is in
  388. // returns 0 if no player found with that ID
  389. //-----------------------------------------------------------------------------
  390. virtual int GetPlayerForUserID(int userID);
  391. #if !defined( NO_VOICE )
  392. virtual struct IVoiceTweak_s *GetVoiceTweakAPI( void );
  393. #endif
  394. virtual void EngineStats_BeginFrame( void );
  395. virtual void EngineStats_EndFrame( void );
  396. virtual void FireEvents();
  397. virtual void CheckPoint( const char *pName );
  398. virtual int GetLeavesArea( int *pLeaves, int nLeaves );
  399. virtual bool DoesBoxTouchAreaFrustum( const Vector &mins, const Vector &maxs, int iArea );
  400. // Sets the hearing origin
  401. virtual void SetAudioState( const AudioState_t &audioState );
  402. //-----------------------------------------------------------------------------
  403. //
  404. // Sentence API
  405. //
  406. //-----------------------------------------------------------------------------
  407. virtual int SentenceGroupPick( int groupIndex, char *name, int nameLen );
  408. virtual int SentenceGroupPickSequential( int groupIndex, char *name, int nameLen, int sentenceIndex, int reset );
  409. virtual int SentenceIndexFromName( const char *pSentenceName );
  410. virtual const char *SentenceNameFromIndex( int sentenceIndex );
  411. virtual int SentenceGroupIndexFromName( const char *pGroupName );
  412. virtual const char *SentenceGroupNameFromIndex( int groupIndex );
  413. virtual float SentenceLength( int sentenceIndex );
  414. virtual void DebugDrawPhysCollide( const CPhysCollide *pCollide, IMaterial *pMaterial, matrix3x4_t& transform, const color32 &color );
  415. // Activates/deactivates an occluder...
  416. virtual void ActivateOccluder( int nOccluderIndex, bool bActive );
  417. virtual bool IsOccluded( const Vector &vecAbsMins, const Vector &vecAbsMaxs );
  418. virtual void *SaveAllocMemory( size_t num, size_t size );
  419. virtual void SaveFreeMemory( void *pSaveMem );
  420. virtual INetChannelInfo *GetNetChannelInfo( void );
  421. virtual bool IsPlayingDemo( void );
  422. virtual bool IsRecordingDemo( void );
  423. virtual bool IsPlayingTimeDemo( void );
  424. virtual int GetDemoRecordingTick( void );
  425. virtual int GetDemoPlaybackTick( void );
  426. virtual int GetDemoPlaybackStartTick( void );
  427. virtual float GetDemoPlaybackTimeScale( void );
  428. virtual int GetDemoPlaybackTotalTicks( void );
  429. virtual bool IsPaused( void );
  430. virtual bool IsTakingScreenshot( void );
  431. virtual bool IsHLTV( void );
  432. virtual void GetVideoModes( int &nCount, vmode_s *&pModes );
  433. virtual void GetUILanguage( char *dest, int destlen );
  434. // Can skybox be seen from a particular point?
  435. virtual SkyboxVisibility_t IsSkyboxVisibleFromPoint( const Vector &vecPoint );
  436. virtual const char* GetMapEntitiesString();
  437. virtual bool IsInEditMode( void );
  438. virtual bool IsInCommentaryMode( void );
  439. virtual float GetScreenAspectRatio();
  440. virtual unsigned int GetEngineBuildNumber() { return PROTOCOL_VERSION; }
  441. virtual const char * GetProductVersionString() { return GetSteamInfIDVersionInfo().szVersionString; }
  442. virtual void GrabPreColorCorrectedFrame( int x, int y, int width, int height );
  443. virtual bool IsHammerRunning( ) const;
  444. // Stuffs the cmd into the buffer & executes it immediately (vs ClientCmd() which executes it next frame)
  445. virtual void ExecuteClientCmd( const char *szCmdString );
  446. virtual bool MapHasHDRLighting( void) ;
  447. virtual int GetAppID();
  448. virtual void SetOverlayBindProxy( int iOverlayID, void *pBindProxy );
  449. virtual bool CopyFrameBufferToMaterial( const char *pMaterialName );
  450. // Matchmaking
  451. void ChangeTeam( const char *pTeamName );
  452. virtual void ReadConfiguration( const bool readDefault = false );
  453. virtual void SetAchievementMgr( IAchievementMgr *pAchievementMgr );
  454. virtual IAchievementMgr *GetAchievementMgr();
  455. virtual bool MapLoadFailed( void );
  456. virtual void SetMapLoadFailed( bool bState );
  457. virtual bool IsLowViolence();
  458. virtual const char *GetMostRecentSaveGame( void );
  459. virtual void SetMostRecentSaveGame( const char *lpszFilename );
  460. virtual void StartXboxExitingProcess();
  461. virtual bool IsSaveInProgress();
  462. virtual uint OnStorageDeviceAttached( void );
  463. virtual void OnStorageDeviceDetached( void );
  464. virtual void ResetDemoInterpolation( void );
  465. virtual bool REMOVED_SteamRefreshLogin( const char *password, bool isSecure ) { return false; }
  466. virtual bool REMOVED_SteamProcessCall( bool & finished ) { return false; }
  467. virtual void SetGamestatsData( CGamestatsData *pGamestatsData );
  468. virtual CGamestatsData *GetGamestatsData();
  469. #if defined( USE_SDL )
  470. virtual void GetMouseDelta( int &x, int &y, bool bIgnoreNextMouseDelta );
  471. #endif
  472. virtual void ServerCmdKeyValues( KeyValues *pKeyValues );
  473. virtual bool IsSkippingPlayback( void );
  474. virtual bool IsLoadingDemo( void );
  475. virtual bool IsPlayingDemoALocallyRecordedDemo();
  476. virtual uint GetProtocolVersion( void );
  477. virtual bool IsWindowedMode( void );
  478. virtual void FlashWindow();
  479. virtual int GetClientVersion() const; // engines build
  480. virtual bool IsActiveApp();
  481. virtual void DisconnectInternal();
  482. virtual int GetInstancesRunningCount( );
  483. virtual float GetPausedExpireTime( void ) OVERRIDE;
  484. virtual bool StartDemoRecording( const char *pszFilename, const char *pszFolder = NULL );
  485. virtual void StopDemoRecording( void );
  486. virtual void TakeScreenshot( const char *pszFilename, const char *pszFolder = NULL );
  487. };
  488. //-----------------------------------------------------------------------------
  489. // Singleton
  490. //-----------------------------------------------------------------------------
  491. static CEngineClient s_VEngineClient;
  492. IVEngineClient *engineClient = &s_VEngineClient;
  493. EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CEngineClient, IVEngineClient, VENGINE_CLIENT_INTERFACE_VERSION, s_VEngineClient );
  494. EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CEngineClient, IVEngineClient013, VENGINE_CLIENT_INTERFACE_VERSION_13, s_VEngineClient );
  495. //-----------------------------------------------------------------------------
  496. // Constructor
  497. //-----------------------------------------------------------------------------
  498. CEngineClient::CEngineClient()
  499. {
  500. }
  501. int CEngineClient::GetIntersectingSurfaces(
  502. const model_t *model,
  503. const Vector &vCenter,
  504. const float radius,
  505. const bool bOnlyVisible,
  506. SurfInfo *pInfos,
  507. const int nMaxInfos)
  508. {
  509. if ( !model )
  510. return 0;
  511. byte pvs[MAX_MAP_LEAFS/8];
  512. GetIntersectingSurfaces_Struct theStruct;
  513. theStruct.m_pModel = ( model_t * )model;
  514. theStruct.m_pCenter = &vCenter;
  515. theStruct.m_pCenterPVS = CM_Vis( pvs, sizeof(pvs), CM_LeafCluster( CM_PointLeafnum( vCenter ) ), DVIS_PVS );
  516. theStruct.m_Radius = radius;
  517. theStruct.m_bOnlyVisible = bOnlyVisible;
  518. theStruct.m_pInfos = pInfos;
  519. theStruct.m_nMaxInfos = nMaxInfos;
  520. theStruct.m_nSetInfos = 0;
  521. // Go down the BSP.
  522. GetIntersectingSurfaces_R(
  523. &theStruct,
  524. &model->brush.pShared->nodes[ model->brush.firstnode ] );
  525. return theStruct.m_nSetInfos;
  526. }
  527. Vector CEngineClient::GetLightForPoint(const Vector &pos, bool bClamp)
  528. {
  529. Vector vRet;
  530. ComputeLighting( pos, NULL, bClamp, vRet, NULL );
  531. return vRet;
  532. }
  533. Vector CEngineClient::GetLightForPointFast(const Vector &pos, bool bClamp)
  534. {
  535. Vector vRet;
  536. int leafIndex = CM_PointLeafnum(pos);
  537. vRet.Init();
  538. Vector cube[6];
  539. Mod_LeafAmbientColorAtPos( cube, pos, leafIndex );
  540. for ( int i = 0; i < 6; i++ )
  541. {
  542. vRet.x = fpmax(vRet.x, cube[i].x );
  543. vRet.y = fpmax(vRet.y, cube[i].y );
  544. vRet.z = fpmax(vRet.z, cube[i].z );
  545. }
  546. if ( bClamp )
  547. {
  548. if ( vRet.x > 1.0f )
  549. vRet.x = 1.0f;
  550. if ( vRet.y > 1.0f )
  551. vRet.y = 1.0f;
  552. if ( vRet.z > 1.0f )
  553. vRet.z = 1.0f;
  554. }
  555. return vRet;
  556. }
  557. const char *CEngineClient::ParseFile( const char *data, char *token, int maxlen )
  558. {
  559. return ::COM_ParseFile( data, token, maxlen );
  560. }
  561. bool CEngineClient::CopyLocalFile( const char *source, const char *destination )
  562. {
  563. return ::COM_CopyFile( source, destination );
  564. }
  565. void CEngineClient::GetScreenSize( int& w, int &h )
  566. {
  567. CMatRenderContextPtr pRenderContext( materials );
  568. pRenderContext->GetWindowSize( w, h );
  569. }
  570. void CEngineClient::ServerCmd( const char *szCmdString, bool bReliable )
  571. {
  572. // info handling
  573. char buf[255];
  574. Q_snprintf( buf, sizeof( buf ), "cmd %s", szCmdString );
  575. CCommand args;
  576. args.Tokenize( buf );
  577. Cmd_ForwardToServer( args, bReliable );
  578. }
  579. void CEngineClient::ClientCmd( const char *szCmdString )
  580. {
  581. // Check that we can add the two execution markers
  582. if ( cl.m_bRestrictClientCommands && !Cbuf_HasRoomForExecutionMarkers( 2 ) )
  583. {
  584. AssertMsg( false, "CEngineClient::ClientCmd called but there is no room for the execution markers. Ignoring command." );
  585. return;
  586. }
  587. // Only let them run commands marked with FCVAR_CLIENTCMD_CAN_EXECUTE.
  588. if ( cl.m_bRestrictClientCommands )
  589. Cbuf_AddTextWithMarkers( eCmdExecutionMarker_Enable_FCVAR_CLIENTCMD_CAN_EXECUTE, szCmdString, eCmdExecutionMarker_Disable_FCVAR_CLIENTCMD_CAN_EXECUTE );
  590. else
  591. Cbuf_AddText( szCmdString );
  592. }
  593. void CEngineClient::ClientCmd_Unrestricted( const char *szCmdString )
  594. {
  595. Cbuf_AddText( szCmdString );
  596. }
  597. void CEngineClient::SetRestrictServerCommands( bool bRestrict )
  598. {
  599. cl.m_bRestrictServerCommands = bRestrict;
  600. }
  601. void CEngineClient::SetRestrictClientCommands( bool bRestrict )
  602. {
  603. cl.m_bRestrictClientCommands = bRestrict;
  604. }
  605. void CEngineClient::ExecuteClientCmd( const char *szCmdString )
  606. {
  607. Cbuf_AddText( szCmdString );
  608. Cbuf_Execute();
  609. }
  610. bool CEngineClient::GetPlayerInfo( int ent_num, player_info_t *pinfo )
  611. {
  612. ent_num--; // player list if offset by 1 from ents
  613. if ( ent_num >= cl.m_nMaxClients || ent_num < 0 )
  614. {
  615. Q_memset( pinfo, 0, sizeof( player_info_t ) );
  616. return false;
  617. }
  618. Assert( cl.m_pUserInfoTable );
  619. if ( !cl.m_pUserInfoTable )
  620. {
  621. Q_memset( pinfo, 0, sizeof( player_info_t ) );
  622. return false;
  623. }
  624. Assert( ent_num < cl.m_pUserInfoTable->GetNumStrings() );
  625. if ( ent_num >= cl.m_pUserInfoTable->GetNumStrings() )
  626. {
  627. Q_memset( pinfo, 0, sizeof( player_info_t ) );
  628. return false;
  629. }
  630. int cubPlayerInfo;
  631. player_info_t *pi = (player_info_t*) cl.m_pUserInfoTable->GetStringUserData( ent_num, &cubPlayerInfo );
  632. if ( !pi || cubPlayerInfo < sizeof( player_info_t ) )
  633. {
  634. Q_memset( pinfo, 0, sizeof( player_info_t ) );
  635. return false;
  636. }
  637. Q_memcpy( pinfo, pi, sizeof( player_info_t ) );
  638. // Fixup from network order (little endian)
  639. CByteswap byteswap;
  640. byteswap.SetTargetBigEndian( false );
  641. byteswap.SwapFieldsToTargetEndian( pinfo );
  642. return true;
  643. }
  644. client_textmessage_t *CEngineClient::TextMessageGet( const char *pName )
  645. {
  646. return ::TextMessageGet( pName );
  647. }
  648. bool CEngineClient::Con_IsVisible( void )
  649. {
  650. return ::Con_IsVisible();
  651. }
  652. int CEngineClient::GetLocalPlayer( void )
  653. {
  654. return cl.m_nPlayerSlot + 1;
  655. }
  656. float CEngineClient::GetLastTimeStamp( void )
  657. {
  658. return cl.m_flLastServerTickTime;
  659. }
  660. bool CEngineClient::MapHasHDRLighting( void)
  661. {
  662. return modelloader->LastLoadedMapHasHDRLighting();
  663. }
  664. const model_t *CEngineClient::LoadModel( const char *pName, bool bProp )
  665. {
  666. return modelloader->GetModelForName( pName, bProp ? IModelLoader::FMODELLOADER_DETAILPROP : IModelLoader::FMODELLOADER_CLIENTDLL );
  667. }
  668. CSentence *CEngineClient::GetSentence( CAudioSource *pAudioSource )
  669. {
  670. if (pAudioSource)
  671. {
  672. return pAudioSource->GetSentence();
  673. }
  674. return NULL;
  675. }
  676. void AddPhonemesFromFile( const char *pszFileName );
  677. void CEngineClient::AddPhonemeFile( const char *pszPhonemeFile )
  678. {
  679. AddPhonemesFromFile( pszPhonemeFile );
  680. }
  681. float CEngineClient::GetSentenceLength( CAudioSource *pAudioSource )
  682. {
  683. if (pAudioSource && pAudioSource->SampleRate() > 0 )
  684. {
  685. float length = (float)pAudioSource->SampleCount() / (float)pAudioSource->SampleRate();
  686. return length;
  687. }
  688. return 0.0f;
  689. }
  690. bool CEngineClient::IsStreaming( CAudioSource *pAudioSource ) const
  691. {
  692. if ( pAudioSource )
  693. {
  694. return pAudioSource->IsStreaming();
  695. }
  696. return false;
  697. }
  698. // FIXME, move entirely to client .dll
  699. void CEngineClient::GetViewAngles( QAngle& va )
  700. {
  701. VectorCopy( cl.viewangles, va );
  702. }
  703. void CEngineClient::SetViewAngles( QAngle& va )
  704. {
  705. cl.viewangles.x = AngleNormalize( va.x );
  706. cl.viewangles.y = AngleNormalize( va.y );
  707. cl.viewangles.z = AngleNormalize( va.z );
  708. Assert( !IS_NAN(cl.viewangles.x ) );
  709. Assert( !IS_NAN(cl.viewangles.y ) );
  710. Assert( !IS_NAN(cl.viewangles.z ) );
  711. }
  712. int CEngineClient::GetMaxClients( void )
  713. {
  714. return cl.m_nMaxClients;
  715. }
  716. void CEngineClient::SetMapLoadFailed( bool bState )
  717. {
  718. g_ServerGlobalVariables.bMapLoadFailed = bState;
  719. }
  720. bool CEngineClient::MapLoadFailed( void )
  721. {
  722. return g_ServerGlobalVariables.bMapLoadFailed;
  723. }
  724. void CEngineClient::ReadConfiguration( const bool readDefault /*= false*/ )
  725. {
  726. Host_ReadConfiguration();
  727. }
  728. const char *CEngineClient::Key_LookupBinding( const char *pBinding )
  729. {
  730. return ::Key_NameForBinding( pBinding );
  731. }
  732. const char *CEngineClient::Key_LookupBindingExact( const char *pBinding )
  733. {
  734. return ::Key_NameForBindingExact( pBinding );
  735. }
  736. const char *CEngineClient::Key_BindingForKey( ButtonCode_t code )
  737. {
  738. return ::Key_BindingForKey( code );
  739. }
  740. void CEngineClient::StartKeyTrapMode( void )
  741. {
  742. Key_StartTrapMode();
  743. }
  744. bool CEngineClient::CheckDoneKeyTrapping( ButtonCode_t &code )
  745. {
  746. return Key_CheckDoneTrapping( code );
  747. }
  748. bool CEngineClient::IsInGame( void )
  749. {
  750. return cl.IsActive();
  751. }
  752. bool CEngineClient::IsConnected( void )
  753. {
  754. return cl.IsConnected();
  755. }
  756. bool CEngineClient::IsDrawingLoadingImage( void )
  757. {
  758. return scr_drawloading;
  759. }
  760. void CEngineClient::Con_NPrintf( int pos, const char *fmt, ... )
  761. {
  762. va_list argptr;
  763. char text[4096];
  764. va_start (argptr, fmt);
  765. Q_vsnprintf(text, sizeof( text ), fmt, argptr);
  766. va_end (argptr);
  767. ::Con_NPrintf( pos, "%s", text );
  768. }
  769. void CEngineClient::Con_NXPrintf( const struct con_nprint_s *info, const char *fmt, ... )
  770. {
  771. va_list argptr;
  772. char text[4096];
  773. va_start (argptr, fmt);
  774. Q_vsnprintf(text, sizeof( text ), fmt, argptr);
  775. va_end (argptr);
  776. ::Con_NXPrintf( info, "%s", text );
  777. }
  778. IMaterial *CEngineClient::TraceLineMaterialAndLighting( const Vector &start, const Vector &end,
  779. Vector &diffuseLightColor, Vector &baseColor )
  780. {
  781. return BrushModel_GetLightingAndMaterial( start, end, diffuseLightColor, baseColor );
  782. }
  783. int CEngineClient::IsBoxVisible( const Vector& mins, const Vector& maxs )
  784. {
  785. return CM_BoxVisible( mins, maxs, Map_VisCurrent(), CM_ClusterPVSSize() );
  786. }
  787. int CEngineClient::IsBoxInViewCluster( const Vector& mins, const Vector& maxs )
  788. {
  789. // See comments in Map_VisCurrentCluster for why we might get a negative number.
  790. int curCluster = Map_VisCurrentCluster();
  791. if ( curCluster < 0 )
  792. return false;
  793. byte pvs[MAX_MAP_LEAFS/8];
  794. const byte *ppvs = CM_Vis( pvs, sizeof(pvs), curCluster, DVIS_PVS );
  795. return CM_BoxVisible(mins, maxs, ppvs, sizeof(pvs) );
  796. }
  797. float CEngineClient::Time()
  798. {
  799. return Sys_FloatTime();
  800. }
  801. void CEngineClient::Sound_ExtraUpdate( void )
  802. {
  803. // On xbox this is not necessary except for long pauses, so unhook this one
  804. if ( IsX360() )
  805. return;
  806. VPROF_BUDGET( "CEngineClient::Sound_ExtraUpdate()", VPROF_BUDGETGROUP_OTHER_SOUND );
  807. S_ExtraUpdate();
  808. }
  809. bool CEngineClient::CullBox ( const Vector& mins, const Vector& maxs )
  810. {
  811. return R_CullBoxSkipNear( mins, maxs, g_Frustum );
  812. }
  813. const char *CEngineClient::GetGameDirectory( void )
  814. {
  815. return com_gamedir;
  816. }
  817. const VMatrix& CEngineClient::WorldToScreenMatrix()
  818. {
  819. // FIXME: this is only valid if we're currently rendering. If not, it should use the player, or it really should pass one in.
  820. return g_EngineRenderer->WorldToScreenMatrix();
  821. }
  822. const VMatrix& CEngineClient::WorldToViewMatrix()
  823. {
  824. // FIXME: this is only valid if we're currently rendering. If not, it should use the player, or it really should pass one in.
  825. return g_EngineRenderer->ViewMatrix();
  826. }
  827. // Loads a game lump off disk
  828. int CEngineClient::GameLumpVersion( int lumpId ) const
  829. {
  830. return Mod_GameLumpVersion( lumpId );
  831. }
  832. int CEngineClient::GameLumpSize( int lumpId ) const
  833. {
  834. return Mod_GameLumpSize( lumpId );
  835. }
  836. bool CEngineClient::LoadGameLump( int lumpId, void* pBuffer, int size )
  837. {
  838. return Mod_LoadGameLump( lumpId, pBuffer, size );
  839. }
  840. // Returns the number of leaves in the level
  841. int CEngineClient::LevelLeafCount() const
  842. {
  843. return host_state.worldbrush->numleafs;
  844. }
  845. ISpatialQuery* CEngineClient::GetBSPTreeQuery()
  846. {
  847. return g_pToolBSPTree;
  848. }
  849. // Convert texlight to gamma...
  850. void CEngineClient::LinearToGamma( float* linear, float* gamma )
  851. {
  852. gamma[0] = LinearToTexture( linear[0] ) / 255.0f;
  853. gamma[1] = LinearToTexture( linear[1] ) / 255.0f;
  854. gamma[2] = LinearToTexture( linear[2] ) / 255.0f;
  855. }
  856. // Get the lightstyle value
  857. float CEngineClient::LightStyleValue( int style )
  858. {
  859. return ::LightStyleValue( style );
  860. }
  861. void CEngineClient::DrawPortals()
  862. {
  863. R_DrawPortals();
  864. }
  865. // Computes light due to dynamic lighting at a point
  866. // If the normal isn't specified, then it'll return the maximum lighting
  867. void CEngineClient::ComputeDynamicLighting( Vector const& pt, Vector const* pNormal, Vector& color )
  868. {
  869. ::ComputeDynamicLighting( pt, pNormal, color );
  870. }
  871. // Computes light due to dynamic lighting at a point
  872. // If the normal isn't specified, then it'll return the maximum lighting
  873. void CEngineClient::ComputeLighting( const Vector& pt, const Vector* pNormal, bool bClamp, Vector& color, Vector *pBoxColors )
  874. {
  875. ::ComputeLighting( pt, pNormal, bClamp, color, pBoxColors );
  876. }
  877. // Returns the color of the ambient light
  878. void CEngineClient::GetAmbientLightColor( Vector& color )
  879. {
  880. dworldlight_t* pWorldLight = FindAmbientLight();
  881. if (!pWorldLight)
  882. color.Init( 0, 0, 0 );
  883. else
  884. VectorCopy( pWorldLight->intensity, color );
  885. }
  886. // Returns the dx support level
  887. int CEngineClient::GetDXSupportLevel()
  888. {
  889. return g_pMaterialSystemHardwareConfig->GetDXSupportLevel();
  890. }
  891. bool CEngineClient::SupportsHDR()
  892. {
  893. // deprecated.
  894. // Assert( 0 );
  895. return false;
  896. }
  897. void CEngineClient::Mat_Stub( IMaterialSystem *pMatSys )
  898. {
  899. materials = pMatSys;
  900. // Pass the call to the model renderer.
  901. if ( g_pStudioRender )
  902. g_pStudioRender->Mat_Stub( pMatSys );
  903. }
  904. void CEngineClient::GetChapterName( char *pchBuff, int iMaxLength )
  905. {
  906. serverGameDLL->GetSaveComment( pchBuff, iMaxLength, 0.0f, 0.0f, true );
  907. }
  908. char const *CEngineClient::GetLevelName( void )
  909. {
  910. if ( sv.IsDedicated() )
  911. {
  912. return "Dedicated Server";
  913. }
  914. else if ( !cl.IsConnected() )
  915. {
  916. return "";
  917. }
  918. return cl.m_szLevelFileName;
  919. }
  920. int CEngineClient::GetLevelVersion( void )
  921. {
  922. return g_ServerGlobalVariables.mapversion;
  923. }
  924. bool CEngineClient::IsLevelMainMenuBackground( void )
  925. {
  926. return sv.IsLevelMainMenuBackground();
  927. }
  928. void CEngineClient::GetMainMenuBackgroundName( char *dest, int destlen )
  929. {
  930. CL_GetBackgroundLevelName( dest, destlen, false );
  931. }
  932. // Occlusion system control
  933. void CEngineClient::SetOcclusionParameters( const OcclusionParams_t &params )
  934. {
  935. OcclusionSystem()->SetOcclusionParameters( params.m_flMaxOccludeeArea, params.m_flMinOccluderArea );
  936. }
  937. //-----------------------------------------------------------------------------
  938. // Purpose: Takes a trackerID and returns which player slot that user is in
  939. // returns 0 if no player found with that ID
  940. //-----------------------------------------------------------------------------
  941. int CEngineClient::GetPlayerForUserID(int userID)
  942. {
  943. if ( !cl.m_pUserInfoTable )
  944. return 0;
  945. // We are occasionally getting crashes here where it looks like cl.m_nMaxClients
  946. // is larger than the number of items in cl.m_pUserInfoTable. Callstack:
  947. // engine.dll CEngineClient::GetPlayerForUserID
  948. // client.dll CTFHudDeathNotice::OnGameEvent
  949. // client.dll CHudBaseDeathNotice::FireGameEvent
  950. // client.dll CTFHudDeathNotice::FireGameEvent
  951. // engine.dll CGameEventManager::FireEventIntern
  952. // engine.dll CGameEventManager::FireEventClientSide
  953. // engine.dll CClientState::ProcessGameEvent
  954. // So add check to make sure we don't go over m_pUserInfoTable size.
  955. int nMaxClients = Min( cl.m_nMaxClients, cl.m_pUserInfoTable->GetNumStrings() );
  956. for ( int i = 0; i < nMaxClients; i++ )
  957. {
  958. player_info_t *pi = (player_info_t*) cl.m_pUserInfoTable->GetStringUserData( i, NULL );
  959. if ( !pi )
  960. continue;
  961. // Fixup from network order (little endian)
  962. if ( LittleLong( pi->userID ) == userID )
  963. {
  964. // return as entity index
  965. return (i+1);
  966. }
  967. }
  968. return 0;
  969. }
  970. #if !defined( NO_VOICE )
  971. struct IVoiceTweak_s *CEngineClient::GetVoiceTweakAPI( void )
  972. {
  973. return &g_VoiceTweakAPI;
  974. }
  975. #endif
  976. void CEngineClient::EngineStats_BeginFrame( void )
  977. {
  978. g_EngineStats.BeginFrame();
  979. }
  980. void CEngineClient::EngineStats_EndFrame( void )
  981. {
  982. g_EngineStats.EndFrame();
  983. }
  984. void CEngineClient::FireEvents()
  985. {
  986. // Run any events queued up for this frame
  987. CL_FireEvents();
  988. }
  989. void CEngineClient::CheckPoint( const char *pName )
  990. {
  991. GetTestScriptMgr()->CheckPoint( pName );
  992. }
  993. int CEngineClient::GetLeavesArea( int *pLeaves, int nLeaves )
  994. {
  995. if ( nLeaves == 0 )
  996. return -1;
  997. int iArea = host_state.worldbrush->leafs[pLeaves[0]].area;
  998. for ( int i=1; i < nLeaves; i++ )
  999. {
  1000. int iTestArea = host_state.worldbrush->leafs[pLeaves[i]].area;
  1001. if ( iTestArea != iArea )
  1002. return -1;
  1003. }
  1004. return iArea;
  1005. }
  1006. bool CEngineClient::DoesBoxTouchAreaFrustum( const Vector &mins, const Vector &maxs, int iArea )
  1007. {
  1008. const Frustum_t *pFrustum = GetAreaFrustum( iArea );
  1009. return !R_CullBoxSkipNear( mins, maxs, *pFrustum );
  1010. }
  1011. //-----------------------------------------------------------------------------
  1012. // Sets the hearing origin
  1013. //-----------------------------------------------------------------------------
  1014. void CEngineClient::SetAudioState( const AudioState_t &audioState )
  1015. {
  1016. Host_SetAudioState( audioState );
  1017. }
  1018. //-----------------------------------------------------------------------------
  1019. //
  1020. // Sentence API
  1021. //
  1022. //-----------------------------------------------------------------------------
  1023. int CEngineClient::SentenceGroupPick( int groupIndex, char *name, int nameLen )
  1024. {
  1025. return VOX_GroupPick( groupIndex, name, nameLen );
  1026. }
  1027. int CEngineClient::SentenceGroupPickSequential( int groupIndex, char *name, int nameLen, int sentenceIndex, int reset )
  1028. {
  1029. return VOX_GroupPickSequential( groupIndex, name, nameLen, sentenceIndex, reset );
  1030. }
  1031. int CEngineClient::SentenceIndexFromName( const char *pSentenceName )
  1032. {
  1033. int sentenceIndex = -1;
  1034. VOX_LookupString( pSentenceName, &sentenceIndex );
  1035. return sentenceIndex;
  1036. }
  1037. const char *CEngineClient::SentenceNameFromIndex( int sentenceIndex )
  1038. {
  1039. return VOX_SentenceNameFromIndex( sentenceIndex );
  1040. }
  1041. int CEngineClient::SentenceGroupIndexFromName( const char *pGroupName )
  1042. {
  1043. return VOX_GroupIndexFromName( pGroupName );
  1044. }
  1045. const char *CEngineClient::SentenceGroupNameFromIndex( int groupIndex )
  1046. {
  1047. return VOX_GroupNameFromIndex( groupIndex );
  1048. }
  1049. float CEngineClient::SentenceLength( int sentenceIndex )
  1050. {
  1051. return VOX_SentenceLength( sentenceIndex );
  1052. }
  1053. void CEngineClient::DebugDrawPhysCollide( const CPhysCollide *pCollide, IMaterial *pMaterial, matrix3x4_t& transform, const color32 &color )
  1054. {
  1055. ::DebugDrawPhysCollide( pCollide, pMaterial, transform, color, false );
  1056. }
  1057. // Activates/deactivates an occluder...
  1058. void CEngineClient::ActivateOccluder( int nOccluderIndex, bool bActive )
  1059. {
  1060. OcclusionSystem()->ActivateOccluder( nOccluderIndex, bActive );
  1061. }
  1062. bool CEngineClient::IsOccluded( const Vector &vecAbsMins, const Vector &vecAbsMaxs )
  1063. {
  1064. return OcclusionSystem()->IsOccluded( vecAbsMins, vecAbsMaxs );
  1065. }
  1066. void *CEngineClient::SaveAllocMemory( size_t num, size_t size )
  1067. {
  1068. return ::SaveAllocMemory( num, size );
  1069. }
  1070. void CEngineClient::SaveFreeMemory( void *pSaveMem )
  1071. {
  1072. ::SaveFreeMemory( pSaveMem );
  1073. }
  1074. INetChannelInfo *CEngineClient::GetNetChannelInfo( void )
  1075. {
  1076. return (INetChannelInfo*)cl.m_NetChannel;
  1077. }
  1078. bool CEngineClient::IsPlayingDemo( void )
  1079. {
  1080. return demoplayer->IsPlayingBack();
  1081. }
  1082. bool CEngineClient::IsRecordingDemo( void )
  1083. {
  1084. return demorecorder->IsRecording();
  1085. }
  1086. bool CEngineClient::IsPlayingTimeDemo( void )
  1087. {
  1088. return demoplayer->IsPlayingTimeDemo();
  1089. }
  1090. bool CEngineClient::IsPaused( void )
  1091. {
  1092. return cl.IsPaused();
  1093. }
  1094. bool CEngineClient::IsTakingScreenshot( void )
  1095. {
  1096. return cl_takesnapshot;
  1097. }
  1098. int CEngineClient::GetDemoRecordingTick( void )
  1099. {
  1100. return demorecorder->GetRecordingTick();
  1101. }
  1102. int CEngineClient::GetDemoPlaybackTick( void )
  1103. {
  1104. return demoplayer->GetPlaybackTick();
  1105. }
  1106. int CEngineClient::GetDemoPlaybackStartTick( void )
  1107. {
  1108. return demoplayer->GetPlaybackStartTick();
  1109. }
  1110. float CEngineClient::GetDemoPlaybackTimeScale( void )
  1111. {
  1112. return demoplayer->GetPlaybackTimeScale();
  1113. }
  1114. int CEngineClient::GetDemoPlaybackTotalTicks( void )
  1115. {
  1116. return demoplayer->GetTotalTicks();
  1117. }
  1118. bool CEngineClient::IsHLTV( void )
  1119. {
  1120. return cl.ishltv;
  1121. }
  1122. void CEngineClient::GetVideoModes( int &nCount, vmode_s *&pModes )
  1123. {
  1124. nCount = videomode->GetModeCount();
  1125. pModes = videomode->GetMode( 0 );
  1126. }
  1127. void CEngineClient::GetUILanguage( char *dest, int destlen )
  1128. {
  1129. const char *pStr = cl_language.GetString();
  1130. if ( pStr )
  1131. {
  1132. V_strncpy( dest, pStr, destlen );
  1133. }
  1134. else if ( IsX360() )
  1135. {
  1136. dest[0] = 0;
  1137. }
  1138. }
  1139. //-----------------------------------------------------------------------------
  1140. // Can skybox be seen from a particular point?
  1141. //-----------------------------------------------------------------------------
  1142. SkyboxVisibility_t CEngineClient::IsSkyboxVisibleFromPoint( const Vector &vecPoint )
  1143. {
  1144. // In the mat_fullbright 1 case, it's always visible
  1145. // (we may have no lighting in the level, and vrad is where LEAF_FLAGS_SKY is computed)
  1146. if ( g_pMaterialSystemConfig->nFullbright == 1 )
  1147. return SKYBOX_3DSKYBOX_VISIBLE;
  1148. int nLeaf = CM_PointLeafnum( vecPoint );
  1149. int nFlags = GetCollisionBSPData()->map_leafs[nLeaf].flags;
  1150. if ( nFlags & LEAF_FLAGS_SKY )
  1151. return SKYBOX_3DSKYBOX_VISIBLE;
  1152. return ( nFlags & LEAF_FLAGS_SKY2D ) ? SKYBOX_2DSKYBOX_VISIBLE : SKYBOX_NOT_VISIBLE;
  1153. }
  1154. const char* CEngineClient::GetMapEntitiesString()
  1155. {
  1156. return CM_EntityString();
  1157. }
  1158. bool CEngineClient::IsInEditMode( void )
  1159. {
  1160. return g_bInEditMode;
  1161. }
  1162. bool CEngineClient::IsInCommentaryMode( void )
  1163. {
  1164. return g_bInCommentaryMode;
  1165. }
  1166. float CEngineClient::GetScreenAspectRatio()
  1167. {
  1168. return GetScreenAspect( );
  1169. }
  1170. int CEngineClient::GetAppID()
  1171. {
  1172. return GetSteamAppID();
  1173. }
  1174. void CEngineClient::SetOverlayBindProxy( int iOverlayID, void *pBindProxy )
  1175. {
  1176. OverlayMgr()->SetOverlayBindProxy( iOverlayID, pBindProxy );
  1177. }
  1178. void CEngineClient::ChangeTeam( const char *pTeamName )
  1179. {
  1180. g_pMatchmaking->ChangeTeam( pTeamName );
  1181. }
  1182. //-----------------------------------------------------------------------------
  1183. // Returns true if copy occured
  1184. //-----------------------------------------------------------------------------
  1185. bool CEngineClient::CopyFrameBufferToMaterial( const char *pMaterialName )
  1186. {
  1187. if ( !IsX360() )
  1188. {
  1189. // not for PC
  1190. Assert( 0 );
  1191. return false;
  1192. }
  1193. IMaterial *pMaterial = materials->FindMaterial( pMaterialName, TEXTURE_GROUP_OTHER );
  1194. if ( pMaterial->IsErrorMaterial() )
  1195. {
  1196. // unknown material
  1197. return false;
  1198. }
  1199. bool bFound;
  1200. IMaterialVar *pMaterialVar = pMaterial->FindVar( "$baseTexture", &bFound, false );
  1201. if ( !bFound || pMaterialVar->GetType() != MATERIAL_VAR_TYPE_TEXTURE )
  1202. {
  1203. // lack of expected $basetexture
  1204. return false;
  1205. }
  1206. ITexture *pTexture = pMaterialVar->GetTextureValue();
  1207. if ( !pTexture || !pTexture->IsRenderTarget() )
  1208. {
  1209. // base texture is not a render target
  1210. return false;
  1211. }
  1212. CMatRenderContextPtr pRenderContext( materials );
  1213. int width, height;
  1214. pRenderContext->GetRenderTargetDimensions( width, height );
  1215. if ( width != pTexture->GetActualWidth() || height != pTexture->GetActualHeight() )
  1216. {
  1217. // better be matched, not supporting a disparate blit in this context
  1218. // disparate blit may very well use same RT we are trying to copy into
  1219. return false;
  1220. }
  1221. pRenderContext->CopyRenderTargetToTexture( pTexture );
  1222. return true;
  1223. }
  1224. //-----------------------------------------------------------------------------
  1225. // Used by the color correction UI
  1226. //-----------------------------------------------------------------------------
  1227. void CEngineClient::GrabPreColorCorrectedFrame( int x, int y, int width, int height )
  1228. {
  1229. colorcorrectiontools->GrabPreColorCorrectedFrame( x, y, width, height );
  1230. }
  1231. //-----------------------------------------------------------------------------
  1232. // Is hammer running?
  1233. //-----------------------------------------------------------------------------
  1234. bool CEngineClient::IsHammerRunning( ) const
  1235. {
  1236. return IsPC() ? InEditMode() : false;
  1237. }
  1238. extern IAchievementMgr *g_pAchievementMgr;
  1239. //-----------------------------------------------------------------------------
  1240. // Sets achievement mgr
  1241. //-----------------------------------------------------------------------------
  1242. void CEngineClient::SetAchievementMgr( IAchievementMgr *pAchievementMgr )
  1243. {
  1244. g_pAchievementMgr = pAchievementMgr;
  1245. }
  1246. //-----------------------------------------------------------------------------
  1247. // Gets achievement mgr
  1248. //-----------------------------------------------------------------------------
  1249. IAchievementMgr *CEngineClient::GetAchievementMgr()
  1250. {
  1251. return g_pAchievementMgr;
  1252. }
  1253. //-----------------------------------------------------------------------------
  1254. // Called by the client to determine violence settings for things like ragdoll
  1255. // fading.
  1256. //-----------------------------------------------------------------------------
  1257. bool CEngineClient::IsLowViolence()
  1258. {
  1259. return g_bLowViolence;
  1260. }
  1261. const char *CEngineClient::GetMostRecentSaveGame( void )
  1262. {
  1263. return saverestore->GetMostRecentlyLoadedFileName();
  1264. }
  1265. void CEngineClient::SetMostRecentSaveGame( const char *lpszFilename )
  1266. {
  1267. saverestore->SetMostRecentSaveGame( lpszFilename );
  1268. }
  1269. //-----------------------------------------------------------------------------
  1270. // Called by gameui to hint the engine that an exiting process has started.
  1271. // The Engine needs to stabilize to a safe quiet state. More frames are going
  1272. // to and have to run, but the true exit will occur.
  1273. //-----------------------------------------------------------------------------
  1274. void CEngineClient::StartXboxExitingProcess()
  1275. {
  1276. if ( IsPC() )
  1277. {
  1278. // not for PC
  1279. return;
  1280. }
  1281. g_pInputSystem->StopRumble();
  1282. // save out the achievements
  1283. g_pAchievementMgr->SaveGlobalStateIfDirty( false );
  1284. S_StopAllSounds( true );
  1285. // Shutdown QMS, need to go back to single threaded
  1286. Host_AllowQueuedMaterialSystem( false );
  1287. }
  1288. bool CEngineClient::IsSaveInProgress()
  1289. {
  1290. return saverestore->IsSaveInProgress();
  1291. }
  1292. extern IXboxSystem *g_pXboxSystem;
  1293. //-----------------------------------------------------------------------------
  1294. // Purpose:
  1295. //-----------------------------------------------------------------------------
  1296. uint CEngineClient::OnStorageDeviceAttached( void )
  1297. {
  1298. return g_pXboxSystem->OpenContainers();
  1299. }
  1300. //-----------------------------------------------------------------------------
  1301. // Purpose:
  1302. //-----------------------------------------------------------------------------
  1303. void CEngineClient::OnStorageDeviceDetached( void )
  1304. {
  1305. XBX_SetStorageDeviceId( XBX_INVALID_STORAGE_ID );
  1306. g_pXboxSystem->CloseContainers();
  1307. }
  1308. void CEngineClient::ResetDemoInterpolation( void )
  1309. {
  1310. if( demorecorder->IsRecording() )
  1311. demorecorder->ResetDemoInterpolation();
  1312. if (demoplayer->IsPlayingBack() )
  1313. demoplayer->ResetDemoInterpolation();
  1314. }
  1315. extern CGamestatsData *g_pGamestatsData;
  1316. void CEngineClient::SetGamestatsData( CGamestatsData *pGamestatsData )
  1317. {
  1318. g_pGamestatsData = pGamestatsData;
  1319. }
  1320. CGamestatsData *CEngineClient::GetGamestatsData()
  1321. {
  1322. return g_pGamestatsData;
  1323. }
  1324. //-----------------------------------------------------------------------------
  1325. #if defined( USE_SDL )
  1326. void CEngineClient::GetMouseDelta( int &x, int &y, bool bIgnoreNextMouseDelta )
  1327. {
  1328. g_pLauncherMgr->GetMouseDelta( x, y, bIgnoreNextMouseDelta );
  1329. }
  1330. #endif
  1331. void CEngineClient::ServerCmdKeyValues( KeyValues *pKeyValues )
  1332. {
  1333. cl.SendServerCmdKeyValues( pKeyValues );
  1334. }
  1335. bool CEngineClient::IsSkippingPlayback( void )
  1336. {
  1337. return demoplayer->IsSkipping();
  1338. }
  1339. bool CEngineClient::IsLoadingDemo( void )
  1340. {
  1341. return demoplayer->IsLoading();
  1342. }
  1343. bool CEngineClient::IsPlayingDemoALocallyRecordedDemo()
  1344. {
  1345. return IsPlayingDemo() &&
  1346. demoplayer &&
  1347. demoplayer->GetDemoFile() &&
  1348. !V_strnicmp( demoplayer->GetDemoFile()->m_DemoHeader.servername, "localhost", 9 );
  1349. }
  1350. uint CEngineClient::GetProtocolVersion()
  1351. {
  1352. if ( demoplayer && demoplayer->IsPlayingBack() )
  1353. {
  1354. return demoplayer->GetProtocolVersion();
  1355. }
  1356. return PROTOCOL_VERSION;
  1357. }
  1358. bool CEngineClient::IsWindowedMode()
  1359. {
  1360. return videomode->IsWindowedMode();
  1361. }
  1362. int CEngineClient::GetClientVersion() const
  1363. {
  1364. return GetSteamInfIDVersionInfo().ClientVersion;
  1365. }
  1366. bool CEngineClient::IsActiveApp( void )
  1367. {
  1368. return game->IsActiveApp();
  1369. }
  1370. //-----------------------------------------------------------------------------
  1371. // Previously ConCommand disconnect
  1372. //-----------------------------------------------------------------------------
  1373. void CEngineClient::DisconnectInternal( void )
  1374. {
  1375. Disconnect();
  1376. }
  1377. //-----------------------------------------------------------------------------
  1378. // The client DLL serves out this interface
  1379. //-----------------------------------------------------------------------------
  1380. IBaseClientDLL *g_ClientDLL = NULL;
  1381. IClientVirtualReality *g_pClientVR = NULL;
  1382. IPrediction *g_pClientSidePrediction = NULL;
  1383. IClientRenderTargets *g_pClientRenderTargets = NULL;
  1384. IClientEntityList *entitylist = NULL;
  1385. ICenterPrint *centerprint = NULL;
  1386. IClientLeafSystemEngine *clientleafsystem = NULL;
  1387. bool g_bClientLeafSystemV1;
  1388. ClientClass *g_pClientClassHead = NULL;
  1389. IClientReplay *g_pClientReplay = NULL;
  1390. ClientClass *ClientDLL_GetAllClasses( void )
  1391. {
  1392. if ( g_ClientDLL )
  1393. return g_ClientDLL->GetAllClasses();
  1394. else
  1395. return g_pClientClassHead;
  1396. }
  1397. static void ClientDLL_InitRecvTableMgr()
  1398. {
  1399. // Register all the receive tables.
  1400. RecvTable *pRecvTables[MAX_DATATABLES];
  1401. int nRecvTables = 0;
  1402. for ( ClientClass *pCur = ClientDLL_GetAllClasses(); pCur; pCur=pCur->m_pNext )
  1403. {
  1404. ErrorIfNot(
  1405. nRecvTables < ARRAYSIZE( pRecvTables ),
  1406. ("ClientDLL_InitRecvTableMgr: overflowed MAX_DATATABLES")
  1407. );
  1408. pRecvTables[nRecvTables] = pCur->m_pRecvTable;
  1409. ++nRecvTables;
  1410. }
  1411. RecvTable_Init( pRecvTables, nRecvTables );
  1412. }
  1413. static void ClientDLL_ShutdownRecvTableMgr()
  1414. {
  1415. RecvTable_Term();
  1416. }
  1417. CreateInterfaceFn ClientDLL_GetFactory( void )
  1418. {
  1419. return g_ClientFactory;
  1420. }
  1421. //-----------------------------------------------------------------------------
  1422. // Purpose: Loads the client DLL
  1423. // Input : -
  1424. //-----------------------------------------------------------------------------
  1425. bool ClientDLL_Load()
  1426. {
  1427. Assert ( !g_ClientDLLModule );
  1428. // Check the signature on the client dll. If this fails we load it anyway but put this client
  1429. // into insecure mode so it won't connect to secure servers and get VAC banned
  1430. if ( !Host_AllowLoadModule( "client.dll", "GAMEBIN", true ) )
  1431. {
  1432. // not supposed to load this but we will anyway
  1433. Host_DisallowSecureServers();
  1434. Host_AllowLoadModule( "client.dll","GAMEBIN", true );
  1435. }
  1436. g_ClientDLLModule = g_pFileSystem->LoadModule( "client", "GAMEBIN", false );
  1437. if ( g_ClientDLLModule )
  1438. {
  1439. g_ClientFactory = Sys_GetFactory( g_ClientDLLModule );
  1440. if ( g_ClientFactory )
  1441. {
  1442. g_ClientDLL = (IBaseClientDLL *)g_ClientFactory( CLIENT_DLL_INTERFACE_VERSION, NULL );
  1443. // this is to ensure the old format of the string table is used for clients version 13 and older.
  1444. // when the client version gets revved, there will need to be an else that sets this bool to true
  1445. g_bClientGameDLLGreaterThanV13 = false;
  1446. if ( !g_ClientDLL )
  1447. {
  1448. Sys_Error( "Could not get client.dll interface from library client" );
  1449. }
  1450. if( g_pSourceVR )
  1451. {
  1452. g_pClientVR = (IClientVirtualReality *)g_ClientFactory( CLIENTVIRTUALREALITY_INTERFACE_VERSION, NULL );
  1453. if( !g_pClientVR )
  1454. {
  1455. Msg( "client.dll is not VR-compatible.\n" );
  1456. }
  1457. }
  1458. }
  1459. else
  1460. {
  1461. Sys_Error( "Could not find factory interface in library client" );
  1462. }
  1463. }
  1464. else
  1465. {
  1466. // tell Steam to do a quick verify of the install. Sys_Error doesn't return, so do this first.
  1467. if( Steam3Client().SteamApps() )
  1468. Steam3Client().SteamApps()->MarkContentCorrupt( true );
  1469. // library failed to load
  1470. Sys_Error( "Could not load library client. Try restarting. If that doesn't work, verify the cache." );
  1471. }
  1472. // Load the client render targets interface from the client .dll
  1473. // NOTE: Its OK if this returns NULL, as some mods won't provide the interface and will just use the default behavior of the engine
  1474. g_pClientRenderTargets = (IClientRenderTargets *)g_ClientFactory( CLIENTRENDERTARGETS_INTERFACE_VERSION, NULL );
  1475. return true;
  1476. }
  1477. void InitExtraClientCmdCanExecuteVars()
  1478. {
  1479. // This can go away when we ship a client DLL with the FCVAR_CLIENTCMD_CAN_EXECUTE flag set on these cvars/concommands.
  1480. Cmd_AddClientCmdCanExecuteVar( "cancelselect" );
  1481. Cmd_AddClientCmdCanExecuteVar( "menuselect" );
  1482. Cmd_AddClientCmdCanExecuteVar( "playgamesound" );
  1483. Cmd_AddClientCmdCanExecuteVar( "_cl_classmenuopen" );
  1484. Cmd_AddClientCmdCanExecuteVar( "cl_buy_favorite" );
  1485. Cmd_AddClientCmdCanExecuteVar( "voice_modenable" );
  1486. Cmd_AddClientCmdCanExecuteVar( "togglescores" );
  1487. Cmd_AddClientCmdCanExecuteVar( "spec_next" );
  1488. Cmd_AddClientCmdCanExecuteVar( "spec_prev" );
  1489. Cmd_AddClientCmdCanExecuteVar( "spec_mode" );
  1490. Cmd_AddClientCmdCanExecuteVar( "spec_menu" );
  1491. Cmd_AddClientCmdCanExecuteVar( "spec_autodirector" );
  1492. Cmd_AddClientCmdCanExecuteVar( "overview_zoom" );
  1493. Cmd_AddClientCmdCanExecuteVar( "overview_mode" );
  1494. Cmd_AddClientCmdCanExecuteVar( "overview_health" );
  1495. Cmd_AddClientCmdCanExecuteVar( "overview_names" );
  1496. Cmd_AddClientCmdCanExecuteVar( "overview_tracks" );
  1497. Cmd_AddClientCmdCanExecuteVar( "overview_locked" );
  1498. Cmd_AddClientCmdCanExecuteVar( "overview_alpha" );
  1499. Cmd_AddClientCmdCanExecuteVar( "playgamesound" );
  1500. }
  1501. //-----------------------------------------------------------------------------
  1502. // Purpose: Inits the client .dll
  1503. //-----------------------------------------------------------------------------
  1504. void ClientDLL_Init( void )
  1505. {
  1506. extern void CL_SetSteamCrashComment();
  1507. // Assert ClientDLL_Load successfully created these interfaces, as we need them to init properly
  1508. Assert ( g_ClientDLL );
  1509. Assert ( g_ClientFactory );
  1510. // this will get updated after we load a map, but this gets video info if we sys_error() prior to loading a map
  1511. CL_SetSteamCrashComment();
  1512. if ( g_ClientDLL )
  1513. {
  1514. COM_TimestampedLog( "g_ClientDLL->Init" );
  1515. if ( !g_ClientDLL->Init(g_AppSystemFactory, g_AppSystemFactory, &g_ClientGlobalVariables ) )
  1516. {
  1517. Sys_Error("Client.dll Init() in library client failed.");
  1518. }
  1519. if ( g_ClientFactory )
  1520. {
  1521. COM_TimestampedLog( "g_pClientSidePrediction->Init" );
  1522. // Load the prediction interface from the client .dll
  1523. g_pClientSidePrediction = (IPrediction *)g_ClientFactory( VCLIENT_PREDICTION_INTERFACE_VERSION, NULL );
  1524. if ( !g_pClientSidePrediction )
  1525. {
  1526. Sys_Error( "Could not get IPrediction interface from library client" );
  1527. }
  1528. g_pClientSidePrediction->Init();
  1529. entitylist = ( IClientEntityList *)g_ClientFactory( VCLIENTENTITYLIST_INTERFACE_VERSION, NULL );
  1530. if ( !entitylist )
  1531. {
  1532. Sys_Error( "Could not get client entity list interface from library client" );
  1533. }
  1534. centerprint = ( ICenterPrint * )g_ClientFactory( VCENTERPRINT_INTERFACE_VERSION, NULL );
  1535. if ( !centerprint )
  1536. {
  1537. Sys_Error( "Could not get centerprint interface from library client" );
  1538. }
  1539. clientleafsystem = ( IClientLeafSystemEngine *)g_ClientFactory( CLIENTLEAFSYSTEM_INTERFACE_VERSION, NULL );
  1540. if ( clientleafsystem )
  1541. {
  1542. g_bClientLeafSystemV1 = false;
  1543. }
  1544. else if ( !clientleafsystem )
  1545. {
  1546. clientleafsystem = ( IClientLeafSystemEngine *)g_ClientFactory( CLIENTLEAFSYSTEM_INTERFACE_VERSION_1, NULL );
  1547. if ( !clientleafsystem )
  1548. {
  1549. Sys_Error( "Could not get client leaf system interface from library client" );
  1550. }
  1551. else
  1552. {
  1553. g_bClientLeafSystemV1 = true;
  1554. }
  1555. }
  1556. #if defined( REPLAY_ENABLED )
  1557. if ( Replay_IsSupportedModAndPlatform() )
  1558. {
  1559. // Replay dll should be loaded by this point
  1560. if ( !g_pReplay )
  1561. {
  1562. Sys_Error( "Replay.dll was not loaded" );
  1563. }
  1564. // Get pointer to client-side replay interface implementation
  1565. g_pClientReplay = (IClientReplay *)g_ClientFactory( CLIENT_REPLAY_INTERFACE_VERSION, NULL );
  1566. if ( !g_pClientReplay )
  1567. {
  1568. Sys_Error( "Could not get the replay interface from library client" );
  1569. }
  1570. // Allow the client dll to setup pointers to replay interfaces
  1571. extern CreateInterfaceFn g_fnReplayFactory;
  1572. if ( !g_ClientDLL->ReplayInit( g_fnReplayFactory ) )
  1573. {
  1574. Sys_Error( "Client ReplayInit() failed!" );
  1575. }
  1576. // Allow the replay dll to setup pointers to client interfaces
  1577. if ( !g_pReplay->CL_Init( g_ClientFactory ) )
  1578. {
  1579. Sys_Error( "Replay system ClientInit() failed" );
  1580. }
  1581. if ( !g_ClientDLL->ReplayPostInit() )
  1582. {
  1583. Sys_Error( "Client ReplayPostInit() failed!" );
  1584. }
  1585. #if !defined( DEDICATED )
  1586. extern CGameServer sv;
  1587. if ( !sv.IsDedicated() )
  1588. {
  1589. g_pClientReplayContext = g_pReplay->CL_GetContext();
  1590. g_pReplayManager = g_pClientReplayContext->GetReplayManager();
  1591. g_pReplayMovieManager = g_pClientReplayContext->GetMovieManager();
  1592. g_pReplayMovieRenderer = g_pClientReplayContext->GetMovieRenderer();
  1593. g_pReplayPerformanceManager = g_pClientReplayContext->GetPerformanceManager();
  1594. g_pReplayPerformanceController = g_pClientReplayContext->GetPerformanceController();
  1595. ReplayLib_Init( com_gamedir, g_pClientReplayContext );
  1596. }
  1597. #endif
  1598. }
  1599. #endif
  1600. toolframework->ClientInit( g_ClientFactory );
  1601. }
  1602. // Don't want TF2 running less than DX 8
  1603. if ( g_pMaterialSystemHardwareConfig && g_pMaterialSystemHardwareConfig->GetDXSupportLevel() < 80 )
  1604. {
  1605. if ( ( Q_stricmp( COM_GetModDirectory(), "tf" ) == 0 ) || ( Q_stricmp( COM_GetModDirectory(), "ep2" ) == 0 ) || ( Q_stricmp( COM_GetModDirectory(), "portal" ) == 0 ) || ( Q_stricmp( COM_GetModDirectory(), "tf_beta" ) == 0 ) )
  1606. {
  1607. Sys_Error( "Your graphics hardware must support at least pixel shader version 1.1 to run this game!" );
  1608. }
  1609. }
  1610. }
  1611. COM_TimestampedLog( "ClientDLL_InitRecvTableMgr" );
  1612. ClientDLL_InitRecvTableMgr();
  1613. InitExtraClientCmdCanExecuteVars();
  1614. }
  1615. //-----------------------------------------------------------------------------
  1616. // Purpose: Shuts down the client .dll
  1617. //-----------------------------------------------------------------------------
  1618. void ClientDLL_Shutdown( void )
  1619. {
  1620. #if defined( REPLAY_ENABLED )
  1621. if ( g_pReplay )
  1622. {
  1623. g_pReplay->CL_Shutdown();
  1624. }
  1625. #endif
  1626. toolframework->ClientShutdown();
  1627. ClientDLL_ShutdownRecvTableMgr();
  1628. vgui::ivgui()->RunFrame();
  1629. materials->UncacheAllMaterials();
  1630. vgui::ivgui()->RunFrame();
  1631. g_pClientSidePrediction->Shutdown();
  1632. entitylist = NULL;
  1633. g_pClientSidePrediction = NULL;
  1634. g_ClientFactory = NULL;
  1635. centerprint = NULL;
  1636. g_ClientDLL->Shutdown();
  1637. }
  1638. //-----------------------------------------------------------------------------
  1639. // Purpose: Unloads the client .dll
  1640. // Input : -
  1641. //-----------------------------------------------------------------------------
  1642. void ClientDLL_Unload()
  1643. {
  1644. FileSystem_UnloadModule( g_ClientDLLModule );
  1645. g_ClientDLL = NULL;
  1646. g_ClientDLLModule = NULL;
  1647. g_pClientRenderTargets = NULL;
  1648. }
  1649. //-----------------------------------------------------------------------------
  1650. // Purpose: Called when the game initializes and whenever the vid_mode is changed
  1651. // so the HUD can reinitialize itself.
  1652. //-----------------------------------------------------------------------------
  1653. void ClientDLL_HudVidInit( void )
  1654. {
  1655. g_ClientDLL->HudVidInit();
  1656. }
  1657. //-----------------------------------------------------------------------------
  1658. // Purpose: Allow client .dll to modify input data
  1659. //-----------------------------------------------------------------------------
  1660. void ClientDLL_ProcessInput( void )
  1661. {
  1662. if ( !g_ClientDLL )
  1663. return;
  1664. VPROF("ClientDLL_ProcessInput");
  1665. tmZoneFiltered( TELEMETRY_LEVEL0, 50, TMZF_NONE, "%s", __FUNCTION__ );
  1666. g_ClientDLL->HudProcessInput( cl.IsConnected() );
  1667. }
  1668. //-----------------------------------------------------------------------------
  1669. // Purpose:
  1670. //-----------------------------------------------------------------------------
  1671. void ClientDLL_FrameStageNotify( ClientFrameStage_t frameStage )
  1672. {
  1673. if ( !g_ClientDLL )
  1674. return;
  1675. tmZoneFiltered( TELEMETRY_LEVEL0, 50, TMZF_NONE, "%s", __FUNCTION__ );
  1676. g_ClientDLL->FrameStageNotify( frameStage );
  1677. }
  1678. //-----------------------------------------------------------------------------
  1679. // Purpose: Allow client .dll to think
  1680. //-----------------------------------------------------------------------------
  1681. void ClientDLL_Update( void )
  1682. {
  1683. if ( sv.IsDedicated() )
  1684. return;
  1685. if ( !g_ClientDLL )
  1686. return;
  1687. g_ClientDLL->HudUpdate( true );
  1688. }
  1689. //-----------------------------------------------------------------------------
  1690. // Purpose:
  1691. //-----------------------------------------------------------------------------
  1692. void ClientDLL_VoiceStatus( int entindex, bool bTalking )
  1693. {
  1694. if( g_ClientDLL )
  1695. g_ClientDLL->VoiceStatus( entindex, bTalking );
  1696. }
  1697. #ifdef IS_WINDOWS_PC
  1698. #include "winlite.h"
  1699. #endif
  1700. //-----------------------------------------------------------------------------
  1701. // Purpose:
  1702. //-----------------------------------------------------------------------------
  1703. void CEngineClient::FlashWindow()
  1704. {
  1705. #ifndef USE_SDL
  1706. FLASHWINFO flashwinfo;
  1707. flashwinfo.cbSize = sizeof( flashwinfo );
  1708. flashwinfo.hwnd = (HWND)game->GetMainWindow();
  1709. flashwinfo.dwFlags = FLASHW_ALL;
  1710. flashwinfo.uCount = 5;
  1711. flashwinfo.dwTimeout = 0;
  1712. FlashWindowEx( &flashwinfo );
  1713. #endif
  1714. }
  1715. //-----------------------------------------------------------------------------
  1716. // Purpose:
  1717. //-----------------------------------------------------------------------------
  1718. int CEngineClient::GetInstancesRunningCount( )
  1719. {
  1720. return CheckOtherInstancesRunning( );
  1721. }
  1722. //-----------------------------------------------------------------------------
  1723. // Purpose:
  1724. //-----------------------------------------------------------------------------
  1725. float CEngineClient::GetPausedExpireTime( void )
  1726. {
  1727. return cl.GetPausedExpireTime();
  1728. }
  1729. //-----------------------------------------------------------------------------
  1730. // Purpose:
  1731. //-----------------------------------------------------------------------------
  1732. bool CEngineClient::StartDemoRecording( const char *pszFilename, const char *pszFolder /* = NULL */ )
  1733. {
  1734. bool bUseFolder = ( pszFolder && pszFolder[0] );
  1735. if ( demorecorder->IsRecording() )
  1736. {
  1737. ConMsg( "Already recording.\n" );
  1738. return false;
  1739. }
  1740. if ( demoplayer->IsPlayingBack() )
  1741. {
  1742. ConMsg( "Can't record during demo playback.\n" );
  1743. return false;
  1744. }
  1745. // check filename
  1746. if ( !COM_IsValidPath( pszFilename ) )
  1747. {
  1748. ConMsg( "record %s: invalid filename.\n", pszFilename );
  1749. return false;
  1750. }
  1751. if ( bUseFolder )
  1752. {
  1753. // check folder
  1754. if ( !COM_IsValidPath( pszFolder ) )
  1755. {
  1756. ConMsg( "record %s: invalid folder.\n", pszFolder );
  1757. return false;
  1758. }
  1759. }
  1760. char szFinal[MAX_OSPATH];
  1761. char szTemp[MAX_OSPATH];
  1762. if ( !g_ClientDLL->CanRecordDemo( szTemp, sizeof( szTemp ) ) )
  1763. {
  1764. ConMsg( "%s\n", szTemp ); // re-use szTemp as the error string if the client prevents us from starting a demo
  1765. return false;
  1766. }
  1767. if ( bUseFolder )
  1768. {
  1769. V_sprintf_safe( szTemp, "%s%c%s", pszFolder, CORRECT_PATH_SEPARATOR, pszFilename );
  1770. }
  1771. else
  1772. {
  1773. V_sprintf_safe( szTemp, "%s", pszFilename );
  1774. }
  1775. // remove .dem extension if it exists
  1776. Q_StripExtension( szTemp, szFinal, sizeof( szFinal ) );
  1777. // record it
  1778. demorecorder->StartRecording( szFinal, false );
  1779. return true;
  1780. }
  1781. //-----------------------------------------------------------------------------
  1782. // Purpose:
  1783. //-----------------------------------------------------------------------------
  1784. void CEngineClient::StopDemoRecording( void )
  1785. {
  1786. if ( !demorecorder->IsRecording() )
  1787. {
  1788. ConDMsg( "Not recording a demo.\n" );
  1789. return;
  1790. }
  1791. demorecorder->StopRecording();
  1792. }
  1793. //-----------------------------------------------------------------------------
  1794. // Purpose:
  1795. //-----------------------------------------------------------------------------
  1796. void CEngineClient::TakeScreenshot( const char *pszFilename, const char *pszFolder /* = NULL */ )
  1797. {
  1798. bool bUseFolder = ( pszFolder && pszFolder[0] );
  1799. // check filename
  1800. if ( !COM_IsValidPath( pszFilename ) )
  1801. {
  1802. ConMsg( "TakeScreenshot invalid filename: %s\n", pszFilename );
  1803. return;
  1804. }
  1805. if ( bUseFolder )
  1806. {
  1807. // check folder
  1808. if ( !COM_IsValidPath( pszFolder ) )
  1809. {
  1810. ConMsg( "TakeScreenshot invalid folder: %s\n", pszFolder );
  1811. return;
  1812. }
  1813. }
  1814. bool bReadPixelsFromFrontBuffer = g_pMaterialSystemHardwareConfig->ReadPixelsFromFrontBuffer();
  1815. if ( bReadPixelsFromFrontBuffer )
  1816. {
  1817. Shader_SwapBuffers();
  1818. }
  1819. // Disable threading for the duration of the screenshots, because we need to get pointers to the (complete)
  1820. // back buffer right now.
  1821. bool bEnabled = materials->AllowThreading( false, g_nMaterialSystemThread );
  1822. char szFinal[MAX_OSPATH] = {0};
  1823. if ( bUseFolder )
  1824. {
  1825. V_sprintf_safe( szFinal, "%s%c%s", pszFolder, CORRECT_PATH_SEPARATOR, pszFilename );
  1826. }
  1827. else
  1828. {
  1829. V_sprintf_safe( szFinal, "%s", pszFilename );
  1830. }
  1831. V_SetExtension( szFinal, ".tga", sizeof( szFinal ) );
  1832. videomode->TakeSnapshotTGA( szFinal );
  1833. // Restore threading if it was previously enabled (if it wasn't this will do nothing).
  1834. materials->AllowThreading( bEnabled, g_nMaterialSystemThread );
  1835. if ( !bReadPixelsFromFrontBuffer )
  1836. {
  1837. Shader_SwapBuffers();
  1838. }
  1839. }