source-engine/engine/hltvserver.h

263 lines
8.3 KiB
C
Raw Normal View History

2020-04-22 16:56:21 +00:00
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef HLTVSERVER_H
#define HLTVSERVER_H
#ifdef _WIN32
#pragma once
#endif
#include "baseserver.h"
#include "hltvclient.h"
#include "hltvdemo.h"
#include "hltvclientstate.h"
#include "clientframe.h"
#include "networkstringtable.h"
#include <ihltv.h>
#include <convar.h>
#define HLTV_BUFFER_DIRECTOR 0 // director commands
#define HLTV_BUFFER_RELIABLE 1 // reliable messages
#define HLTV_BUFFER_UNRELIABLE 2 // unreliable messages
#define HLTV_BUFFER_VOICE 3 // player voice data
#define HLTV_BUFFER_SOUNDS 4 // unreliable sounds
#define HLTV_BUFFER_TEMPENTS 5 // temporary/event entities
#define HLTV_BUFFER_MAX 6 // end marker
// proxy dispatch modes
#define DISPATCH_MODE_OFF 0
#define DISPATCH_MODE_AUTO 1
#define DISPATCH_MODE_ALWAYS 2
extern ConVar tv_debug;
class CHLTVFrame : public CClientFrame
{
public:
CHLTVFrame();
virtual ~CHLTVFrame();
void Reset(); // resets all data & buffers
void FreeBuffers();
void AllocBuffers();
bool HasData();
void CopyHLTVData( CHLTVFrame &frame );
virtual bool IsMemPoolAllocated() { return false; }
public:
// message buffers:
bf_write m_Messages[HLTV_BUFFER_MAX];
};
struct CFrameCacheEntry_s
{
CClientFrame* pFrame;
int nTick;
};
class CDeltaEntityCache
{
struct DeltaEntityEntry_s
{
DeltaEntityEntry_s *pNext;
int nDeltaTick;
int nBits;
};
public:
CDeltaEntityCache();
~CDeltaEntityCache();
void SetTick( int nTick, int nMaxEntities );
unsigned char* FindDeltaBits( int nEntityIndex, int nDeltaTick, int &nBits );
void AddDeltaBits( int nEntityIndex, int nDeltaTick, int nBits, bf_write *pBuffer );
void Flush();
protected:
int m_nTick; // current tick
int m_nMaxEntities; // max entities = length of cache
int m_nCacheSize;
DeltaEntityEntry_s* m_Cache[MAX_EDICTS]; // array of pointers to delta entries
};
class CGameClient;
class CGameServer;
class IHLTVDirector;
class CHLTVServer : public IGameEventListener2, public CBaseServer, public CClientFrameManager, public IHLTVServer, public IDemoPlayer
{
friend class CHLTVClientState;
public:
CHLTVServer();
virtual ~CHLTVServer();
public: // CBaseServer interface:
bool ProcessConnectionlessPacket( netpacket_t * packet );
void Init (bool bIsDedicated);
void Shutdown( void );
void Clear( void );
bool IsHLTV( void ) const { return true; };
bool IsMultiplayer( void ) const { return true; };
void FillServerInfo(SVC_ServerInfo &serverinfo);
void GetNetStats( float &avgIn, float &avgOut );
int GetChallengeType ( netadr_t &adr );
const char *GetName( void ) const;
const char *GetPassword() const;
IClient *ConnectClient ( netadr_t &adr, int protocol, int challenge, int clientChallenge, int authProtocol,
const char *name, const char *password, const char *hashedCDkey, int cdKeyLen );
public:
void FireGameEvent(IGameEvent *event);
public: // IHLTVServer interface:
IServer *GetBaseServer( void );
IHLTVDirector *GetDirector( void );
int GetHLTVSlot( void ); // return entity index-1 of HLTV in game
float GetOnlineTime( void ); // seconds since broadcast started
void GetLocalStats( int &proxies, int &slots, int &clients );
void GetGlobalStats( int &proxies, int &slots, int &clients );
void GetRelayStats( int &proxies, int &slots, int &clients );
bool IsMasterProxy( void ); // true, if this is the HLTV master proxy
bool IsTVRelay(); // true if we're running a relay (i.e. this is the opposite of IsMasterProxy()).
bool IsDemoPlayback( void ); // true if this is a HLTV demo
const netadr_t *GetRelayAddress( void ); // returns relay address
void BroadcastEvent(IGameEvent *event);
public: // IDemoPlayer interface
CDemoFile *GetDemoFile();
int GetPlaybackStartTick( void );
int GetPlaybackTick( void );
int GetTotalTicks( void );
bool StartPlayback( const char *filename, bool bAsTimeDemo );
bool IsPlayingBack( void ); // true if demo loaded and playing back
bool IsPlaybackPaused( void ); // true if playback paused
bool IsPlayingTimeDemo( void ) { return false; } // true if playing back in timedemo mode
bool IsSkipping( void ) { return false; }; // true, if demo player skiiping trough packets
bool CanSkipBackwards( void ) { return true; } // true if demoplayer can skip backwards
void SetPlaybackTimeScale( float timescale ); // sets playback timescale
float GetPlaybackTimeScale( void ); // get playback timescale
void PausePlayback( float seconds ) {}
void SkipToTick( int tick, bool bRelative, bool bPause ) {}
void SetEndTick( int tick) {}
void ResumePlayback( void ) {}
void StopPlayback( void ) {}
void InterpolateViewpoint() {}
netpacket_t *ReadPacket( void ) { return NULL; }
void ResetDemoInterpolation( void ) {}
int GetProtocolVersion();
bool ShouldLoopDemos() { return true; }
void OnLastDemoInLoopPlayed() {}
bool IsLoading( void ) { return false; } // true if demo is currently loading
public:
void StartMaster(CGameClient *client); // start HLTV server as master proxy
void ConnectRelay(const char *address); // connect to other HLTV proxy
void StartDemo(const char *filename); // starts playing back a demo file
void StartRelay( void ); // start HLTV server as relay proxy
bool SendNetMsg( INetMessage &msg, bool bForceReliable = false );
void RunFrame();
void SetMaxClients( int number );
void Changelevel( void );
void UserInfoChanged( int nClientIndex );
void SendClientMessages ( bool bSendSnapshots );
CClientFrame *AddNewFrame( CClientFrame * pFrame ); // add new frame, returns HLTV's copy
void SignonComplete( void );
void LinkInstanceBaselines( void );
void BroadcastEventLocal( IGameEvent *event, bool bReliable ); // broadcast event but not to relay proxies
void BroadcastLocalChat( const char *pszChat, const char *pszGroup ); // broadcast event but not to relay proxies
void BroadcastLocalTitle( CHLTVClient *client = NULL ); // NULL = broadcast to all
bool DispatchToRelay( CHLTVClient *pClient);
bf_write *GetBuffer( int nBuffer);
CClientFrame *GetDeltaFrame( int nTick );
inline CHLTVClient* Client( int i ) { return static_cast<CHLTVClient*>(m_Clients[i]); }
protected:
virtual bool ShouldUpdateMasterServer();
private:
CBaseClient *CreateNewClient( int slot );
void UpdateTick( void );
void UpdateStats( void );
void InstallStringTables( void );
void RestoreTick( int tick );
void EntityPVSCheck( CClientFrame *pFrame );
void InitClientRecvTables();
void FreeClientRecvTables();
void ReadCompleteDemoFile();
void ResyncDemoClock();
#ifndef NO_STEAM
void ReplyInfo( const netadr_t &adr );
#endif
// Vector GetOriginFromPackedEntity(PackedEntity* pe);
public:
CGameClient *m_MasterClient; // if != NULL, this is the master HLTV
CHLTVClientState m_ClientState;
CHLTVDemoRecorder m_DemoRecorder; // HLTV demo object for recording and playback
CGameServer *m_Server; // pointer to source server (sv.)
IHLTVDirector *m_Director; // HTLV director exported by game.dll
int m_nFirstTick; // first known server tick;
int m_nLastTick; // last tick from AddFrame()
CHLTVFrame *m_CurrentFrame; // current delayed HLTV frame
int m_nViewEntity; // the current entity HLTV is tracking
int m_nPlayerSlot; // slot of HLTV client on game server
CHLTVFrame m_HLTVFrame; // all incoming messages go here until Snapshot is made
bool m_bSignonState; // true if connecting to server
float m_flStartTime;
float m_flFPS; // FPS the proxy is running;
int m_nGameServerMaxClients; // max clients on game server
float m_fNextSendUpdateTime; // time to send next HLTV status messages
RecvTable *m_pRecvTables[MAX_DATATABLES];
int m_nRecvTables;
Vector m_vPVSOrigin;
bool m_bMasterOnlyMode;
netadr_t m_RootServer; // HLTV root server
int m_nGlobalSlots;
int m_nGlobalClients;
int m_nGlobalProxies;
CNetworkStringTableContainer m_NetworkStringTables;
CDeltaEntityCache m_DeltaCache;
CUtlVector<CFrameCacheEntry_s> m_FrameCache;
// demoplayer stuff:
CDemoFile m_DemoFile; // for demo playback
int m_nStartTick;
democmdinfo_t m_LastCmdInfo;
bool m_bPlayingBack;
bool m_bPlaybackPaused; // true if demo is paused right now
float m_flPlaybackRateModifier;
int m_nSkipToTick; // skip to tick ASAP, -1 = off
};
extern CHLTVServer *hltv; // The global HLTV server/object. NULL on xbox.
#endif // HLTVSERVER_H