//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // //=============================================================================// #ifndef BASECLIENTSTATE_H #define BASECLIENTSTATE_H #ifdef _WIN32 #pragma once #endif #include #include #include #include #include #include "common.h" #include "clockdriftmgr.h" #include "convar.h" #include "cl_bounded_cvars.h" // Only send this many requests before timing out. #define CL_CONNECTION_RETRIES 4 // Mininum time gap (in seconds) before a subsequent connection request is sent. #define CL_MIN_RESEND_TIME 1.5f // Max time. The cvar cl_resend is bounded by these. #define CL_MAX_RESEND_TIME 20.0f // In release, send commands at least this many times per second #define MIN_CMD_RATE 10.0f #define MAX_CMD_RATE 100.0f extern ConVar cl_name; // This represents a server's class C_ServerClassInfo { public: C_ServerClassInfo(); ~C_ServerClassInfo(); public: ClientClass *m_pClientClass; char *m_ClassName; char *m_DatatableName; // This is an index into the network string table (cl.GetInstanceBaselineTable()). int m_InstanceBaselineIndex; // INVALID_STRING_INDEX if not initialized yet. }; #define EndGameAssertMsg( assertion, msg ) \ if ( !(assertion) )\ Host_EndGame msg class CNetworkStringTableContainer; class PackedEntity; class INetworkStringTable; class CEntityReadInfo; abstract_class CBaseClientState : public INetChannelHandler, public IConnectionlessPacketHandler, public IServerMessageHandler { public: CBaseClientState(); virtual ~CBaseClientState(); public: // IConnectionlessPacketHandler interface: virtual bool ProcessConnectionlessPacket(struct netpacket_s *packet); public: // INetMsgHandler interface: virtual void ConnectionStart(INetChannel *chan); virtual void ConnectionClosing( const char *reason ); virtual void ConnectionCrashed(const char *reason); virtual void PacketStart(int incoming_sequence, int outgoing_acknowledged) {}; virtual void PacketEnd( void ) {}; virtual void FileReceived( const char *fileName, unsigned int transferID ); virtual void FileRequested( const char *fileName, unsigned int transferID ); virtual void FileDenied( const char *fileName, unsigned int transferID ); virtual void FileSent( const char *fileName, unsigned int transferID ); public: // IServerMessageHandlers PROCESS_NET_MESSAGE( Tick ); PROCESS_NET_MESSAGE( StringCmd ); PROCESS_NET_MESSAGE( SetConVar ); PROCESS_NET_MESSAGE( SignonState ); PROCESS_SVC_MESSAGE( Print ); PROCESS_SVC_MESSAGE( ServerInfo ); PROCESS_SVC_MESSAGE( SendTable ); PROCESS_SVC_MESSAGE( ClassInfo ); PROCESS_SVC_MESSAGE( SetPause ); PROCESS_SVC_MESSAGE( CreateStringTable ); PROCESS_SVC_MESSAGE( UpdateStringTable ); PROCESS_SVC_MESSAGE( SetView ); PROCESS_SVC_MESSAGE( PacketEntities ); PROCESS_SVC_MESSAGE( Menu ); PROCESS_SVC_MESSAGE( GameEventList ); PROCESS_SVC_MESSAGE( GetCvarValue ); PROCESS_SVC_MESSAGE( CmdKeyValues ); PROCESS_SVC_MESSAGE( SetPauseTimed ); // Returns dem file protocol version, or, if not playing a demo, just returns PROTOCOL_VERSION virtual int GetDemoProtocolVersion() const; public: inline bool IsActive( void ) const { return m_nSignonState == SIGNONSTATE_FULL; }; inline bool IsConnected( void ) const { return m_nSignonState >= SIGNONSTATE_CONNECTED; }; virtual void Clear( void ); virtual void FullConnect( netadr_t &adr ); // a connection was established virtual void Connect(const char* adr, const char *pszSourceTag); // start a connection challenge virtual bool SetSignonState ( int state, int count ); virtual void Disconnect( const char *pszReason, bool bShowMainMenu ); virtual void SendConnectPacket (int challengeNr, int authProtocol, uint64 unGSSteamID, bool bGSSecure ); virtual const char *GetCDKeyHash() { return "123"; } virtual void RunFrame ( void ); virtual void CheckForResend ( void ); virtual void InstallStringTableCallback( char const *tableName ) { } virtual bool HookClientStringTable( char const *tableName ) { return false; } virtual bool LinkClasses( void ); virtual int GetConnectionRetryNumber() const { return CL_CONNECTION_RETRIES; } virtual const char *GetClientName() { return cl_name.GetString(); } static ClientClass* FindClientClass(const char *pClassName); CClockDriftMgr& GetClockDriftMgr(); int GetClientTickCount() const; // Get the client tick count. void SetClientTickCount( int tick ); int GetServerTickCount() const; void SetServerTickCount( int tick ); void SetClientAndServerTickCount( int tick ); INetworkStringTable *GetStringTable( const char * name ) const; PackedEntity *GetEntityBaseline( int iBaseline, int nEntityIndex ); void SetEntityBaseline(int iBaseline, ClientClass *pClientClass, int index, char *packedData, int length); void CopyEntityBaseline( int iFrom, int iTo ); void FreeEntityBaselines(); bool GetClassBaseline( int iClass, void const **pData, int *pDatalen ); ClientClass *GetClientClass( int i ); void ForceFullUpdate( void ); void SendStringCmd(const char * command); void ReadPacketEntities( CEntityReadInfo &u ); virtual void ReadEnterPVS( CEntityReadInfo &u ) = 0; virtual void ReadLeavePVS( CEntityReadInfo &u ) = 0; virtual void ReadDeltaEnt( CEntityReadInfo &u ) = 0; virtual void ReadPreserveEnt( CEntityReadInfo &u ) = 0; virtual void ReadDeletions( CEntityReadInfo &u ) = 0; bool IsClientConnectionViaMatchMaking( void ); static bool ConnectMethodAllowsRedirects( void ); private: bool PrepareSteamConnectResponse( uint64 unGSSteamID, bool bGSSecure, const netadr_t &adr, bf_write &msg ); public: // Connection to server. int m_Socket; // network socket INetChannel *m_NetChannel; // Our sequenced channel to the remote server. unsigned int m_nChallengeNr; // connection challenge number double m_flConnectTime; // If gap of connect_time to net_time > 3000, then resend connect packet int m_nRetryNumber; // number of retry connection attemps char m_szRetryAddress[ MAX_OSPATH ]; CUtlString m_sRetrySourceTag; // string that describes why we decided to connect to this server (empty for command line, "serverbrowser", "quickplay", etc) int m_retryChallenge; // challenge we sent to the server int m_nSignonState; // see SIGNONSTATE_* definitions double m_flNextCmdTime; // When can we send the next command packet? int m_nServerCount; // server identification for prespawns, must match the svs.spawncount which // is incremented on server spawning. This supercedes svs.spawn_issued, in that // we can now spend a fair amount of time sitting connected to the server // but downloading models, sounds, etc. So much time that it is possible that the // server might change levels again and, if so, we need to know that. uint64 m_ulGameServerSteamID; // Steam ID of the game server we are trying to connect to, or are connected to. Zero if unknown int m_nCurrentSequence; // this is the sequence number of the current incoming packet CClockDriftMgr m_ClockDriftMgr; int m_nDeltaTick; // last valid received snapshot (server) tick bool m_bPaused; // send over by server float m_flPausedExpireTime; int m_nViewEntity; // cl_entitites[cl.viewentity] == player point of view int m_nPlayerSlot; // own player entity index-1. skips world. Add 1 to get cl_entitites index; char m_szLevelFileName[ 128 ]; // for display on solo scoreboard char m_szLevelBaseName[ 128 ]; // removes maps/ and .bsp extension int m_nMaxClients; // max clients on server PackedEntity *m_pEntityBaselines[2][MAX_EDICTS]; // storing entity baselines // This stuff manages the receiving of data tables and instantiating of client versions // of server-side classes. C_ServerClassInfo *m_pServerClasses; int m_nServerClasses; int m_nServerClassBits; char m_szEncrytionKey[STEAM_KEYSIZE]; unsigned int m_iEncryptionKeySize; CNetworkStringTableContainer *m_StringTableContainer; bool m_bRestrictServerCommands; // If true, then the server is only allowed to execute commands marked with FCVAR_SERVER_CAN_EXECUTE on the client. bool m_bRestrictClientCommands; // If true, then IVEngineClient::ClientCmd is only allowed to execute commands marked with FCVAR_CLIENTCMD_CAN_EXECUTE on the client. }; inline CClockDriftMgr& CBaseClientState::GetClockDriftMgr() { return m_ClockDriftMgr; } inline void CBaseClientState::SetClientTickCount( int tick ) { m_ClockDriftMgr.m_nClientTick = tick; } inline int CBaseClientState::GetClientTickCount() const { return m_ClockDriftMgr.m_nClientTick; } inline int CBaseClientState::GetServerTickCount() const { return m_ClockDriftMgr.m_nServerTick; } inline void CBaseClientState::SetServerTickCount( int tick ) { m_ClockDriftMgr.m_nServerTick = tick; } inline void CBaseClientState::SetClientAndServerTickCount( int tick ) { m_ClockDriftMgr.m_nServerTick = m_ClockDriftMgr.m_nClientTick = tick; } #endif // BASECLIENTSTATE_H