//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
# include "cbase.h"
# include <crtmemdebug.h>
# include "vgui_int.h"
# include "clientmode.h"
# include "iinput.h"
# include "iviewrender.h"
# include "ivieweffects.h"
# include "ivmodemanager.h"
# include "prediction.h"
# include "clientsideeffects.h"
# include "particlemgr.h"
# include "steam/steam_api.h"
# include "initializer.h"
# include "smoke_fog_overlay.h"
# include "view.h"
# include "ienginevgui.h"
# include "iefx.h"
# include "enginesprite.h"
# include "networkstringtable_clientdll.h"
# include "voice_status.h"
# include "filesystem.h"
# include "c_te_legacytempents.h"
# include "c_rope.h"
# include "engine/ishadowmgr.h"
# include "engine/IStaticPropMgr.h"
# include "hud_basechat.h"
# include "hud_crosshair.h"
# include "view_shared.h"
# include "env_wind_shared.h"
# include "detailobjectsystem.h"
# include "clienteffectprecachesystem.h"
# include "soundenvelope.h"
# include "c_basetempentity.h"
# include "materialsystem/imaterialsystemstub.h"
# include "VGuiMatSurface/IMatSystemSurface.h"
# include "materialsystem/imaterialsystemhardwareconfig.h"
# include "c_soundscape.h"
# include "engine/ivdebugoverlay.h"
# include "vguicenterprint.h"
# include "iviewrender_beams.h"
# include "tier0/vprof.h"
# include "engine/IEngineTrace.h"
# include "engine/ivmodelinfo.h"
# include "physics.h"
# include "usermessages.h"
# include "gamestringpool.h"
# include "c_user_message_register.h"
# include "IGameUIFuncs.h"
# include "saverestoretypes.h"
# include "saverestore.h"
# include "physics_saverestore.h"
# include "igameevents.h"
# include "datacache/idatacache.h"
# include "datacache/imdlcache.h"
# include "kbutton.h"
# include "tier0/icommandline.h"
# include "gamerules_register.h"
# include "vgui_controls/AnimationController.h"
# include "bitmap/tgawriter.h"
# include "c_world.h"
# include "perfvisualbenchmark.h"
# include "SoundEmitterSystem/isoundemittersystembase.h"
# include "hud_closecaption.h"
# include "colorcorrectionmgr.h"
# include "physpropclientside.h"
# include "panelmetaclassmgr.h"
# include "c_vguiscreen.h"
# include "imessagechars.h"
# include "game/client/IGameClientExports.h"
# include "client_factorylist.h"
# include "ragdoll_shared.h"
# include "rendertexture.h"
# include "view_scene.h"
# include "iclientmode.h"
# include "con_nprint.h"
# include "inputsystem/iinputsystem.h"
# include "appframework/IAppSystemGroup.h"
# include "scenefilecache/ISceneFileCache.h"
# include "tier2/tier2dm.h"
# include "tier3/tier3.h"
# include "ihudlcd.h"
# include "toolframework_client.h"
# include "hltvcamera.h"
# if defined( REPLAY_ENABLED )
# include "replay/replaycamera.h"
# include "replay/replay_ragdoll.h"
# include "qlimits.h"
# include "replay/replay.h"
# include "replay/ireplaysystem.h"
# include "replay/iclientreplay.h"
# include "replay/ienginereplay.h"
# include "replay/ireplaymanager.h"
# include "replay/ireplayscreenshotmanager.h"
# include "replay/iclientreplaycontext.h"
# include "replay/vgui/replayconfirmquitdlg.h"
# include "replay/vgui/replaybrowsermainpanel.h"
# include "replay/vgui/replayinputpanel.h"
# include "replay/vgui/replayperformanceeditor.h"
# endif
# include "vgui/ILocalize.h"
# include "vgui/IVGui.h"
# include "ixboxsystem.h"
# include "ipresence.h"
# include "engine/imatchmaking.h"
# include "cdll_bounded_cvars.h"
# include "matsys_controls/matsyscontrols.h"
# include "gamestats.h"
# include "particle_parse.h"
# if defined( TF_CLIENT_DLL )
# include "rtime.h"
# include "tf_hud_disconnect_prompt.h"
# include "../engine/audio/public/sound.h"
# include "tf_shared_content_manager.h"
# endif
# include "clientsteamcontext.h"
# include "renamed_recvtable_compat.h"
# include "mouthinfo.h"
# include "sourcevr/isourcevirtualreality.h"
# include "client_virtualreality.h"
# include "mumble.h"
// NVNT includes
# include "hud_macros.h"
# include "haptics/ihaptics.h"
# include "haptics/haptic_utils.h"
# include "haptics/haptic_msgs.h"
# if defined( TF_CLIENT_DLL )
# include "abuse_report.h"
# endif
# ifdef USES_ECON_ITEMS
# include "econ_item_system.h"
# endif // USES_ECON_ITEMS
# if defined( TF_CLIENT_DLL )
# include "econ/tool_items/custom_texture_cache.h"
# endif
# ifdef WORKSHOP_IMPORT_ENABLED
# include "fbxsystem/fbxsystem.h"
# endif
# include "touch.h"
extern vgui : : IInputInternal * g_InputInternal ;
//=============================================================================
// HPE_BEGIN
// [dwenger] Necessary for stats display
//=============================================================================
# include "achievements_and_stats_interface.h"
//=============================================================================
// HPE_END
//=============================================================================
# ifdef PORTAL
# include "PortalRender.h"
# endif
# ifdef SIXENSE
# include "sixense/in_sixense.h"
# endif
// memdbgon must be the last include file in a .cpp file!!!
# include "tier0/memdbgon.h"
extern IClientMode * GetClientModeNormal ( ) ;
// IF YOU ADD AN INTERFACE, EXTERN IT IN THE HEADER FILE.
IVEngineClient * engine = NULL ;
IVModelRender * modelrender = NULL ;
IVEfx * effects = NULL ;
IVRenderView * render = NULL ;
IVDebugOverlay * debugoverlay = NULL ;
IMaterialSystemStub * materials_stub = NULL ;
IDataCache * datacache = NULL ;
IVModelInfoClient * modelinfo = NULL ;
IEngineVGui * enginevgui = NULL ;
INetworkStringTableContainer * networkstringtable = NULL ;
ISpatialPartition * partition = NULL ;
IFileSystem * filesystem = NULL ;
IShadowMgr * shadowmgr = NULL ;
IStaticPropMgrClient * staticpropmgr = NULL ;
IEngineSound * enginesound = NULL ;
IUniformRandomStream * random = NULL ;
static CGaussianRandomStream s_GaussianRandomStream ;
CGaussianRandomStream * randomgaussian = & s_GaussianRandomStream ;
ISharedGameRules * sharedgamerules = NULL ;
IEngineTrace * enginetrace = NULL ;
IGameUIFuncs * gameuifuncs = NULL ;
IGameEventManager2 * gameeventmanager = NULL ;
ISoundEmitterSystemBase * soundemitterbase = NULL ;
IInputSystem * inputsystem = NULL ;
ISceneFileCache * scenefilecache = NULL ;
IXboxSystem * xboxsystem = NULL ; // Xbox 360 only
IMatchmaking * matchmaking = NULL ;
IUploadGameStats * gamestatsuploader = NULL ;
IClientReplayContext * g_pClientReplayContext = NULL ;
# if defined( REPLAY_ENABLED )
IReplayManager * g_pReplayManager = NULL ;
IReplayMovieManager * g_pReplayMovieManager = NULL ;
IReplayScreenshotManager * g_pReplayScreenshotManager = NULL ;
IReplayPerformanceManager * g_pReplayPerformanceManager = NULL ;
IReplayPerformanceController * g_pReplayPerformanceController = NULL ;
IEngineReplay * g_pEngineReplay = NULL ;
IEngineClientReplay * g_pEngineClientReplay = NULL ;
IReplaySystem * g_pReplay = NULL ;
# endif
IHaptics * haptics = NULL ; // NVNT haptics system interface singleton
//=============================================================================
// HPE_BEGIN
// [dwenger] Necessary for stats display
//=============================================================================
AchievementsAndStatsInterface * g_pAchievementsAndStatsInterface = NULL ;
//=============================================================================
// HPE_END
//=============================================================================
IGameSystem * SoundEmitterSystem ( ) ;
IGameSystem * ToolFrameworkClientSystem ( ) ;
// Engine player info, no game related infos here
BEGIN_BYTESWAP_DATADESC ( player_info_s )
DEFINE_ARRAY ( name , FIELD_CHARACTER , MAX_PLAYER_NAME_LENGTH ) ,
DEFINE_FIELD ( userID , FIELD_INTEGER ) ,
DEFINE_ARRAY ( guid , FIELD_CHARACTER , SIGNED_GUID_LEN + 1 ) ,
DEFINE_FIELD ( friendsID , FIELD_INTEGER ) ,
DEFINE_ARRAY ( friendsName , FIELD_CHARACTER , MAX_PLAYER_NAME_LENGTH ) ,
DEFINE_FIELD ( fakeplayer , FIELD_BOOLEAN ) ,
DEFINE_FIELD ( ishltv , FIELD_BOOLEAN ) ,
# if defined( REPLAY_ENABLED )
DEFINE_FIELD ( isreplay , FIELD_BOOLEAN ) ,
# endif
DEFINE_ARRAY ( customFiles , FIELD_INTEGER , MAX_CUSTOM_FILES ) ,
DEFINE_FIELD ( filesDownloaded , FIELD_INTEGER ) ,
END_BYTESWAP_DATADESC ( )
static bool g_bRequestCacheUsedMaterials = false ;
void RequestCacheUsedMaterials ( )
{
g_bRequestCacheUsedMaterials = true ;
}
void ProcessCacheUsedMaterials ( )
{
if ( ! g_bRequestCacheUsedMaterials )
return ;
g_bRequestCacheUsedMaterials = false ;
if ( materials )
{
materials - > CacheUsedMaterials ( ) ;
}
}
// String tables
INetworkStringTable * g_pStringTableParticleEffectNames = NULL ;
INetworkStringTable * g_StringTableEffectDispatch = NULL ;
INetworkStringTable * g_StringTableVguiScreen = NULL ;
INetworkStringTable * g_pStringTableMaterials = NULL ;
INetworkStringTable * g_pStringTableInfoPanel = NULL ;
INetworkStringTable * g_pStringTableClientSideChoreoScenes = NULL ;
INetworkStringTable * g_pStringTableServerMapCycle = NULL ;
# ifdef TF_CLIENT_DLL
INetworkStringTable * g_pStringTableServerPopFiles = NULL ;
INetworkStringTable * g_pStringTableServerMapCycleMvM = NULL ;
# endif
static CGlobalVarsBase dummyvars ( true ) ;
// So stuff that might reference gpGlobals during DLL initialization won't have a NULL pointer.
// Once the engine calls Init on this DLL, this pointer gets assigned to the shared data in the engine
CGlobalVarsBase * gpGlobals = & dummyvars ;
class CHudChat ;
class CViewRender ;
extern CViewRender g_DefaultViewRender ;
extern void StopAllRumbleEffects ( void ) ;
static C_BaseEntityClassList * s_pClassLists = NULL ;
C_BaseEntityClassList : : C_BaseEntityClassList ( )
{
m_pNextClassList = s_pClassLists ;
s_pClassLists = this ;
}
C_BaseEntityClassList : : ~ C_BaseEntityClassList ( )
{
}
// Any entities that want an OnDataChanged during simulation register for it here.
class CDataChangedEvent
{
public :
CDataChangedEvent ( ) = default ;
CDataChangedEvent ( IClientNetworkable * ent , DataUpdateType_t updateType , int * pStoredEvent )
{
m_pEntity = ent ;
m_UpdateType = updateType ;
m_pStoredEvent = pStoredEvent ;
}
IClientNetworkable * m_pEntity ;
DataUpdateType_t m_UpdateType ;
int * m_pStoredEvent ;
} ;
ISaveRestoreBlockHandler * GetEntitySaveRestoreBlockHandler ( ) ;
ISaveRestoreBlockHandler * GetViewEffectsRestoreBlockHandler ( ) ;
CUtlLinkedList < CDataChangedEvent , unsigned short > g_DataChangedEvents ;
ClientFrameStage_t g_CurFrameStage = FRAME_UNDEFINED ;
class IMoveHelper ;
void DispatchHudText ( const char * pszName ) ;
static ConVar s_CV_ShowParticleCounts ( " showparticlecounts " , " 0 " , 0 , " Display number of particles drawn per frame " ) ;
static ConVar s_cl_team ( " cl_team " , " default " , FCVAR_USERINFO | FCVAR_ARCHIVE , " Default team when joining a game " ) ;
static ConVar s_cl_class ( " cl_class " , " default " , FCVAR_USERINFO | FCVAR_ARCHIVE , " Default class when joining a game " ) ;
# ifdef HL1MP_CLIENT_DLL
static ConVar s_cl_load_hl1_content ( " cl_load_hl1_content " , " 0 " , FCVAR_ARCHIVE , " Mount the content from Half-Life: Source if possible " ) ;
# endif
// Physics system
bool g_bLevelInitialized ;
bool g_bTextMode = false ;
class IClientPurchaseInterfaceV2 * g_pClientPurchaseInterface = ( class IClientPurchaseInterfaceV2 * ) ( & g_bTextMode + 156 ) ;
static ConVar * g_pcv_ThreadMode = NULL ;
//-----------------------------------------------------------------------------
// Purpose: interface for gameui to modify voice bans
//-----------------------------------------------------------------------------
class CGameClientExports : public IGameClientExports
{
public :
// ingame voice manipulation
bool IsPlayerGameVoiceMuted ( int playerIndex )
{
return GetClientVoiceMgr ( ) - > IsPlayerBlocked ( playerIndex ) ;
}
void MutePlayerGameVoice ( int playerIndex )
{
GetClientVoiceMgr ( ) - > SetPlayerBlockedState ( playerIndex , true ) ;
}
void UnmutePlayerGameVoice ( int playerIndex )
{
GetClientVoiceMgr ( ) - > SetPlayerBlockedState ( playerIndex , false ) ;
}
void OnGameUIActivated ( void )
{
IGameEvent * event = gameeventmanager - > CreateEvent ( " gameui_activated " ) ;
if ( event )
{
gameeventmanager - > FireEventClientSide ( event ) ;
}
}
void OnGameUIHidden ( void )
{
IGameEvent * event = gameeventmanager - > CreateEvent ( " gameui_hidden " ) ;
if ( event )
{
gameeventmanager - > FireEventClientSide ( event ) ;
}
}
//=============================================================================
// HPE_BEGIN
// [dwenger] Necessary for stats display
//=============================================================================
void CreateAchievementsPanel ( vgui : : Panel * pParent )
{
if ( g_pAchievementsAndStatsInterface )
{
g_pAchievementsAndStatsInterface - > CreatePanel ( pParent ) ;
}
}
void DisplayAchievementPanel ( )
{
if ( g_pAchievementsAndStatsInterface )
{
g_pAchievementsAndStatsInterface - > DisplayPanel ( ) ;
}
}
void ShutdownAchievementPanel ( )
{
if ( g_pAchievementsAndStatsInterface )
{
g_pAchievementsAndStatsInterface - > ReleasePanel ( ) ;
}
}
int GetAchievementsPanelMinWidth ( void ) const
{
if ( g_pAchievementsAndStatsInterface )
{
return g_pAchievementsAndStatsInterface - > GetAchievementsPanelMinWidth ( ) ;
}
return 0 ;
}
//=============================================================================
// HPE_END
//=============================================================================
const char * GetHolidayString ( )
{
return UTIL_GetActiveHolidayString ( ) ;
}
} ;
EXPOSE_SINGLE_INTERFACE ( CGameClientExports , IGameClientExports , GAMECLIENTEXPORTS_INTERFACE_VERSION ) ;
class CClientDLLSharedAppSystems : public IClientDLLSharedAppSystems
{
public :
CClientDLLSharedAppSystems ( )
{
AddAppSystem ( " soundemittersystem " DLL_EXT_STRING , SOUNDEMITTERSYSTEM_INTERFACE_VERSION ) ;
AddAppSystem ( " scenefilecache " DLL_EXT_STRING , SCENE_FILE_CACHE_INTERFACE_VERSION ) ;
}
virtual int Count ( )
{
return m_Systems . Count ( ) ;
}
virtual char const * GetDllName ( int idx )
{
return m_Systems [ idx ] . m_pModuleName ;
}
virtual char const * GetInterfaceName ( int idx )
{
return m_Systems [ idx ] . m_pInterfaceName ;
}
private :
void AddAppSystem ( char const * moduleName , char const * interfaceName )
{
AppSystemInfo_t sys ;
sys . m_pModuleName = moduleName ;
sys . m_pInterfaceName = interfaceName ;
m_Systems . AddToTail ( sys ) ;
}
CUtlVector < AppSystemInfo_t > m_Systems ;
} ;
EXPOSE_SINGLE_INTERFACE ( CClientDLLSharedAppSystems , IClientDLLSharedAppSystems , CLIENT_DLL_SHARED_APPSYSTEMS ) ;
//-----------------------------------------------------------------------------
// Helper interface for voice.
//-----------------------------------------------------------------------------
class CHLVoiceStatusHelper : public IVoiceStatusHelper
{
public :
virtual void GetPlayerTextColor ( int entindex , int color [ 3 ] )
{
color [ 0 ] = color [ 1 ] = color [ 2 ] = 128 ;
}
virtual void UpdateCursorState ( )
{
}
virtual bool CanShowSpeakerLabels ( )
{
return true ;
}
} ;
static CHLVoiceStatusHelper g_VoiceStatusHelper ;
//-----------------------------------------------------------------------------
// Code to display which entities are having their bones setup each frame.
//-----------------------------------------------------------------------------
ConVar cl_ShowBoneSetupEnts ( " cl_ShowBoneSetupEnts " , " 0 " , 0 , " Show which entities are having their bones setup each frame. " ) ;
class CBoneSetupEnt
{
public :
char m_ModelName [ 128 ] ;
int m_Index ;
int m_Count ;
} ;
bool BoneSetupCompare ( const CBoneSetupEnt & a , const CBoneSetupEnt & b )
{
return a . m_Index < b . m_Index ;
}
CUtlRBTree < CBoneSetupEnt > g_BoneSetupEnts ( BoneSetupCompare ) ;
void TrackBoneSetupEnt ( C_BaseAnimating * pEnt )
{
# ifdef _DEBUG
if ( IsRetail ( ) )
return ;
if ( ! cl_ShowBoneSetupEnts . GetInt ( ) )
return ;
CBoneSetupEnt ent ;
ent . m_Index = pEnt - > entindex ( ) ;
unsigned short i = g_BoneSetupEnts . Find ( ent ) ;
if ( i = = g_BoneSetupEnts . InvalidIndex ( ) )
{
Q_strncpy ( ent . m_ModelName , modelinfo - > GetModelName ( pEnt - > GetModel ( ) ) , sizeof ( ent . m_ModelName ) ) ;
ent . m_Count = 1 ;
g_BoneSetupEnts . Insert ( ent ) ;
}
else
{
g_BoneSetupEnts [ i ] . m_Count + + ;
}
# endif
}
void DisplayBoneSetupEnts ( )
{
# ifdef _DEBUG
if ( IsRetail ( ) )
return ;
if ( ! cl_ShowBoneSetupEnts . GetInt ( ) )
return ;
unsigned short i ;
int nElements = 0 ;
for ( i = g_BoneSetupEnts . FirstInorder ( ) ; i ! = g_BoneSetupEnts . LastInorder ( ) ; i = g_BoneSetupEnts . NextInorder ( i ) )
+ + nElements ;
engine - > Con_NPrintf ( 0 , " %d bone setup ents (name/count/entindex) ------------ " , nElements ) ;
con_nprint_s printInfo ;
printInfo . time_to_live = - 1 ;
printInfo . fixed_width_font = true ;
printInfo . color [ 0 ] = printInfo . color [ 1 ] = printInfo . color [ 2 ] = 1 ;
printInfo . index = 2 ;
for ( i = g_BoneSetupEnts . FirstInorder ( ) ; i ! = g_BoneSetupEnts . LastInorder ( ) ; i = g_BoneSetupEnts . NextInorder ( i ) )
{
CBoneSetupEnt * pEnt = & g_BoneSetupEnts [ i ] ;
if ( pEnt - > m_Count > = 3 )
{
printInfo . color [ 0 ] = 1 ;
printInfo . color [ 1 ] = printInfo . color [ 2 ] = 0 ;
}
else if ( pEnt - > m_Count = = 2 )
{
printInfo . color [ 0 ] = ( float ) 200 / 255 ;
printInfo . color [ 1 ] = ( float ) 220 / 255 ;
printInfo . color [ 2 ] = 0 ;
}
else
{
printInfo . color [ 0 ] = printInfo . color [ 0 ] = printInfo . color [ 0 ] = 1 ;
}
engine - > Con_NXPrintf ( & printInfo , " %25s / %3d / %3d " , pEnt - > m_ModelName , pEnt - > m_Count , pEnt - > m_Index ) ;
printInfo . index + + ;
}
g_BoneSetupEnts . RemoveAll ( ) ;
# endif
}
//-----------------------------------------------------------------------------
// Purpose: engine to client .dll interface
//-----------------------------------------------------------------------------
class CHLClient : public IBaseClientDLL
{
public :
CHLClient ( ) ;
virtual int Init ( CreateInterfaceFn appSystemFactory , CreateInterfaceFn physicsFactory , CGlobalVarsBase * pGlobals ) ;
virtual void PostInit ( ) ;
virtual void Shutdown ( void ) ;
virtual bool ReplayInit ( CreateInterfaceFn fnReplayFactory ) ;
virtual bool ReplayPostInit ( ) ;
virtual void LevelInitPreEntity ( const char * pMapName ) ;
virtual void LevelInitPostEntity ( ) ;
virtual void LevelShutdown ( void ) ;
virtual ClientClass * GetAllClasses ( void ) ;
virtual int HudVidInit ( void ) ;
virtual void HudProcessInput ( bool bActive ) ;
virtual void HudUpdate ( bool bActive ) ;
virtual void HudReset ( void ) ;
virtual void HudText ( const char * message ) ;
// Mouse Input Interfaces
virtual void IN_ActivateMouse ( void ) ;
virtual void IN_DeactivateMouse ( void ) ;
virtual void IN_Accumulate ( void ) ;
virtual void IN_ClearStates ( void ) ;
virtual bool IN_IsKeyDown ( const char * name , bool & isdown ) ;
virtual void IN_OnMouseWheeled ( int nDelta ) ;
// Raw signal
virtual int IN_KeyEvent ( int eventcode , ButtonCode_t keynum , const char * pszCurrentBinding ) ;
virtual void IN_SetSampleTime ( float frametime ) ;
// Create movement command
virtual void CreateMove ( int sequence_number , float input_sample_frametime , bool active ) ;
virtual void ExtraMouseSample ( float frametime , bool active ) ;
virtual bool WriteUsercmdDeltaToBuffer ( bf_write * buf , int from , int to , bool isnewcommand ) ;
virtual void EncodeUserCmdToBuffer ( bf_write & buf , int slot ) ;
virtual void DecodeUserCmdFromBuffer ( bf_read & buf , int slot ) ;
virtual void View_Render ( vrect_t * rect ) ;
virtual void RenderView ( const CViewSetup & view , int nClearFlags , int whatToDraw ) ;
virtual void View_Fade ( ScreenFade_t * pSF ) ;
virtual void SetCrosshairAngle ( const QAngle & angle ) ;
virtual void InitSprite ( CEngineSprite * pSprite , const char * loadname ) ;
virtual void ShutdownSprite ( CEngineSprite * pSprite ) ;
virtual int GetSpriteSize ( void ) const ;
virtual void VoiceStatus ( int entindex , qboolean bTalking ) ;
virtual void InstallStringTableCallback ( const char * tableName ) ;
virtual void FrameStageNotify ( ClientFrameStage_t curStage ) ;
virtual bool DispatchUserMessage ( int msg_type , bf_read & msg_data ) ;
// Save/restore system hooks
virtual CSaveRestoreData * SaveInit ( int size ) ;
virtual void SaveWriteFields ( CSaveRestoreData * , const char * , void * , datamap_t * , typedescription_t * , int ) ;
virtual void SaveReadFields ( CSaveRestoreData * , const char * , void * , datamap_t * , typedescription_t * , int ) ;
virtual void PreSave ( CSaveRestoreData * ) ;
virtual void Save ( CSaveRestoreData * ) ;
virtual void WriteSaveHeaders ( CSaveRestoreData * ) ;
virtual void ReadRestoreHeaders ( CSaveRestoreData * ) ;
virtual void Restore ( CSaveRestoreData * , bool ) ;
virtual void DispatchOnRestore ( ) ;
virtual void WriteSaveGameScreenshot ( const char * pFilename ) ;
// Given a list of "S(wavname) S(wavname2)" tokens, look up the localized text and emit
// the appropriate close caption if running with closecaption = 1
virtual void EmitSentenceCloseCaption ( char const * tokenstream ) ;
virtual void EmitCloseCaption ( char const * captionname , float duration ) ;
virtual CStandardRecvProxies * GetStandardRecvProxies ( ) ;
virtual bool CanRecordDemo ( char * errorMsg , int length ) const ;
virtual void OnDemoRecordStart ( char const * pDemoBaseName ) ;
virtual void OnDemoRecordStop ( ) ;
virtual void OnDemoPlaybackStart ( char const * pDemoBaseName ) ;
virtual void OnDemoPlaybackStop ( ) ;
virtual bool ShouldDrawDropdownConsole ( ) ;
// Get client screen dimensions
virtual int GetScreenWidth ( ) ;
virtual int GetScreenHeight ( ) ;
// save game screenshot writing
virtual void WriteSaveGameScreenshotOfSize ( const char * pFilename , int width , int height , bool bCreatePowerOf2Padded /*=false*/ , bool bWriteVTF /*=false*/ ) ;
// Gets the location of the player viewpoint
virtual bool GetPlayerView ( CViewSetup & playerView ) ;
// Matchmaking
virtual void SetupGameProperties ( CUtlVector < XUSER_CONTEXT > & contexts , CUtlVector < XUSER_PROPERTY > & properties ) ;
virtual uint GetPresenceID ( const char * pIDName ) ;
virtual const char * GetPropertyIdString ( const uint id ) ;
virtual void GetPropertyDisplayString ( uint id , uint value , char * pOutput , int nBytes ) ;
virtual void StartStatsReporting ( HANDLE handle , bool bArbitrated ) ;
virtual void InvalidateMdlCache ( ) ;
virtual void ReloadFilesInList ( IFileList * pFilesToReload ) ;
// Let the client handle UI toggle - if this function returns false, the UI will toggle, otherwise it will not.
virtual bool HandleUiToggle ( ) ;
// Allow the console to be shown?
virtual bool ShouldAllowConsole ( ) ;
// Get renamed recv tables
virtual CRenamedRecvTableInfo * GetRenamedRecvTableInfos ( ) ;
// Get the mouthinfo for the sound being played inside UI panels
virtual CMouthInfo * GetClientUIMouthInfo ( ) ;
// Notify the client that a file has been received from the game server
virtual void FileReceived ( const char * fileName , unsigned int transferID ) ;
virtual const char * TranslateEffectForVisionFilter ( const char * pchEffectType , const char * pchEffectName ) ;
virtual void ClientAdjustStartSoundParams ( struct StartSoundParams_t & params ) ;
// Returns true if the disconnect command has been handled by the client
virtual bool DisconnectAttempt ( void ) ;
public :
void PrecacheMaterial ( const char * pMaterialName ) ;
virtual bool IsConnectedUserInfoChangeAllowed ( IConVar * pCvar ) ;
virtual void IN_TouchEvent ( int type , int fingerId , int x , int y ) ;
private :
void UncacheAllMaterials ( ) ;
void ResetStringTablePointers ( ) ;
CUtlVector < IMaterial * > m_CachedMaterials ;
} ;
CHLClient gHLClient ;
IBaseClientDLL * clientdll = & gHLClient ;
EXPOSE_SINGLE_INTERFACE_GLOBALVAR ( CHLClient , IBaseClientDLL , CLIENT_DLL_INTERFACE_VERSION , gHLClient ) ;
//-----------------------------------------------------------------------------
// Precaches a material
//-----------------------------------------------------------------------------
void PrecacheMaterial ( const char * pMaterialName )
{
gHLClient . PrecacheMaterial ( pMaterialName ) ;
}
//-----------------------------------------------------------------------------
// Converts a previously precached material into an index
//-----------------------------------------------------------------------------
int GetMaterialIndex ( const char * pMaterialName )
{
if ( pMaterialName )
{
int nIndex = g_pStringTableMaterials - > FindStringIndex ( pMaterialName ) ;
Assert ( nIndex > = 0 ) ;
if ( nIndex > = 0 )
return nIndex ;
}
// This is the invalid string index
return 0 ;
}
//-----------------------------------------------------------------------------
// Converts precached material indices into strings
//-----------------------------------------------------------------------------
const char * GetMaterialNameFromIndex ( int nIndex )
{
if ( nIndex ! = ( g_pStringTableMaterials - > GetMaxStrings ( ) - 1 ) )
{
return g_pStringTableMaterials - > GetString ( nIndex ) ;
}
else
{
return NULL ;
}
}
//-----------------------------------------------------------------------------
// Precaches a particle system
//-----------------------------------------------------------------------------
void PrecacheParticleSystem ( const char * pParticleSystemName )
{
g_pStringTableParticleEffectNames - > AddString ( false , pParticleSystemName ) ;
g_pParticleSystemMgr - > PrecacheParticleSystem ( pParticleSystemName ) ;
}
//-----------------------------------------------------------------------------
// Converts a previously precached particle system into an index
//-----------------------------------------------------------------------------
int GetParticleSystemIndex ( const char * pParticleSystemName )
{
if ( pParticleSystemName )
{
int nIndex = g_pStringTableParticleEffectNames - > FindStringIndex ( pParticleSystemName ) ;
if ( nIndex ! = INVALID_STRING_INDEX )
return nIndex ;
DevWarning ( " Client: Missing precache for particle system \" %s \" ! \n " , pParticleSystemName ) ;
}
// This is the invalid string index
return 0 ;
}
//-----------------------------------------------------------------------------
// Converts precached particle system indices into strings
//-----------------------------------------------------------------------------
const char * GetParticleSystemNameFromIndex ( int nIndex )
{
if ( nIndex < g_pStringTableParticleEffectNames - > GetMaxStrings ( ) )
return g_pStringTableParticleEffectNames - > GetString ( nIndex ) ;
return " error " ;
}
//-----------------------------------------------------------------------------
// Returns true if host_thread_mode is set to non-zero (and engine is running in threaded mode)
//-----------------------------------------------------------------------------
bool IsEngineThreaded ( )
{
if ( g_pcv_ThreadMode )
{
return g_pcv_ThreadMode - > GetBool ( ) ;
}
return false ;
}
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CHLClient : : CHLClient ( )
{
// Kinda bogus, but the logic in the engine is too convoluted to put it there
g_bLevelInitialized = false ;
}
extern IGameSystem * ViewportClientSystem ( ) ;
//-----------------------------------------------------------------------------
ISourceVirtualReality * g_pSourceVR = NULL ;
// Purpose: Called when the DLL is first loaded.
// Input : engineFactory -
// Output : int
//-----------------------------------------------------------------------------
int CHLClient : : Init ( CreateInterfaceFn appSystemFactory , CreateInterfaceFn physicsFactory , CGlobalVarsBase * pGlobals )
{
InitCRTMemDebug ( ) ;
MathLib_Init ( 2.2f , 2.2f , 0.0f , 2.0f ) ;
# ifdef SIXENSE
g_pSixenseInput = new SixenseInput ;
# endif
// Hook up global variables
gpGlobals = pGlobals ;
ConnectTier1Libraries ( & appSystemFactory , 1 ) ;
ConnectTier2Libraries ( & appSystemFactory , 1 ) ;
ConnectTier3Libraries ( & appSystemFactory , 1 ) ;
# ifndef NO_STEAM
ClientSteamContext ( ) . Activate ( ) ;
# endif
// We aren't happy unless we get all of our interfaces.
// please don't collapse this into one monolithic boolean expression (impossible to debug)
if ( ( engine = ( IVEngineClient * ) appSystemFactory ( VENGINE_CLIENT_INTERFACE_VERSION , NULL ) ) = = NULL )
return false ;
if ( ( modelrender = ( IVModelRender * ) appSystemFactory ( VENGINE_HUDMODEL_INTERFACE_VERSION , NULL ) ) = = NULL )
return false ;
if ( ( effects = ( IVEfx * ) appSystemFactory ( VENGINE_EFFECTS_INTERFACE_VERSION , NULL ) ) = = NULL )
return false ;
if ( ( enginetrace = ( IEngineTrace * ) appSystemFactory ( INTERFACEVERSION_ENGINETRACE_CLIENT , NULL ) ) = = NULL )
return false ;
if ( ( render = ( IVRenderView * ) appSystemFactory ( VENGINE_RENDERVIEW_INTERFACE_VERSION , NULL ) ) = = NULL )
return false ;
if ( ( debugoverlay = ( IVDebugOverlay * ) appSystemFactory ( VDEBUG_OVERLAY_INTERFACE_VERSION , NULL ) ) = = NULL )
return false ;
if ( ( datacache = ( IDataCache * ) appSystemFactory ( DATACACHE_INTERFACE_VERSION , NULL ) ) = = NULL )
return false ;
if ( ! mdlcache )
return false ;
if ( ( modelinfo = ( IVModelInfoClient * ) appSystemFactory ( VMODELINFO_CLIENT_INTERFACE_VERSION , NULL ) ) = = NULL )
return false ;
if ( ( enginevgui = ( IEngineVGui * ) appSystemFactory ( VENGINE_VGUI_VERSION , NULL ) ) = = NULL )
return false ;
if ( ( networkstringtable = ( INetworkStringTableContainer * ) appSystemFactory ( INTERFACENAME_NETWORKSTRINGTABLECLIENT , NULL ) ) = = NULL )
return false ;
if ( ( partition = ( ISpatialPartition * ) appSystemFactory ( INTERFACEVERSION_SPATIALPARTITION , NULL ) ) = = NULL )
return false ;
if ( ( shadowmgr = ( IShadowMgr * ) appSystemFactory ( ENGINE_SHADOWMGR_INTERFACE_VERSION , NULL ) ) = = NULL )
return false ;
if ( ( staticpropmgr = ( IStaticPropMgrClient * ) appSystemFactory ( INTERFACEVERSION_STATICPROPMGR_CLIENT , NULL ) ) = = NULL )
return false ;
if ( ( enginesound = ( IEngineSound * ) appSystemFactory ( IENGINESOUND_CLIENT_INTERFACE_VERSION , NULL ) ) = = NULL )
return false ;
if ( ( filesystem = ( IFileSystem * ) appSystemFactory ( FILESYSTEM_INTERFACE_VERSION , NULL ) ) = = NULL )
return false ;
if ( ( random = ( IUniformRandomStream * ) appSystemFactory ( VENGINE_CLIENT_RANDOM_INTERFACE_VERSION , NULL ) ) = = NULL )
return false ;
if ( ( gameuifuncs = ( IGameUIFuncs * ) appSystemFactory ( VENGINE_GAMEUIFUNCS_VERSION , NULL ) ) = = NULL )
return false ;
if ( ( gameeventmanager = ( IGameEventManager2 * ) appSystemFactory ( INTERFACEVERSION_GAMEEVENTSMANAGER2 , NULL ) ) = = NULL )
return false ;
if ( ( soundemitterbase = ( ISoundEmitterSystemBase * ) appSystemFactory ( SOUNDEMITTERSYSTEM_INTERFACE_VERSION , NULL ) ) = = NULL )
return false ;
if ( ( inputsystem = ( IInputSystem * ) appSystemFactory ( INPUTSYSTEM_INTERFACE_VERSION , NULL ) ) = = NULL )
return false ;
if ( ( scenefilecache = ( ISceneFileCache * ) appSystemFactory ( SCENE_FILE_CACHE_INTERFACE_VERSION , NULL ) ) = = NULL )
return false ;
if ( IsX360 ( ) & & ( xboxsystem = ( IXboxSystem * ) appSystemFactory ( XBOXSYSTEM_INTERFACE_VERSION , NULL ) ) = = NULL )
return false ;
if ( IsX360 ( ) & & ( matchmaking = ( IMatchmaking * ) appSystemFactory ( VENGINE_MATCHMAKING_VERSION , NULL ) ) = = NULL )
return false ;
# ifndef _XBOX
if ( ( gamestatsuploader = ( IUploadGameStats * ) appSystemFactory ( INTERFACEVERSION_UPLOADGAMESTATS , NULL ) ) = = NULL )
return false ;
# endif
# if defined( REPLAY_ENABLED )
if ( IsPC ( ) & & ( g_pEngineReplay = ( IEngineReplay * ) appSystemFactory ( ENGINE_REPLAY_INTERFACE_VERSION , NULL ) ) = = NULL )
return false ;
if ( IsPC ( ) & & ( g_pEngineClientReplay = ( IEngineClientReplay * ) appSystemFactory ( ENGINE_REPLAY_CLIENT_INTERFACE_VERSION , NULL ) ) = = NULL )
return false ;
# endif
if ( ! g_pMatSystemSurface )
return false ;
# ifdef WORKSHOP_IMPORT_ENABLED
if ( ! ConnectDataModel ( appSystemFactory ) )
return false ;
if ( InitDataModel ( ) ! = INIT_OK )
return false ;
InitFbx ( ) ;
# endif
// it's ok if this is NULL. That just means the sourcevr.dll wasn't found
g_pSourceVR = ( ISourceVirtualReality * ) appSystemFactory ( SOURCE_VIRTUAL_REALITY_INTERFACE_VERSION , NULL ) ;
factorylist_t factories ;
factories . appSystemFactory = appSystemFactory ;
factories . physicsFactory = physicsFactory ;
FactoryList_Store ( factories ) ;
// Yes, both the client and game .dlls will try to Connect, the soundemittersystem.dll will handle this gracefully
if ( ! soundemitterbase - > Connect ( appSystemFactory ) )
{
return false ;
}
if ( CommandLine ( ) - > FindParm ( " -textmode " ) )
g_bTextMode = true ;
if ( CommandLine ( ) - > FindParm ( " -makedevshots " ) )
g_MakingDevShots = true ;
// Not fatal if the material system stub isn't around.
materials_stub = ( IMaterialSystemStub * ) appSystemFactory ( MATERIAL_SYSTEM_STUB_INTERFACE_VERSION , NULL ) ;
if ( ! g_pMaterialSystemHardwareConfig )
return false ;
// Hook up the gaussian random number generator
s_GaussianRandomStream . AttachToStream ( random ) ;
// Initialize the console variables.
ConVar_Register ( FCVAR_CLIENTDLL ) ;
g_pcv_ThreadMode = g_pCVar - > FindVar ( " host_thread_mode " ) ;
if ( ! Initializer : : InitializeAllObjects ( ) )
return false ;
if ( ! ParticleMgr ( ) - > Init ( MAX_TOTAL_PARTICLES , materials ) )
return false ;
if ( ! VGui_Startup ( appSystemFactory ) )
return false ;
vgui : : VGui_InitMatSysInterfacesList ( " ClientDLL " , & appSystemFactory , 1 ) ;
// Add the client systems.
// Client Leaf System has to be initialized first, since DetailObjectSystem uses it
IGameSystem : : Add ( GameStringSystem ( ) ) ;
IGameSystem : : Add ( SoundEmitterSystem ( ) ) ;
IGameSystem : : Add ( ToolFrameworkClientSystem ( ) ) ;
IGameSystem : : Add ( ClientLeafSystem ( ) ) ;
IGameSystem : : Add ( DetailObjectSystem ( ) ) ;
IGameSystem : : Add ( ViewportClientSystem ( ) ) ;
IGameSystem : : Add ( ClientEffectPrecacheSystem ( ) ) ;
IGameSystem : : Add ( g_pClientShadowMgr ) ;
IGameSystem : : Add ( g_pColorCorrectionMgr ) ; // NOTE: This must happen prior to ClientThinkList (color correction is updated there)
IGameSystem : : Add ( ClientThinkList ( ) ) ;
IGameSystem : : Add ( ClientSoundscapeSystem ( ) ) ;
IGameSystem : : Add ( PerfVisualBenchmark ( ) ) ;
IGameSystem : : Add ( MumbleSystem ( ) ) ;
# if defined( TF_CLIENT_DLL )
IGameSystem : : Add ( CustomTextureToolCacheGameSystem ( ) ) ;
IGameSystem : : Add ( TFSharedContentManager ( ) ) ;
# endif
# if defined( TF_CLIENT_DLL )
if ( g_AbuseReportMgr ! = NULL )
{
IGameSystem : : Add ( g_AbuseReportMgr ) ;
}
# endif
# if defined( CLIENT_DLL ) && defined( COPY_CHECK_STRESSTEST )
IGameSystem : : Add ( GetPredictionCopyTester ( ) ) ;
# endif
modemanager - > Init ( ) ;
g_pClientMode - > InitViewport ( ) ;
gHUD . Init ( ) ;
gTouch . Init ( ) ;
g_pClientMode - > Init ( ) ;
if ( ! IGameSystem : : InitAllSystems ( ) )
return false ;
g_pClientMode - > Enable ( ) ;
if ( ! view )
{
view = ( IViewRender * ) & g_DefaultViewRender ;
}
view - > Init ( ) ;
vieweffects - > Init ( ) ;
C_BaseTempEntity : : PrecacheTempEnts ( ) ;
input - > Init_All ( ) ;
VGui_CreateGlobalPanels ( ) ;
InitSmokeFogOverlay ( ) ;
// Register user messages..
CUserMessageRegister : : RegisterAll ( ) ;
ClientVoiceMgr_Init ( ) ;
// Embed voice status icons inside chat element
{
vgui : : VPANEL parent = enginevgui - > GetPanel ( PANEL_CLIENTDLL ) ;
GetClientVoiceMgr ( ) - > Init ( & g_VoiceStatusHelper , parent ) ;
}
if ( ! PhysicsDLLInit ( physicsFactory ) )
return false ;
g_pGameSaveRestoreBlockSet - > AddBlockHandler ( GetEntitySaveRestoreBlockHandler ( ) ) ;
g_pGameSaveRestoreBlockSet - > AddBlockHandler ( GetPhysSaveRestoreBlockHandler ( ) ) ;
g_pGameSaveRestoreBlockSet - > AddBlockHandler ( GetViewEffectsRestoreBlockHandler ( ) ) ;
ClientWorldFactoryInit ( ) ;
C_BaseAnimating : : InitBoneSetupThreadPool ( ) ;
# if defined( WIN32 ) && !defined( _X360 )
// NVNT connect haptics sytem
ConnectHaptics ( appSystemFactory ) ;
# endif
# ifndef _X360
HookHapticMessages ( ) ; // Always hook the messages
# endif
return true ;
}
bool CHLClient : : ReplayInit ( CreateInterfaceFn fnReplayFactory )
{
# if defined( REPLAY_ENABLED )
if ( ! IsPC ( ) )
return false ;
if ( ( g_pReplay = ( IReplaySystem * ) fnReplayFactory ( REPLAY_INTERFACE_VERSION , NULL ) ) = = NULL )
return false ;
if ( ( g_pClientReplayContext = g_pReplay - > CL_GetContext ( ) ) = = NULL )
return false ;
return true ;
# else
return false ;
# endif
}
bool CHLClient : : ReplayPostInit ( )
{
# if defined( REPLAY_ENABLED )
if ( ( g_pReplayManager = g_pClientReplayContext - > GetReplayManager ( ) ) = = NULL )
return false ;
if ( ( g_pReplayScreenshotManager = g_pClientReplayContext - > GetScreenshotManager ( ) ) = = NULL )
return false ;
if ( ( g_pReplayPerformanceManager = g_pClientReplayContext - > GetPerformanceManager ( ) ) = = NULL )
return false ;
if ( ( g_pReplayPerformanceController = g_pClientReplayContext - > GetPerformanceController ( ) ) = = NULL )
return false ;
if ( ( g_pReplayMovieManager = g_pClientReplayContext - > GetMovieManager ( ) ) = = NULL )
return false ;
return true ;
# else
return false ;
# endif
}
//-----------------------------------------------------------------------------
// Purpose: Called after client & server DLL are loaded and all systems initialized
//-----------------------------------------------------------------------------
void CHLClient : : PostInit ( )
{
IGameSystem : : PostInitAllSystems ( ) ;
# ifdef SIXENSE
// allow sixnese input to perform post-init operations
g_pSixenseInput - > PostInit ( ) ;
# endif
g_ClientVirtualReality . StartupComplete ( ) ;
# ifdef HL1MP_CLIENT_DLL
if ( s_cl_load_hl1_content . GetBool ( ) & & steamapicontext & & steamapicontext - > SteamApps ( ) )
{
char szPath [ MAX_PATH * 2 ] ;
int ccFolder = steamapicontext - > SteamApps ( ) - > GetAppInstallDir ( 280 , szPath , sizeof ( szPath ) ) ;
if ( ccFolder > 0 )
{
V_AppendSlash ( szPath , sizeof ( szPath ) ) ;
V_strncat ( szPath , " hl1 " , sizeof ( szPath ) ) ;
g_pFullFileSystem - > AddSearchPath ( szPath , " HL1 " ) ;
g_pFullFileSystem - > AddSearchPath ( szPath , " GAME " ) ;
}
}
# endif
}
//-----------------------------------------------------------------------------
// Purpose: Called when the client .dll is being dismissed
//-----------------------------------------------------------------------------
void CHLClient : : Shutdown ( void )
{
if ( g_pAchievementsAndStatsInterface )
{
g_pAchievementsAndStatsInterface - > ReleasePanel ( ) ;
}
# ifdef SIXENSE
g_pSixenseInput - > Shutdown ( ) ;
delete g_pSixenseInput ;
g_pSixenseInput = NULL ;
# endif
C_BaseAnimating : : ShutdownBoneSetupThreadPool ( ) ;
ClientWorldFactoryShutdown ( ) ;
g_pGameSaveRestoreBlockSet - > RemoveBlockHandler ( GetViewEffectsRestoreBlockHandler ( ) ) ;
g_pGameSaveRestoreBlockSet - > RemoveBlockHandler ( GetPhysSaveRestoreBlockHandler ( ) ) ;
g_pGameSaveRestoreBlockSet - > RemoveBlockHandler ( GetEntitySaveRestoreBlockHandler ( ) ) ;
ClientVoiceMgr_Shutdown ( ) ;
Initializer : : FreeAllObjects ( ) ;
g_pClientMode - > Disable ( ) ;
g_pClientMode - > Shutdown ( ) ;
input - > Shutdown_All ( ) ;
C_BaseTempEntity : : ClearDynamicTempEnts ( ) ;
TermSmokeFogOverlay ( ) ;
view - > Shutdown ( ) ;
g_pParticleSystemMgr - > UncacheAllParticleSystems ( ) ;
UncacheAllMaterials ( ) ;
IGameSystem : : ShutdownAllSystems ( ) ;
gHUD . Shutdown ( ) ;
VGui_Shutdown ( ) ;
gTouch . Shutdown ( ) ;
ParticleMgr ( ) - > Term ( ) ;
ClearKeyValuesCache ( ) ;
# ifndef NO_STEAM
ClientSteamContext ( ) . Shutdown ( ) ;
# endif
# ifdef WORKSHOP_IMPORT_ENABLED
ShutdownDataModel ( ) ;
DisconnectDataModel ( ) ;
ShutdownFbx ( ) ;
# endif
// This call disconnects the VGui libraries which we rely on later in the shutdown path, so don't do it
// DisconnectTier3Libraries( );
DisconnectTier2Libraries ( ) ;
ConVar_Unregister ( ) ;
DisconnectTier1Libraries ( ) ;
gameeventmanager = NULL ;
# if defined( WIN32 ) && !defined( _X360 )
// NVNT Disconnect haptics system
DisconnectHaptics ( ) ;
# endif
}
//-----------------------------------------------------------------------------
// Purpose:
// Called when the game initializes
// and whenever the vid_mode is changed
// so the HUD can reinitialize itself.
// Output : int
//-----------------------------------------------------------------------------
int CHLClient : : HudVidInit ( void )
{
gHUD . VidInit ( ) ;
GetClientVoiceMgr ( ) - > VidInit ( ) ;
return 1 ;
}
//-----------------------------------------------------------------------------
// Method used to allow the client to filter input messages before the
// move record is transmitted to the server
//-----------------------------------------------------------------------------
void CHLClient : : HudProcessInput ( bool bActive )
{
g_pClientMode - > ProcessInput ( bActive ) ;
}
//-----------------------------------------------------------------------------
// Purpose: Called when shared data gets changed, allows dll to modify data
// Input : bActive -
//-----------------------------------------------------------------------------
void CHLClient : : HudUpdate ( bool bActive )
{
float frametime = gpGlobals - > frametime ;
# if defined( TF_CLIENT_DLL )
CRTime : : UpdateRealTime ( ) ;
# endif
GetClientVoiceMgr ( ) - > Frame ( frametime ) ;
gHUD . UpdateHud ( bActive ) ;
{
C_BaseAnimating : : AutoAllowBoneAccess boneaccess ( true , false ) ;
IGameSystem : : UpdateAllSystems ( frametime ) ;
}
// run vgui animations
vgui : : GetAnimationController ( ) - > UpdateAnimations ( engine - > Time ( ) ) ;
hudlcd - > SetGlobalStat ( " (time_int) " , VarArgs ( " %d " , ( int ) gpGlobals - > curtime ) ) ;
hudlcd - > SetGlobalStat ( " (time_float) " , VarArgs ( " %.2f " , gpGlobals - > curtime ) ) ;
// I don't think this is necessary any longer, but I will leave it until
// I can check into this further.
C_BaseTempEntity : : CheckDynamicTempEnts ( ) ;
# ifdef SIXENSE
// If we're not connected, update sixense so we can move the mouse cursor when in the menus
if ( ! engine - > IsConnected ( ) | | engine - > IsPaused ( ) )
{
g_pSixenseInput - > SixenseFrame ( 0 , NULL ) ;
}
# endif
}
//-----------------------------------------------------------------------------
// Purpose: Called to restore to "non"HUD state.
//-----------------------------------------------------------------------------
void CHLClient : : HudReset ( void )
{
gHUD . VidInit ( ) ;
PhysicsReset ( ) ;
}
//-----------------------------------------------------------------------------
// Purpose: Called to add hud text message
//-----------------------------------------------------------------------------
void CHLClient : : HudText ( const char * message )
{
DispatchHudText ( message ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CHLClient : : ShouldDrawDropdownConsole ( )
{
# if defined( REPLAY_ENABLED )
extern ConVar hud_freezecamhide ;
extern bool IsTakingAFreezecamScreenshot ( ) ;
if ( hud_freezecamhide . GetBool ( ) & & IsTakingAFreezecamScreenshot ( ) )
{
return false ;
}
# endif
return true ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : ClientClass
//-----------------------------------------------------------------------------
ClientClass * CHLClient : : GetAllClasses ( void )
{
return g_pClientClassHead ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CHLClient : : IN_ActivateMouse ( void )
{
input - > ActivateMouse ( ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CHLClient : : IN_DeactivateMouse ( void )
{
input - > DeactivateMouse ( ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CHLClient : : IN_Accumulate ( void )
{
input - > AccumulateMouse ( ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CHLClient : : IN_ClearStates ( void )
{
input - > ClearStates ( ) ;
}
//-----------------------------------------------------------------------------
// Purpose: Engine can query for particular keys
// Input : *name -
//-----------------------------------------------------------------------------
bool CHLClient : : IN_IsKeyDown ( const char * name , bool & isdown )
{
kbutton_t * key = input - > FindKey ( name ) ;
if ( ! key )
{
return false ;
}
isdown = ( key - > state & 1 ) ? true : false ;
// Found the key by name
return true ;
}
//-----------------------------------------------------------------------------
// Purpose: Engine can issue a key event
// Input : eventcode -
// keynum -
// *pszCurrentBinding -
void CHLClient : : IN_OnMouseWheeled ( int nDelta )
{
# if defined( REPLAY_ENABLED )
CReplayPerformanceEditorPanel * pPerfEditor = ReplayUI_GetPerformanceEditor ( ) ;
if ( pPerfEditor )
{
pPerfEditor - > OnInGameMouseWheelEvent ( nDelta ) ;
}
# endif
}
//-----------------------------------------------------------------------------
// Purpose: Engine can issue a key event
// Input : eventcode -
// keynum -
// *pszCurrentBinding -
// Output : int
//-----------------------------------------------------------------------------
int CHLClient : : IN_KeyEvent ( int eventcode , ButtonCode_t keynum , const char * pszCurrentBinding )
{
return input - > KeyEvent ( eventcode , keynum , pszCurrentBinding ) ;
}
void CHLClient : : ExtraMouseSample ( float frametime , bool active )
{
Assert ( C_BaseEntity : : IsAbsRecomputationsEnabled ( ) ) ;
Assert ( C_BaseEntity : : IsAbsQueriesValid ( ) ) ;
C_BaseAnimating : : AutoAllowBoneAccess boneaccess ( true , false ) ;
MDLCACHE_CRITICAL_SECTION ( ) ;
input - > ExtraMouseSample ( frametime , active ) ;
}
void CHLClient : : IN_SetSampleTime ( float frametime )
{
input - > Joystick_SetSampleTime ( frametime ) ;
input - > IN_SetSampleTime ( frametime ) ;
# ifdef SIXENSE
g_pSixenseInput - > ResetFrameTime ( frametime ) ;
# endif
}
//-----------------------------------------------------------------------------
// Purpose: Fills in usercmd_s structure based on current view angles and key/controller inputs
// Input : frametime - timestamp for last frame
// *cmd - the command to fill in
// active - whether the user is fully connected to a server
//-----------------------------------------------------------------------------
void CHLClient : : CreateMove ( int sequence_number , float input_sample_frametime , bool active )
{
Assert ( C_BaseEntity : : IsAbsRecomputationsEnabled ( ) ) ;
Assert ( C_BaseEntity : : IsAbsQueriesValid ( ) ) ;
C_BaseAnimating : : AutoAllowBoneAccess boneaccess ( true , false ) ;
MDLCACHE_CRITICAL_SECTION ( ) ;
input - > CreateMove ( sequence_number , input_sample_frametime , active ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *buf -
// from -
// to -
//-----------------------------------------------------------------------------
bool CHLClient : : WriteUsercmdDeltaToBuffer ( bf_write * buf , int from , int to , bool isnewcommand )
{
return input - > WriteUsercmdDeltaToBuffer ( buf , from , to , isnewcommand ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : buf -
// buffersize -
// slot -
//-----------------------------------------------------------------------------
void CHLClient : : EncodeUserCmdToBuffer ( bf_write & buf , int slot )
{
input - > EncodeUserCmdToBuffer ( buf , slot ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : buf -
// buffersize -
// slot -
//-----------------------------------------------------------------------------
void CHLClient : : DecodeUserCmdFromBuffer ( bf_read & buf , int slot )
{
input - > DecodeUserCmdFromBuffer ( buf , slot ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CHLClient : : View_Render ( vrect_t * rect )
{
VPROF ( " View_Render " ) ;
// UNDONE: This gets hit at startup sometimes, investigate - will cause NaNs in calcs inside Render()
if ( rect - > width = = 0 | | rect - > height = = 0 )
return ;
view - > Render ( rect ) ;
UpdatePerfStats ( ) ;
}
//-----------------------------------------------------------------------------
// Gets the location of the player viewpoint
//-----------------------------------------------------------------------------
bool CHLClient : : GetPlayerView ( CViewSetup & playerView )
{
playerView = * view - > GetPlayerViewSetup ( ) ;
return true ;
}
//-----------------------------------------------------------------------------
// Matchmaking
//-----------------------------------------------------------------------------
void CHLClient : : SetupGameProperties ( CUtlVector < XUSER_CONTEXT > & contexts , CUtlVector < XUSER_PROPERTY > & properties )
{
presence - > SetupGameProperties ( contexts , properties ) ;
}
uint CHLClient : : GetPresenceID ( const char * pIDName )
{
return presence - > GetPresenceID ( pIDName ) ;
}
const char * CHLClient : : GetPropertyIdString ( const uint id )
{
return presence - > GetPropertyIdString ( id ) ;
}
void CHLClient : : GetPropertyDisplayString ( uint id , uint value , char * pOutput , int nBytes )
{
presence - > GetPropertyDisplayString ( id , value , pOutput , nBytes ) ;
}
void CHLClient : : StartStatsReporting ( HANDLE handle , bool bArbitrated )
{
presence - > StartStatsReporting ( handle , bArbitrated ) ;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CHLClient : : InvalidateMdlCache ( )
{
C_BaseAnimating * pAnimating ;
for ( C_BaseEntity * pEntity = ClientEntityList ( ) . FirstBaseEntity ( ) ; pEntity ; pEntity = ClientEntityList ( ) . NextBaseEntity ( pEntity ) )
{
pAnimating = dynamic_cast < C_BaseAnimating * > ( pEntity ) ;
if ( pAnimating )
{
pAnimating - > InvalidateMdlCache ( ) ;
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pSF -
//-----------------------------------------------------------------------------
void CHLClient : : View_Fade ( ScreenFade_t * pSF )
{
if ( pSF ! = NULL )
vieweffects - > Fade ( * pSF ) ;
}
//-----------------------------------------------------------------------------
// Purpose: Per level init
//-----------------------------------------------------------------------------
void CHLClient : : LevelInitPreEntity ( char const * pMapName )
{
// HACK: Bogus, but the logic is too complicated in the engine
if ( g_bLevelInitialized )
return ;
g_bLevelInitialized = true ;
input - > LevelInit ( ) ;
vieweffects - > LevelInit ( ) ;
//Tony; loadup per-map manifests.
ParseParticleEffectsMap ( pMapName , true ) ;
// Tell mode manager that map is changing
modemanager - > LevelInit ( pMapName ) ;
ParticleMgr ( ) - > LevelInit ( ) ;
hudlcd - > SetGlobalStat ( " (mapname) " , pMapName ) ;
C_BaseTempEntity : : ClearDynamicTempEnts ( ) ;
clienteffects - > Flush ( ) ;
view - > LevelInit ( ) ;
tempents - > LevelInit ( ) ;
ResetToneMapping ( 1.0 ) ;
IGameSystem : : LevelInitPreEntityAllSystems ( pMapName ) ;
# ifdef USES_ECON_ITEMS
GameItemSchema_t * pItemSchema = ItemSystem ( ) - > GetItemSchema ( ) ;
if ( pItemSchema )
{
pItemSchema - > BInitFromDelayedBuffer ( ) ;
}
# endif // USES_ECON_ITEMS
ResetWindspeed ( ) ;
# if !defined( NO_ENTITY_PREDICTION )
// don't do prediction if single player!
// don't set direct because of FCVAR_USERINFO
if ( gpGlobals - > maxClients > 1 )
{
if ( ! cl_predict - > GetInt ( ) )
{
engine - > ClientCmd ( " cl_predict 1 " ) ;
}
}
else
{
if ( cl_predict - > GetInt ( ) )
{
engine - > ClientCmd ( " cl_predict 0 " ) ;
}
}
# endif
// Check low violence settings for this map
g_RagdollLVManager . SetLowViolence ( pMapName ) ;
gHUD . LevelInit ( ) ;
# if defined( REPLAY_ENABLED )
// Initialize replay ragdoll recorder
if ( ! engine - > IsPlayingDemo ( ) )
{
CReplayRagdollRecorder : : Instance ( ) . Init ( ) ;
}
# endif
}
//-----------------------------------------------------------------------------
// Purpose: Per level init
//-----------------------------------------------------------------------------
void CHLClient : : LevelInitPostEntity ( )
{
IGameSystem : : LevelInitPostEntityAllSystems ( ) ;
C_PhysPropClientside : : RecreateAll ( ) ;
internalCenterPrint - > Clear ( ) ;
}
//-----------------------------------------------------------------------------
// Purpose: Reset our global string table pointers
//-----------------------------------------------------------------------------
void CHLClient : : ResetStringTablePointers ( )
{
g_pStringTableParticleEffectNames = NULL ;
g_StringTableEffectDispatch = NULL ;
g_StringTableVguiScreen = NULL ;
g_pStringTableMaterials = NULL ;
g_pStringTableInfoPanel = NULL ;
g_pStringTableClientSideChoreoScenes = NULL ;
g_pStringTableServerMapCycle = NULL ;
# ifdef TF_CLIENT_DLL
g_pStringTableServerPopFiles = NULL ;
g_pStringTableServerMapCycleMvM = NULL ;
# endif
}
//-----------------------------------------------------------------------------
// Purpose: Per level de-init
//-----------------------------------------------------------------------------
void CHLClient : : LevelShutdown ( void )
{
// HACK: Bogus, but the logic is too complicated in the engine
if ( ! g_bLevelInitialized )
return ;
g_bLevelInitialized = false ;
// Disable abs recomputations when everything is shutting down
CBaseEntity : : EnableAbsRecomputations ( false ) ;
// Level shutdown sequence.
// First do the pre-entity shutdown of all systems
IGameSystem : : LevelShutdownPreEntityAllSystems ( ) ;
C_PhysPropClientside : : DestroyAll ( ) ;
modemanager - > LevelShutdown ( ) ;
// Remove temporary entities before removing entities from the client entity list so that the te_* may
// clean up before hand.
tempents - > LevelShutdown ( ) ;
// Now release/delete the entities
cl_entitylist - > Release ( ) ;
C_BaseEntityClassList * pClassList = s_pClassLists ;
while ( pClassList )
{
pClassList - > LevelShutdown ( ) ;
pClassList = pClassList - > m_pNextClassList ;
}
// Now do the post-entity shutdown of all systems
IGameSystem : : LevelShutdownPostEntityAllSystems ( ) ;
view - > LevelShutdown ( ) ;
beams - > ClearBeams ( ) ;
ParticleMgr ( ) - > RemoveAllEffects ( ) ;
StopAllRumbleEffects ( ) ;
gHUD . LevelShutdown ( ) ;
internalCenterPrint - > Clear ( ) ;
messagechars - > Clear ( ) ;
# ifndef TF_CLIENT_DLL
// don't want to do this for TF2 because we have particle systems in our
// character loadout screen that can be viewed when we're not connected to a server
g_pParticleSystemMgr - > UncacheAllParticleSystems ( ) ;
# endif
UncacheAllMaterials ( ) ;
# ifdef _XBOX
ReleaseRenderTargets ( ) ;
# endif
// string tables are cleared on disconnect from a server, so reset our global pointers to NULL
ResetStringTablePointers ( ) ;
# if defined( REPLAY_ENABLED )
// Shutdown the ragdoll recorder
CReplayRagdollRecorder : : Instance ( ) . Shutdown ( ) ;
CReplayRagdollCache : : Instance ( ) . Shutdown ( ) ;
# endif
}
//-----------------------------------------------------------------------------
// Purpose: Engine received crosshair offset ( autoaim )
// Input : angle -
//-----------------------------------------------------------------------------
void CHLClient : : SetCrosshairAngle ( const QAngle & angle )
{
CHudCrosshair * crosshair = GET_HUDELEMENT ( CHudCrosshair ) ;
if ( crosshair )
{
crosshair - > SetCrosshairAngle ( angle ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose: Helper to initialize sprite from .spr semaphor
// Input : *pSprite -
// *loadname -
//-----------------------------------------------------------------------------
void CHLClient : : InitSprite ( CEngineSprite * pSprite , const char * loadname )
{
if ( pSprite )
{
pSprite - > Init ( loadname ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pSprite -
//-----------------------------------------------------------------------------
void CHLClient : : ShutdownSprite ( CEngineSprite * pSprite )
{
if ( pSprite )
{
pSprite - > Shutdown ( ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose: Tells engine how much space to allocate for sprite objects
// Output : int
//-----------------------------------------------------------------------------
int CHLClient : : GetSpriteSize ( void ) const
{
return sizeof ( CEngineSprite ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : entindex -
// bTalking -
//-----------------------------------------------------------------------------
void CHLClient : : VoiceStatus ( int entindex , qboolean bTalking )
{
GetClientVoiceMgr ( ) - > UpdateSpeakerStatus ( entindex , ! ! bTalking ) ;
}
//-----------------------------------------------------------------------------
// Called when the string table for materials changes
//-----------------------------------------------------------------------------
void OnMaterialStringTableChanged ( void * object , INetworkStringTable * stringTable , int stringNumber , const char * newString , void const * newData )
{
// Make sure this puppy is precached
gHLClient . PrecacheMaterial ( newString ) ;
RequestCacheUsedMaterials ( ) ;
}
//-----------------------------------------------------------------------------
// Called when the string table for particle systems changes
//-----------------------------------------------------------------------------
void OnParticleSystemStringTableChanged ( void * object , INetworkStringTable * stringTable , int stringNumber , const char * newString , void const * newData )
{
// Make sure this puppy is precached
g_pParticleSystemMgr - > PrecacheParticleSystem ( newString ) ;
RequestCacheUsedMaterials ( ) ;
}
//-----------------------------------------------------------------------------
// Called when the string table for VGUI changes
//-----------------------------------------------------------------------------
void OnVguiScreenTableChanged ( void * object , INetworkStringTable * stringTable , int stringNumber , const char * newString , void const * newData )
{
// Make sure this puppy is precached
vgui : : Panel * pPanel = PanelMetaClassMgr ( ) - > CreatePanelMetaClass ( newString , 100 , NULL , NULL ) ;
if ( pPanel )
PanelMetaClassMgr ( ) - > DestroyPanelMetaClass ( pPanel ) ;
}
//-----------------------------------------------------------------------------
// Purpose: Preload the string on the client (if single player it should already be in the cache from the server!!!)
// Input : *object -
// *stringTable -
// stringNumber -
// *newString -
// *newData -
//-----------------------------------------------------------------------------
void OnSceneStringTableChanged ( void * object , INetworkStringTable * stringTable , int stringNumber , const char * newString , void const * newData )
{
}
//-----------------------------------------------------------------------------
// Purpose: Hook up any callbacks here, the table definition has been parsed but
// no data has been added yet
//-----------------------------------------------------------------------------
void CHLClient : : InstallStringTableCallback ( const char * tableName )
{
// Here, cache off string table IDs
if ( ! Q_strcasecmp ( tableName , " VguiScreen " ) )
{
// Look up the id
g_StringTableVguiScreen = networkstringtable - > FindTable ( tableName ) ;
// When the material list changes, we need to know immediately
g_StringTableVguiScreen - > SetStringChangedCallback ( NULL , OnVguiScreenTableChanged ) ;
}
else if ( ! Q_strcasecmp ( tableName , " Materials " ) )
{
// Look up the id
g_pStringTableMaterials = networkstringtable - > FindTable ( tableName ) ;
// When the material list changes, we need to know immediately
g_pStringTableMaterials - > SetStringChangedCallback ( NULL , OnMaterialStringTableChanged ) ;
}
else if ( ! Q_strcasecmp ( tableName , " EffectDispatch " ) )
{
g_StringTableEffectDispatch = networkstringtable - > FindTable ( tableName ) ;
}
else if ( ! Q_strcasecmp ( tableName , " InfoPanel " ) )
{
g_pStringTableInfoPanel = networkstringtable - > FindTable ( tableName ) ;
}
else if ( ! Q_strcasecmp ( tableName , " Scenes " ) )
{
g_pStringTableClientSideChoreoScenes = networkstringtable - > FindTable ( tableName ) ;
g_pStringTableClientSideChoreoScenes - > SetStringChangedCallback ( NULL , OnSceneStringTableChanged ) ;
}
else if ( ! Q_strcasecmp ( tableName , " ParticleEffectNames " ) )
{
g_pStringTableParticleEffectNames = networkstringtable - > FindTable ( tableName ) ;
networkstringtable - > SetAllowClientSideAddString ( g_pStringTableParticleEffectNames , true ) ;
// When the particle system list changes, we need to know immediately
g_pStringTableParticleEffectNames - > SetStringChangedCallback ( NULL , OnParticleSystemStringTableChanged ) ;
}
else if ( ! Q_strcasecmp ( tableName , " ServerMapCycle " ) )
{
g_pStringTableServerMapCycle = networkstringtable - > FindTable ( tableName ) ;
}
# ifdef TF_CLIENT_DLL
else if ( ! Q_strcasecmp ( tableName , " ServerPopFiles " ) )
{
g_pStringTableServerPopFiles = networkstringtable - > FindTable ( tableName ) ;
}
else if ( ! Q_strcasecmp ( tableName , " ServerMapCycleMvM " ) )
{
g_pStringTableServerMapCycleMvM = networkstringtable - > FindTable ( tableName ) ;
}
# endif
InstallStringTableCallback_GameRules ( ) ;
}
//-----------------------------------------------------------------------------
// Material precache
//-----------------------------------------------------------------------------
void CHLClient : : PrecacheMaterial ( const char * pMaterialName )
{
Assert ( pMaterialName ) ;
int nLen = Q_strlen ( pMaterialName ) ;
char * pTempBuf = ( char * ) stackalloc ( nLen + 1 ) ;
memcpy ( pTempBuf , pMaterialName , nLen + 1 ) ;
char * pFound = Q_strstr ( pTempBuf , " .vmt \0 " ) ;
if ( pFound )
{
* pFound = 0 ;
}
IMaterial * pMaterial = materials - > FindMaterial ( pTempBuf , TEXTURE_GROUP_PRECACHED ) ;
if ( ! IsErrorMaterial ( pMaterial ) )
{
pMaterial - > IncrementReferenceCount ( ) ;
m_CachedMaterials . AddToTail ( pMaterial ) ;
}
else
{
if ( IsOSX ( ) )
{
printf ( " \n ##### CHLClient::PrecacheMaterial could not find material %s (%s) " , pMaterialName , pTempBuf ) ;
}
}
}
void CHLClient : : UncacheAllMaterials ( )
{
for ( int i = m_CachedMaterials . Count ( ) ; - - i > = 0 ; )
{
m_CachedMaterials [ i ] - > DecrementReferenceCount ( ) ;
}
m_CachedMaterials . RemoveAll ( ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pszName -
// iSize -
// *pbuf -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CHLClient : : DispatchUserMessage ( int msg_type , bf_read & msg_data )
{
return usermessages - > DispatchUserMessage ( msg_type , msg_data ) ;
}
void SimulateEntities ( )
{
VPROF_BUDGET ( " Client SimulateEntities " , VPROF_BUDGETGROUP_CLIENT_SIM ) ;
// Service timer events (think functions).
ClientThinkList ( ) - > PerformThinkFunctions ( ) ;
// TODO: make an ISimulateable interface so C_BaseNetworkables can simulate?
{
VPROF_ ( " C_BaseEntity::Simulate " , 1 , VPROF_BUDGETGROUP_CLIENT_SIM , false , BUDGETFLAG_CLIENT ) ;
C_BaseEntityIterator iterator ;
C_BaseEntity * pEnt ;
while ( ( pEnt = iterator . Next ( ) ) ! = NULL )
{
pEnt - > Simulate ( ) ;
}
}
}
bool AddDataChangeEvent ( IClientNetworkable * ent , DataUpdateType_t updateType , int * pStoredEvent )
{
VPROF ( " AddDataChangeEvent " ) ;
Assert ( ent ) ;
// Make sure we don't already have an event queued for this guy.
if ( * pStoredEvent > = 0 )
{
Assert ( g_DataChangedEvents [ * pStoredEvent ] . m_pEntity = = ent ) ;
// DATA_UPDATE_CREATED always overrides DATA_UPDATE_CHANGED.
if ( updateType = = DATA_UPDATE_CREATED )
g_DataChangedEvents [ * pStoredEvent ] . m_UpdateType = updateType ;
return false ;
}
else
{
* pStoredEvent = g_DataChangedEvents . AddToTail ( CDataChangedEvent ( ent , updateType , pStoredEvent ) ) ;
return true ;
}
}
void ClearDataChangedEvent ( int iStoredEvent )
{
if ( iStoredEvent ! = - 1 )
g_DataChangedEvents . Remove ( iStoredEvent ) ;
}
void ProcessOnDataChangedEvents ( )
{
VPROF_ ( " ProcessOnDataChangedEvents " , 1 , VPROF_BUDGETGROUP_CLIENT_SIM , false , BUDGETFLAG_CLIENT ) ;
FOR_EACH_LL ( g_DataChangedEvents , i )
{
CDataChangedEvent * pEvent = & g_DataChangedEvents [ i ] ;
// Reset their stored event identifier.
* pEvent - > m_pStoredEvent = - 1 ;
// Send the event.
IClientNetworkable * pNetworkable = pEvent - > m_pEntity ;
pNetworkable - > OnDataChanged ( pEvent - > m_UpdateType ) ;
}
g_DataChangedEvents . Purge ( ) ;
}
void UpdateClientRenderableInPVSStatus ( )
{
// Vis for this view should already be setup at this point.
// For each client-only entity, notify it if it's newly coming into the PVS.
CUtlLinkedList < CClientEntityList : : CPVSNotifyInfo , unsigned short > & theList = ClientEntityList ( ) . GetPVSNotifiers ( ) ;
FOR_EACH_LL ( theList , i )
{
CClientEntityList : : CPVSNotifyInfo * pInfo = & theList [ i ] ;
if ( pInfo - > m_InPVSStatus & INPVS_YES )
{
// Ok, this entity already thinks it's in the PVS. No need to notify it.
// We need to set the INPVS_YES_THISFRAME flag if it's in this frame at all, so we
// don't tell the entity it's not in the PVS anymore at the end of the frame.
if ( ! ( pInfo - > m_InPVSStatus & INPVS_THISFRAME ) )
{
if ( g_pClientLeafSystem - > IsRenderableInPVS ( pInfo - > m_pRenderable ) )
{
pInfo - > m_InPVSStatus | = INPVS_THISFRAME ;
}
}
}
else
{
// This entity doesn't think it's in the PVS yet. If it is now in the PVS, let it know.
if ( g_pClientLeafSystem - > IsRenderableInPVS ( pInfo - > m_pRenderable ) )
{
pInfo - > m_InPVSStatus | = ( INPVS_YES | INPVS_THISFRAME | INPVS_NEEDSNOTIFY ) ;
}
}
}
}
void UpdatePVSNotifiers ( )
{
MDLCACHE_CRITICAL_SECTION ( ) ;
// At this point, all the entities that were rendered in the previous frame have INPVS_THISFRAME set
// so we can tell the entities that aren't in the PVS anymore so.
CUtlLinkedList < CClientEntityList : : CPVSNotifyInfo , unsigned short > & theList = ClientEntityList ( ) . GetPVSNotifiers ( ) ;
FOR_EACH_LL ( theList , i )
{
CClientEntityList : : CPVSNotifyInfo * pInfo = & theList [ i ] ;
// If this entity thinks it's in the PVS, but it wasn't in the PVS this frame, tell it so.
if ( pInfo - > m_InPVSStatus & INPVS_YES )
{
if ( pInfo - > m_InPVSStatus & INPVS_THISFRAME )
{
if ( pInfo - > m_InPVSStatus & INPVS_NEEDSNOTIFY )
{
pInfo - > m_pNotify - > OnPVSStatusChanged ( true ) ;
}
// Clear it for the next time around.
pInfo - > m_InPVSStatus & = ~ ( INPVS_THISFRAME | INPVS_NEEDSNOTIFY ) ;
}
else
{
pInfo - > m_InPVSStatus & = ~ INPVS_YES ;
pInfo - > m_pNotify - > OnPVSStatusChanged ( false ) ;
}
}
}
}
void OnRenderStart ( )
{
VPROF ( " OnRenderStart " ) ;
MDLCACHE_CRITICAL_SECTION ( ) ;
MDLCACHE_COARSE_LOCK ( ) ;
# ifdef PORTAL
g_pPortalRender - > UpdatePortalPixelVisibility ( ) ; //updating this one or two lines before querying again just isn't cutting it. Update as soon as it's cheap to do so.
# endif
partition - > SuppressLists ( PARTITION_ALL_CLIENT_EDICTS , true ) ;
C_BaseEntity : : SetAbsQueriesValid ( false ) ;
Rope_ResetCounters ( ) ;
// Interpolate server entities and move aiments.
{
PREDICTION_TRACKVALUECHANGESCOPE ( " interpolation " ) ;
C_BaseEntity : : InterpolateServerEntities ( ) ;
}
{
// vprof node for this bloc of math
VPROF ( " OnRenderStart: dirty bone caches " ) ;
// Invalidate any bone information.
C_BaseAnimating : : InvalidateBoneCaches ( ) ;
C_BaseEntity : : SetAbsQueriesValid ( true ) ;
C_BaseEntity : : EnableAbsRecomputations ( true ) ;
// Enable access to all model bones except view models.
// This is necessary for aim-ent computation to occur properly
C_BaseAnimating : : PushAllowBoneAccess ( true , false , " OnRenderStart->CViewRender::SetUpView " ) ; // pops in CViewRender::SetUpView
// FIXME: This needs to be done before the player moves; it forces
// aiments the player may be attached to to forcibly update their position
C_BaseEntity : : MarkAimEntsDirty ( ) ;
}
// Make sure the camera simulation happens before OnRenderStart, where it's used.
// NOTE: the only thing that happens in CAM_Think is thirdperson related code.
input - > CAM_Think ( ) ;
// This will place the player + the view models + all parent
// entities at the correct abs position so that their attachment points
// are at the correct location
view - > OnRenderStart ( ) ;
RopeManager ( ) - > OnRenderStart ( ) ;
// This will place all entities in the correct position in world space and in the KD-tree
C_BaseAnimating : : UpdateClientSideAnimations ( ) ;
partition - > SuppressLists ( PARTITION_ALL_CLIENT_EDICTS , false ) ;
// Process OnDataChanged events.
ProcessOnDataChangedEvents ( ) ;
// Reset the overlay alpha. Entities can change the state of this in their think functions.
g_SmokeFogOverlayAlpha = 0 ;
// This must occur prior to SimulatEntities,
// which is where the client thinks for c_colorcorrection + c_colorcorrectionvolumes
// update the color correction weights.
// FIXME: The place where IGameSystem::Update is called should be in here
// so we don't have to explicitly call ResetColorCorrectionWeights + SimulateEntities, etc.
g_pColorCorrectionMgr - > ResetColorCorrectionWeights ( ) ;
// Simulate all the entities.
SimulateEntities ( ) ;
PhysicsSimulate ( ) ;
C_BaseAnimating : : ThreadedBoneSetup ( ) ;
{
VPROF_ ( " Client TempEnts " , 0 , VPROF_BUDGETGROUP_CLIENT_SIM , false , BUDGETFLAG_CLIENT ) ;
// This creates things like temp entities.
engine - > FireEvents ( ) ;
// Update temp entities
tempents - > Update ( ) ;
// Update temp ent beams...
beams - > UpdateTempEntBeams ( ) ;
// Lock the frame from beam additions
SetBeamCreationAllowed ( false ) ;
}
// Update particle effects (eventually, the effects should use Simulate() instead of having
// their own update system).
{
// Enable FP exceptions here when FP_EXCEPTIONS_ENABLED is defined,
// to help track down bad math.
FPExceptionEnabler enableExceptions ;
VPROF_BUDGET ( " ParticleMgr()->Simulate " , VPROF_BUDGETGROUP_PARTICLE_SIMULATION ) ;
ParticleMgr ( ) - > Simulate ( gpGlobals - > frametime ) ;
}
// Now that the view model's position is setup and aiments are marked dirty, update
// their positions so they're in the leaf system correctly.
C_BaseEntity : : CalcAimEntPositions ( ) ;
// For entities marked for recording, post bone messages to IToolSystems
if ( ToolsEnabled ( ) )
{
C_BaseEntity : : ToolRecordEntities ( ) ;
}
# if defined( REPLAY_ENABLED )
// This will record any ragdolls if Replay mode is enabled on the server
CReplayRagdollRecorder : : Instance ( ) . Think ( ) ;
CReplayRagdollCache : : Instance ( ) . Think ( ) ;
# endif
// Finally, link all the entities into the leaf system right before rendering.
C_BaseEntity : : AddVisibleEntities ( ) ;
}
void OnRenderEnd ( )
{
// Disallow access to bones (access is enabled in CViewRender::SetUpView).
C_BaseAnimating : : PopBoneAccess ( " CViewRender::SetUpView->OnRenderEnd " ) ;
UpdatePVSNotifiers ( ) ;
DisplayBoneSetupEnts ( ) ;
}
void CHLClient : : FrameStageNotify ( ClientFrameStage_t curStage )
{
g_CurFrameStage = curStage ;
switch ( curStage )
{
default :
break ;
case FRAME_RENDER_START :
{
VPROF ( " CHLClient::FrameStageNotify FRAME_RENDER_START " ) ;
// Last thing before rendering, run simulation.
OnRenderStart ( ) ;
}
break ;
case FRAME_RENDER_END :
{
VPROF ( " CHLClient::FrameStageNotify FRAME_RENDER_END " ) ;
OnRenderEnd ( ) ;
PREDICTION_SPEWVALUECHANGES ( ) ;
}
break ;
case FRAME_NET_UPDATE_START :
{
VPROF ( " CHLClient::FrameStageNotify FRAME_NET_UPDATE_START " ) ;
// disabled all recomputations while we update entities
C_BaseEntity : : EnableAbsRecomputations ( false ) ;
C_BaseEntity : : SetAbsQueriesValid ( false ) ;
Interpolation_SetLastPacketTimeStamp ( engine - > GetLastTimeStamp ( ) ) ;
partition - > SuppressLists ( PARTITION_ALL_CLIENT_EDICTS , true ) ;
PREDICTION_STARTTRACKVALUE ( " netupdate " ) ;
}
break ;
case FRAME_NET_UPDATE_END :
{
ProcessCacheUsedMaterials ( ) ;
// reenable abs recomputation since now all entities have been updated
C_BaseEntity : : EnableAbsRecomputations ( true ) ;
C_BaseEntity : : SetAbsQueriesValid ( true ) ;
partition - > SuppressLists ( PARTITION_ALL_CLIENT_EDICTS , false ) ;
PREDICTION_ENDTRACKVALUE ( ) ;
}
break ;
case FRAME_NET_UPDATE_POSTDATAUPDATE_START :
{
VPROF ( " CHLClient::FrameStageNotify FRAME_NET_UPDATE_POSTDATAUPDATE_START " ) ;
PREDICTION_STARTTRACKVALUE ( " postdataupdate " ) ;
}
break ;
case FRAME_NET_UPDATE_POSTDATAUPDATE_END :
{
VPROF ( " CHLClient::FrameStageNotify FRAME_NET_UPDATE_POSTDATAUPDATE_END " ) ;
PREDICTION_ENDTRACKVALUE ( ) ;
// Let prediction copy off pristine data
prediction - > PostEntityPacketReceived ( ) ;
HLTVCamera ( ) - > PostEntityPacketReceived ( ) ;
# if defined( REPLAY_ENABLED )
ReplayCamera ( ) - > PostEntityPacketReceived ( ) ;
# endif
}
break ;
case FRAME_START :
{
// Mark the frame as open for client fx additions
SetFXCreationAllowed ( true ) ;
SetBeamCreationAllowed ( true ) ;
C_BaseEntity : : CheckCLInterpChanged ( ) ;
}
break ;
}
}
CSaveRestoreData * SaveInit ( int size ) ;
// Save/restore system hooks
CSaveRestoreData * CHLClient : : SaveInit ( int size )
{
return : : SaveInit ( size ) ;
}
void CHLClient : : SaveWriteFields ( CSaveRestoreData * pSaveData , const char * pname , void * pBaseData , datamap_t * pMap , typedescription_t * pFields , int fieldCount )
{
CSave saveHelper ( pSaveData ) ;
saveHelper . WriteFields ( pname , pBaseData , pMap , pFields , fieldCount ) ;
}
void CHLClient : : SaveReadFields ( CSaveRestoreData * pSaveData , const char * pname , void * pBaseData , datamap_t * pMap , typedescription_t * pFields , int fieldCount )
{
CRestore restoreHelper ( pSaveData ) ;
restoreHelper . ReadFields ( pname , pBaseData , pMap , pFields , fieldCount ) ;
}
void CHLClient : : PreSave ( CSaveRestoreData * s )
{
g_pGameSaveRestoreBlockSet - > PreSave ( s ) ;
}
void CHLClient : : Save ( CSaveRestoreData * s )
{
CSave saveHelper ( s ) ;
g_pGameSaveRestoreBlockSet - > Save ( & saveHelper ) ;
}
void CHLClient : : WriteSaveHeaders ( CSaveRestoreData * s )
{
CSave saveHelper ( s ) ;
g_pGameSaveRestoreBlockSet - > WriteSaveHeaders ( & saveHelper ) ;
g_pGameSaveRestoreBlockSet - > PostSave ( ) ;
}
void CHLClient : : ReadRestoreHeaders ( CSaveRestoreData * s )
{
CRestore restoreHelper ( s ) ;
g_pGameSaveRestoreBlockSet - > PreRestore ( ) ;
g_pGameSaveRestoreBlockSet - > ReadRestoreHeaders ( & restoreHelper ) ;
}
void CHLClient : : Restore ( CSaveRestoreData * s , bool b )
{
CRestore restore ( s ) ;
g_pGameSaveRestoreBlockSet - > Restore ( & restore , b ) ;
g_pGameSaveRestoreBlockSet - > PostRestore ( ) ;
}
static CUtlVector < EHANDLE > g_RestoredEntities ;
void AddRestoredEntity ( C_BaseEntity * pEntity )
{
if ( ! pEntity )
return ;
g_RestoredEntities . AddToTail ( EHANDLE ( pEntity ) ) ;
}
void CHLClient : : DispatchOnRestore ( )
{
for ( int i = 0 ; i < g_RestoredEntities . Count ( ) ; i + + )
{
if ( g_RestoredEntities [ i ] ! = NULL )
{
MDLCACHE_CRITICAL_SECTION ( ) ;
g_RestoredEntities [ i ] - > OnRestore ( ) ;
}
}
g_RestoredEntities . RemoveAll ( ) ;
}
void CHLClient : : WriteSaveGameScreenshot ( const char * pFilename )
{
view - > WriteSaveGameScreenshot ( pFilename ) ;
}
// Given a list of "S(wavname) S(wavname2)" tokens, look up the localized text and emit
// the appropriate close caption if running with closecaption = 1
void CHLClient : : EmitSentenceCloseCaption ( char const * tokenstream )
{
extern ConVar closecaption ;
if ( ! closecaption . GetBool ( ) )
return ;
CHudCloseCaption * hudCloseCaption = GET_HUDELEMENT ( CHudCloseCaption ) ;
if ( hudCloseCaption )
{
hudCloseCaption - > ProcessSentenceCaptionStream ( tokenstream ) ;
}
}
void CHLClient : : EmitCloseCaption ( char const * captionname , float duration )
{
extern ConVar closecaption ;
if ( ! closecaption . GetBool ( ) )
return ;
CHudCloseCaption * hudCloseCaption = GET_HUDELEMENT ( CHudCloseCaption ) ;
if ( hudCloseCaption )
{
hudCloseCaption - > ProcessCaption ( captionname , duration ) ;
}
}
CStandardRecvProxies * CHLClient : : GetStandardRecvProxies ( )
{
return & g_StandardRecvProxies ;
}
bool CHLClient : : CanRecordDemo ( char * errorMsg , int length ) const
{
if ( GetClientModeNormal ( ) )
{
return GetClientModeNormal ( ) - > CanRecordDemo ( errorMsg , length ) ;
}
return true ;
}
void CHLClient : : OnDemoRecordStart ( char const * pDemoBaseName )
{
}
void CHLClient : : OnDemoRecordStop ( )
{
}
void CHLClient : : OnDemoPlaybackStart ( char const * pDemoBaseName )
{
# if defined( REPLAY_ENABLED )
// Load any ragdoll override frames from disk
char szRagdollFile [ MAX_OSPATH ] ;
V_snprintf ( szRagdollFile , sizeof ( szRagdollFile ) , " %s.dmx " , pDemoBaseName ) ;
CReplayRagdollCache : : Instance ( ) . Init ( szRagdollFile ) ;
# endif
}
void CHLClient : : OnDemoPlaybackStop ( )
{
# ifdef DEMOPOLISH_ENABLED
if ( DemoPolish_GetController ( ) . m_bInit )
{
DemoPolish_GetController ( ) . Shutdown ( ) ;
}
# endif
# if defined( REPLAY_ENABLED )
CReplayRagdollCache : : Instance ( ) . Shutdown ( ) ;
# endif
}
int CHLClient : : GetScreenWidth ( )
{
return ScreenWidth ( ) ;
}
int CHLClient : : GetScreenHeight ( )
{
return ScreenHeight ( ) ;
}
// NEW INTERFACES
// save game screenshot writing
void CHLClient : : WriteSaveGameScreenshotOfSize ( const char * pFilename , int width , int height , bool bCreatePowerOf2Padded /*=false*/ ,
bool bWriteVTF /*=false*/ )
{
view - > WriteSaveGameScreenshotOfSize ( pFilename , width , height , bCreatePowerOf2Padded , bWriteVTF ) ;
}
// See RenderViewInfo_t
void CHLClient : : RenderView ( const CViewSetup & setup , int nClearFlags , int whatToDraw )
{
VPROF ( " RenderView " ) ;
view - > RenderView ( setup , nClearFlags , whatToDraw ) ;
}
void ReloadSoundEntriesInList ( IFileList * pFilesToReload ) ;
//-----------------------------------------------------------------------------
// For sv_pure mode. The filesystem figures out which files the client needs to reload to be "pure" ala the server's preferences.
//-----------------------------------------------------------------------------
void CHLClient : : ReloadFilesInList ( IFileList * pFilesToReload )
{
ReloadParticleEffectsInList ( pFilesToReload ) ;
ReloadSoundEntriesInList ( pFilesToReload ) ;
}
bool CHLClient : : HandleUiToggle ( )
{
# if defined( REPLAY_ENABLED )
if ( ! g_pEngineReplay | | ! g_pEngineReplay - > IsSupportedModAndPlatform ( ) )
return false ;
CReplayPerformanceEditorPanel * pEditor = ReplayUI_GetPerformanceEditor ( ) ;
if ( ! pEditor )
return false ;
pEditor - > HandleUiToggle ( ) ;
return true ;
# else
return false ;
# endif
}
bool CHLClient : : ShouldAllowConsole ( )
{
return true ;
}
CRenamedRecvTableInfo * CHLClient : : GetRenamedRecvTableInfos ( )
{
return g_pRenamedRecvTableInfoHead ;
}
CMouthInfo g_ClientUIMouth ;
// Get the mouthinfo for the sound being played inside UI panels
CMouthInfo * CHLClient : : GetClientUIMouthInfo ( )
{
return & g_ClientUIMouth ;
}
void CHLClient : : FileReceived ( const char * fileName , unsigned int transferID )
{
if ( g_pGameRules )
{
g_pGameRules - > OnFileReceived ( fileName , transferID ) ;
}
}
void CHLClient : : ClientAdjustStartSoundParams ( StartSoundParams_t & params )
{
# ifdef TF_CLIENT_DLL
CBaseEntity * pEntity = ClientEntityList ( ) . GetEnt ( params . soundsource ) ;
// A player speaking
if ( params . entchannel = = CHAN_VOICE & & GameRules ( ) & & pEntity & & pEntity - > IsPlayer ( ) )
{
// Use high-pitched voices for other players if the local player has an item that allows them to hear it (Pyro Goggles)
if ( ! GameRules ( ) - > IsLocalPlayer ( params . soundsource ) & & IsLocalPlayerUsingVisionFilterFlags ( TF_VISION_FILTER_PYRO ) )
{
params . pitch * = 1.3f ;
}
// Halloween voice futzery?
else
{
float flHeadScale = 1.f ;
CALL_ATTRIB_HOOK_FLOAT_ON_OTHER ( pEntity , flHeadScale , head_scale ) ;
int iHalloweenVoiceSpell = 0 ;
CALL_ATTRIB_HOOK_INT_ON_OTHER ( pEntity , iHalloweenVoiceSpell , halloween_voice_modulation ) ;
if ( iHalloweenVoiceSpell > 0 )
{
params . pitch * = 0.8f ;
}
else if ( flHeadScale ! = 1.f )
{
// Big head, deep voice
if ( flHeadScale > 1.f )
{
params . pitch * = 0.8f ;
}
else // Small head, high voice
{
params . pitch * = 1.3f ;
}
}
}
}
# endif
}
const char * CHLClient : : TranslateEffectForVisionFilter ( const char * pchEffectType , const char * pchEffectName )
{
if ( ! GameRules ( ) )
return pchEffectName ;
return GameRules ( ) - > TranslateEffectForVisionFilter ( pchEffectType , pchEffectName ) ;
}
bool CHLClient : : DisconnectAttempt ( void )
{
bool bRet = false ;
# if defined( TF_CLIENT_DLL )
bRet = HandleDisconnectAttempt ( ) ;
# endif
return bRet ;
}
bool CHLClient : : IsConnectedUserInfoChangeAllowed ( IConVar * pCvar )
{
return GameRules ( ) ? GameRules ( ) - > IsConnectedUserInfoChangeAllowed ( NULL ) : true ;
}
# ifndef NO_STEAM
CSteamID GetSteamIDForPlayerIndex ( int iPlayerIndex )
{
player_info_t pi ;
if ( steamapicontext & & steamapicontext - > SteamUtils ( ) )
{
if ( engine - > GetPlayerInfo ( iPlayerIndex , & pi ) )
{
if ( pi . friendsID )
{
return CSteamID ( pi . friendsID , 1 , steamapicontext - > SteamUtils ( ) - > GetConnectedUniverse ( ) , k_EAccountTypeIndividual ) ;
}
}
}
return CSteamID ( ) ;
}
# endif
void CHLClient : : IN_TouchEvent ( int type , int fingerId , int x , int y )
{
if ( enginevgui - > IsGameUIVisible ( ) )
return ;
touch_event_t ev ;
ev . type = type ;
ev . fingerid = fingerId ;
memcpy ( & ev . x , & x , sizeof ( ev . x ) ) ;
memcpy ( & ev . y , & y , sizeof ( ev . y ) ) ;
if ( type = = IE_FingerMotion )
inputsystem - > GetTouchAccumulators ( fingerId , ev . dx , ev . dy ) ;
gTouch . ProcessEvent ( & ev ) ;
}