Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

476 lines
17 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #ifndef HLTVSERVER_H
  7. #define HLTVSERVER_H
  8. #ifdef _WIN32
  9. #pragma once
  10. #endif
  11. #include "baseserver.h"
  12. #include "hltvclient.h"
  13. #include "hltvdemo.h"
  14. #include "hltvbroadcast.h"
  15. #include "hltvclientstate.h"
  16. #include "clientframe.h"
  17. #include "networkstringtable.h"
  18. #include <ihltv.h>
  19. #include <convar.h>
  20. #define HLTV_BUFFER_VOICE 0 // player voice data
  21. #define HLTV_BUFFER_SOUNDS 1 // unreliable sounds
  22. #define HLTV_BUFFER_TEMPENTS 2 // temporary/event entities
  23. #define HLTV_BUFFER_RELIABLE 3 // reliable messages
  24. #define HLTV_BUFFER_UNRELIABLE 4 // unreliable messages
  25. #define HLTV_BUFFER_MAX 5 // end marker
  26. // proxy dispatch modes
  27. #define DISPATCH_MODE_OFF 0
  28. #define DISPATCH_MODE_AUTO 1
  29. #define DISPATCH_MODE_ALWAYS 2
  30. extern ConVar tv_debug;
  31. class CHLTVFrame : public CClientFrame
  32. {
  33. public:
  34. CHLTVFrame();
  35. virtual ~CHLTVFrame();
  36. void Reset(); // resets all data & buffers
  37. void FreeBuffers();
  38. void AllocBuffers();
  39. bool HasData();
  40. void CopyHLTVData( const CHLTVFrame &frame );
  41. virtual bool IsMemPoolAllocated() { return false; }
  42. uint GetMemSize()const;
  43. public:
  44. // message buffers:
  45. bf_write m_Messages[HLTV_BUFFER_MAX];
  46. };
  47. struct CFrameCacheEntry_s
  48. {
  49. CClientFrame* pFrame;
  50. int nTick;
  51. };
  52. class CDeltaEntityCache
  53. {
  54. struct DeltaEntityEntry_s
  55. {
  56. DeltaEntityEntry_s *pNext;
  57. int nDeltaTick;
  58. int nBits;
  59. };
  60. public:
  61. CDeltaEntityCache();
  62. ~CDeltaEntityCache();
  63. void SetTick( int nTick, int nMaxEntities );
  64. unsigned char* FindDeltaBits( int nEntityIndex, int nDeltaTick, int &nBits );
  65. void AddDeltaBits( int nEntityIndex, int nDeltaTick, int nBits, bf_write *pBuffer );
  66. void Flush();
  67. protected:
  68. int m_nTick; // current tick
  69. int m_nMaxEntities; // max entities = length of cache
  70. int m_nCacheSize;
  71. DeltaEntityEntry_s* m_Cache[MAX_EDICTS]; // array of pointers to delta entries
  72. };
  73. class CGameClient;
  74. class CGameServer;
  75. class IHLTVDirector;
  76. class CHLTVServer : public IGameEventListener2, public CBaseServer, public CClientFrameManager, public IHLTVServer, public IDemoPlayer
  77. {
  78. friend class CHLTVClientState;
  79. typedef CBaseServer BaseClass;
  80. public:
  81. CHLTVServer( uint nInstance, float flSnapshotRate );
  82. virtual ~CHLTVServer();
  83. public: // CBaseServer interface:
  84. void Init (bool bIsDedicated);
  85. void Shutdown( void );
  86. void Clear( void );
  87. bool IsHLTV( void ) const { return true; };
  88. bool IsMultiplayer( void ) const { return true; };
  89. void FillServerInfo(CSVCMsg_ServerInfo &serverinfo);
  90. void GetNetStats( float &avgIn, float &avgOut );
  91. int GetChallengeType ( const ns_address &adr );
  92. const char *GetName( void ) const;
  93. const char *GetPassword() const;
  94. const char *GetHltvRelayPassword() const;
  95. IClient *ConnectClient ( const ns_address &adr, int protocol, int challenge, int authProtocol,
  96. const char *name, const char *password, const char *hashedCDkey, int cdKeyLen,
  97. CUtlVector< CCLCMsg_SplitPlayerConnect_t * > & splitScreenClients, bool isClientLowViolence, CrossPlayPlatform_t clientPlatform,
  98. const byte *pbEncryptionKey, int nEncryptionKeyIndex ) OVERRIDE;
  99. virtual bool GetRedirectAddressForConnectClient( const ns_address &adr, CUtlVector< CCLCMsg_SplitPlayerConnect_t* > & splitScreenClients, ns_address *pNetAdrRedirect ) OVERRIDE;
  100. bool CheckHltvPasswordMatch( const char *szPasswordProvidedByClient, const char *szServerRequiredPassword, CSteamID steamidClient );
  101. virtual bool GetClassBaseline( ServerClass *pClass, SerializedEntityHandle_t *pHandle);
  102. public:
  103. void FireGameEvent(IGameEvent *event);
  104. int m_nDebugID;
  105. int GetEventDebugID( void );
  106. public: // IHLTVServer interface:
  107. IServer *GetBaseServer( void );
  108. IHLTVDirector *GetDirector( void );
  109. int GetHLTVSlot( void ); // return entity index-1 of HLTV in game
  110. float GetOnlineTime( void ); // seconds since broadcast started
  111. void GetLocalStats( int &proxies, int &slots, int &clients );
  112. void GetGlobalStats( int &proxies, int &slots, int &clients );
  113. void GetExternalStats( int &numExternalTotalViewers, int &numExternalLinkedViewers );
  114. void GetRelayStats( int &proxies, int &slots, int &clients );
  115. bool IsMasterProxy( void ); // true, if this is the HLTV master proxy
  116. bool IsTVRelay(); // true if we're running a relay (i.e. this is the opposite of IsMasterProxy()).
  117. bool IsDemoPlayback( void ); // true if this is a HLTV demo
  118. const netadr_t *GetRelayAddress( void ); // returns relay address
  119. void BroadcastEvent(IGameEvent *event);
  120. virtual void StopRecording( const CGameInfo *pGameInfo = NULL ) { StopRecordingAndFreeFrames( false, pGameInfo ); }
  121. //similar to the standard stop recording, but this allows for specifying a tick before which frames can be dropped. This is very useful for
  122. //shutdown to prevent memory spikes
  123. void StopRecordingAndFreeFrames( bool bFreeClientFrames, const CGameInfo *pGameInfo = NULL );
  124. virtual bool IsRecording();
  125. virtual const char* GetRecordingDemoFilename();
  126. virtual void StartAutoRecording();
  127. public: // IDemoPlayer interface
  128. CDemoFile *GetDemoFile();
  129. int GetPlaybackStartTick( void );
  130. int GetPlaybackTick( void );
  131. bool StartPlayback( const char *filename, bool bAsTimeDemo, CDemoPlaybackParameters_t const *pPlaybackParameters, int );
  132. CDemoPlaybackParameters_t const * GetDemoPlaybackParameters() OVERRIDE { return NULL; }
  133. bool IsPlayingBack( void )const; // true if demo loaded and playing back
  134. bool IsPlaybackPaused( void )const; // true if playback paused
  135. bool IsPlayingTimeDemo( void ) const { return false; } // true if playing back in timedemo mode
  136. bool IsSkipping( void ) const { return false; }; // true, if demo player skiiping trough packets
  137. bool CanSkipBackwards( void ) const { return true; } // true if demoplayer can skip backwards
  138. void SetPlaybackTimeScale( float timescale ); // sets playback timescale
  139. float GetPlaybackTimeScale( void ); // get playback timescale
  140. void PausePlayback( float seconds ) {};
  141. void SkipToTick( int tick, bool bRelative, bool bPause ) {};
  142. void SkipToImportantTick( const DemoImportantTick_t *pTick ) {};
  143. void ResumePlayback( void ) {};
  144. void StopPlayback( void ) {};
  145. void InterpolateViewpoint() {};
  146. netpacket_t *ReadPacket( void ) { return NULL; }
  147. void ResetDemoInterpolation( void ) {};
  148. void SetPacketReadSuspended( bool bSuspendPacketReading ) {};
  149. void SetImportantEventData( const KeyValues *pData ) {};
  150. int FindNextImportantTick( int nCurrentTick, const char *pEventName = NULL ) { return -1; } // -1 = no next important tick
  151. int FindPreviousImportantTick( int nCurrentTick, const char *pEventName = NULL ) { return -1; } // -1 = no previous important tick
  152. const DemoImportantTick_t *GetImportantTick( int nIndex ) { return NULL; }
  153. const DemoImportantGameEvent_t *GetImportantGameEvent( const char *pszEventName ) { return NULL; }
  154. void ListImportantTicks( void ) {};
  155. void ListHighlightData( void ) {};
  156. void SetHighlightXuid( uint64 xuid, bool bLowlights ) {};
  157. bool ScanDemo( const char* filename, const char* pszMode ) { return false; };
  158. public:
  159. void StartMaster(CGameClient *client); // start HLTV server as master proxy
  160. void ConnectRelay(const char *address); // connect to other HLTV proxy
  161. void StartDemo(const char *filename); // starts playing back a demo file
  162. void StartBroadcast();
  163. void StartRelay( void ); // start HLTV server as relay proxy
  164. bool SendNetMsg( INetMessage &msg, bool bForceReliable = false, bool bVoice = false );
  165. bool NETMsg_PlayerAvatarData( const CNETMsg_PlayerAvatarData& msg );
  166. void RunFrame();
  167. void SetMaxClients( int number );
  168. void Changelevel( bool bInactivateClients );
  169. void UserInfoChanged( int nClientIndex );
  170. void SendClientMessages ( bool bSendSnapshots );
  171. bool SendClientMessages( CHLTVClient *pClient );
  172. CClientFrame *AddNewFrame( CClientFrame * pFrame ); // add new frame, returns HLTV's copy
  173. void SignonComplete( void );
  174. void LinkInstanceBaselines( void );
  175. void BroadcastEventLocal( IGameEvent *event, bool bReliable ); // broadcast event but not to relay proxies
  176. void BroadcastLocalChat( const char *pszChat, const char *pszGroup ); // broadcast event but not to relay proxies
  177. void BroadcastLocalTitle( CHLTVClient *client = NULL ); // NULL = broadcast to all
  178. bool DispatchToRelay( CHLTVClient *pClient);
  179. bf_write *GetBuffer( int nBuffer);
  180. CClientFrame *GetDeltaFrame( int nTick );
  181. CClientFrame *ExpandAndGetClientFrame( int nTick, bool bExact );
  182. inline CHLTVClient* Client( int i ) { return static_cast<CHLTVClient*>(m_Clients[i]); }
  183. //called to add a new frame to HLTV by the server, which will be encoded as a delta frame instead of a raw frame, which will then be held in transit and expanded once
  184. //it is time to be replayed to clients (helps to save a huge amount of memory for long delays)
  185. void AddNewDeltaFrame( CClientFrame *pClientFrame );
  186. void UpdateHltvExternalViewers( uint32 numTotalViewers, uint32 numLinkedViewers );
  187. void DumpMem();
  188. uint GetInstanceIndex()const { return m_nInstanceIndex; }
  189. float GetSnapshotRate()const { return m_flSnapshotRate; }
  190. void FixupConvars( CNETMsg_SetConVar_t &convars );
  191. protected:
  192. virtual bool ShouldUpdateMasterServer();
  193. private:
  194. CBaseClient *CreateNewClient( int slot );
  195. void UpdateTick( void );
  196. void UpdateStats( void );
  197. void InstallStringTables( void );
  198. void UninstallStringTables( void );
  199. void RestoreTick( int tick );
  200. void EntityPVSCheck( CClientFrame *pFrame );
  201. void InitClientRecvTables();
  202. void FreeClientRecvTables();
  203. void ReadCompleteDemoFile();
  204. void ResyncDemoClock();
  205. //when frames come in, we delta compress them to strip out all of the state that hasn't changed. This is necessary since otherwise the HLTV will have to hold ALL state for all frames
  206. //that are buffered, which is far too costly
  207. struct SHLTVDeltaEntity_t
  208. {
  209. //a constant used to denote that no packed data is associated with this object
  210. static const SerializedEntityHandle_t knNoPackedData = (SerializedEntityHandle_t)-1;
  211. SHLTVDeltaEntity_t();
  212. ~SHLTVDeltaEntity_t();
  213. //the original index that we came from
  214. uint16 m_nSourceIndex;
  215. //how many proxy recipients should be associated with this entity (note this can be non-zero but have a NULL pointer indicating no value changes)
  216. uint16 m_nNumRecipients;
  217. //the serial number of this entity (this might be able to be 16 bits which would be nice)
  218. int32 m_nSerialNumber;
  219. // This is the tick this PackedEntity was created on (-1 means reuse the previous one)
  220. int32 m_nSnapshotCreationTick;
  221. //the class that this entity maps to
  222. ServerClass *m_pServerClass;
  223. //pointer to the new recipient values if different
  224. CSendProxyRecipients *m_pNewRecipients;
  225. //the delta encoded properties that have changed since the last tick. Note that this can be NULL or NoPackedData to represent that certain parts of the reconstructed class are missing
  226. SerializedEntityHandle_t m_SerializedEntity;
  227. //the next entity in our list
  228. SHLTVDeltaEntity_t *m_pNext;
  229. };
  230. struct SHLTVDeltaFrame_t
  231. {
  232. SHLTVDeltaFrame_t();
  233. ~SHLTVDeltaFrame_t();
  234. //a bit list that contains all of the entities that should just be copied forward
  235. uint32 *m_pCopyEntities;
  236. //the client frame which contains a custom snap shot that has been allocated
  237. CHLTVFrame *m_pClientFrame;
  238. //the entities that we have delta compressed, these will be expanded into the snapshot when needed (we only store entries for valid ones)
  239. SHLTVDeltaEntity_t *m_pEntities;
  240. uint32 m_nNumValidEntities;
  241. //the total number of entities that were in the list so we can expand and have the necessary gaps
  242. uint32 m_nTotalEntities;
  243. //our previous snapshot that we delta compressed from, used to expand out the properties when needed
  244. CFrameSnapshot *m_pRelativeFrame;
  245. //This points to the original snapshot it was generated from. This is intended only for development testing/validation
  246. CFrameSnapshot *m_pSourceFrame;
  247. //the next frame in our list (newest is at the tail of the list)
  248. SHLTVDeltaFrame_t *m_pNewerDeltaFrame;
  249. size_t GetMemSize()const;
  250. };
  251. //the newest delta frame that we've encoded
  252. SHLTVDeltaFrame_t *m_pOldestDeltaFrame;
  253. SHLTVDeltaFrame_t *m_pNewestDeltaFrame;
  254. //the last frame that we took a snapshot from (so we can delta encode subsequent ones)
  255. CFrameSnapshot *m_pLastSourceSnapshot;
  256. CFrameSnapshot *m_pLastTargetSnapshot;
  257. //given a source snapshot, this will create a copy of it for the delta encoding, so it has all data except the entities
  258. CFrameSnapshot* CloneDeltaSnapshot( const CFrameSnapshot *pCopySnapshot );
  259. //given a current frame being encoded, and a previous frame that was last encoded, this will handle creating a packed list of the entities and adding this list to
  260. //the provided HLTV delta frame
  261. void CreateDeltaFrameEntities( SHLTVDeltaFrame_t* pOutputEntities, const CFrameSnapshot *pCurrFrame, const CFrameSnapshot *pPrevFrame );
  262. //given a delta frame, this will expand the snapshot to be a full absolute snapshot
  263. void ExpandDeltaFrameToFullFrame( SHLTVDeltaFrame_t *pDeltaFrame );
  264. //called to handle converting all queued delta frames to full frames up to the specified tick (inclusive). This will handle removing them from
  265. //the delta queue and adding them to the client frame list
  266. void ExpandDeltaFramesToTick( int nTick );
  267. //called to free all delta frames that are queued
  268. void FreeAllDeltaFrames( );
  269. virtual IDemoStream *GetDemoStream() OVERRIDE { return &m_DemoFile; }
  270. public:
  271. CGameClient *m_MasterClient; // if != NULL, this is the master HLTV
  272. CHLTVClientState m_ClientState;
  273. CHLTVDemoRecorder m_DemoRecorder; // HLTV demo object for recording and playback
  274. CHLTVBroadcast m_Broadcast;
  275. CGameServer *m_Server; // pointer to source server (sv.)
  276. IHLTVDirector *m_Director; // HTLV director exported by game.dll
  277. int m_nFirstTick; // first known server tick;
  278. int m_nLastTick; // last tick from AddFrame()
  279. CHLTVFrame *m_CurrentFrame; // current delayed HLTV frame
  280. int m_nViewEntity; // the current entity HLTV is tracking
  281. int m_nPlayerSlot; // slot of HLTV client on game server
  282. CHLTVFrame m_HLTVFrame; // all incoming messages go here until Snapshot is made
  283. bool m_bSignonState; // true if connecting to server
  284. float m_flStartTime;
  285. float m_flFPS; // FPS the proxy is running;
  286. int m_nGameServerMaxClients; // max clients on game server
  287. float m_fNextSendUpdateTime; // time to send next HLTV status messages
  288. RecvTable *m_pRecvTables[MAX_DATATABLES];
  289. int m_nRecvTables;
  290. Vector m_vPVSOrigin;
  291. bool m_bMasterOnlyMode;
  292. netadr_t m_RootServer; // HLTV root server
  293. int m_nGlobalSlots;
  294. int m_nGlobalClients;
  295. int m_nGlobalProxies;
  296. int m_nExternalTotalViewers;
  297. int m_nExternalLinkedViewers;
  298. char m_DemoEventsBuffer[NET_MAX_DATAGRAM_PAYLOAD];
  299. bf_write m_DemoEventWriteBuffer;
  300. CNetworkStringTableContainer m_NetworkStringTables;
  301. CDeltaEntityCache m_DeltaCache;
  302. CUtlVector<CFrameCacheEntry_s> m_FrameCache;
  303. CThreadFastMutex m_FrameCacheMutex; // locks frame cache
  304. typedef CUtlMap< uint32, CNETMsg_PlayerAvatarData_t *, int, CDefLess< uint32 > > PlayerAvatarDataMap_t;
  305. PlayerAvatarDataMap_t m_mapPlayerAvatarData;
  306. // demoplayer stuff:
  307. CDemoFile m_DemoFile; // for demo playback
  308. int m_nStartTick;
  309. democmdinfo_t m_LastCmdInfo;
  310. bool m_bPlayingBack;
  311. bool m_bPlaybackPaused; // true if demo is paused right now
  312. float m_flPlaybackRateModifier;
  313. int m_nSkipToTick; // skip to tick ASAP, -1 = off
  314. const uint m_nInstanceIndex;
  315. float m_flSnapshotRate;
  316. };
  317. enum { HLTV_SERVER_MAX_COUNT = 2 };
  318. extern CHLTVServer *g_pHltvServer[ HLTV_SERVER_MAX_COUNT ]; // The global HLTV server/object. NULL on xbox.
  319. extern bool IsHltvActive();
  320. // given the con-command arguments, selects one or more hltv servers and enumerates them, iterator (of a vector of HLTV servers) style
  321. class CActiveHltvServerSelector
  322. {
  323. protected:
  324. int m_nIndex, m_nMask;
  325. public:
  326. CActiveHltvServerSelector( const CCommand &args );
  327. operator CHLTVServer* ( )
  328. {
  329. return m_nIndex < HLTV_SERVER_MAX_COUNT ? g_pHltvServer[ m_nIndex ] : NULL;
  330. }
  331. CHLTVServer *operator->()
  332. {
  333. return m_nIndex < HLTV_SERVER_MAX_COUNT ? g_pHltvServer[ m_nIndex ] : NULL;
  334. }
  335. bool Next()
  336. {
  337. if ( m_nIndex >= HLTV_SERVER_MAX_COUNT )
  338. return false;
  339. while ( ++m_nIndex < HLTV_SERVER_MAX_COUNT )
  340. {
  341. CHLTVServer *hltv = g_pHltvServer[ m_nIndex ];
  342. if ( ( ( 1 << m_nIndex ) & m_nMask ) && hltv && hltv->IsActive() )
  343. return true;
  344. }
  345. return false; // no more active HLTV instances
  346. }
  347. uint GetIndex()const { return m_nIndex; }
  348. protected:
  349. };
  350. template <bool bActiveOnly >
  351. class THltvServerIterator
  352. {
  353. protected:
  354. int m_nIndex;
  355. public:
  356. THltvServerIterator( ) { m_nIndex = -1; Next(); }
  357. operator CHLTVServer* ( )
  358. {
  359. return m_nIndex < HLTV_SERVER_MAX_COUNT ? g_pHltvServer[ m_nIndex ] : NULL;
  360. }
  361. CHLTVServer *operator->( )
  362. {
  363. return m_nIndex < HLTV_SERVER_MAX_COUNT ? g_pHltvServer[ m_nIndex ] : NULL;
  364. }
  365. bool Next()
  366. {
  367. if ( m_nIndex >= HLTV_SERVER_MAX_COUNT )
  368. return false;
  369. while ( ++m_nIndex < HLTV_SERVER_MAX_COUNT )
  370. {
  371. CHLTVServer *hltv = g_pHltvServer[ m_nIndex ];
  372. if ( hltv )
  373. {
  374. if ( bActiveOnly )
  375. {
  376. if ( hltv->IsActive() )
  377. return true;
  378. }
  379. else
  380. {
  381. return true;
  382. }
  383. }
  384. }
  385. return false; // no more active HLTV instances
  386. }
  387. uint GetIndex()const { return m_nIndex; }
  388. protected:
  389. };
  390. typedef THltvServerIterator<true> CActiveHltvServerIterator;
  391. typedef THltvServerIterator<false> CHltvServerIterator;
  392. #endif // HLTVSERVER_H