|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//----------------------------------------------------------------------------------------
#ifndef REPLAYSERVER_H
#define REPLAYSERVER_H
#ifdef _WIN32
#pragma once
#endif
#include "baseserver.h"
#include "replaydemo.h"
#include "clientframe.h"
#include "networkstringtable.h"
#include "dt_recv.h"
#include "replay/ireplayserver.h"
#include <convar.h>
#define REPLAY_BUFFER_DIRECTOR 0 // director commands
#define REPLAY_BUFFER_RELIABLE 1 // reliable messages
#define REPLAY_BUFFER_UNRELIABLE 2 // unreliable messages
#define REPLAY_BUFFER_VOICE 3 // player voice data
#define REPLAY_BUFFER_SOUNDS 4 // unreliable sounds
#define REPLAY_BUFFER_TEMPENTS 5 // temporary/event entities
#define REPLAY_BUFFER_MAX 6 // end marker
// proxy dispatch modes
#define DISPATCH_MODE_OFF 0
#define DISPATCH_MODE_AUTO 1
#define DISPATCH_MODE_ALWAYS 2
class CReplayFrame : public CClientFrame { public: CReplayFrame(); virtual ~CReplayFrame();
void Reset(); // resets all data & buffers
void FreeBuffers(); void AllocBuffers(); bool HasData(); void CopyReplayData( CReplayFrame &frame ); virtual bool IsMemPoolAllocated() { return false; }
public:
// message buffers:
bf_write m_Messages[REPLAY_BUFFER_MAX]; };
struct CReplayFrameCacheEntry_s { CClientFrame* pFrame; int nTick; };
class CReplayDeltaEntityCache { struct DeltaEntityEntry_s { DeltaEntityEntry_s *pNext; int nDeltaTick; int nBits; };
public: CReplayDeltaEntityCache(); ~CReplayDeltaEntityCache();
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 IReplayDirector; class IServerReplayContext;
class CReplayServer : public IGameEventListener2, public CBaseServer, public CClientFrameManager, public IReplayServer { typedef CBaseServer BaseClass;
public: CReplayServer(); virtual ~CReplayServer();
public: // CBaseServer interface:
virtual bool IsMultiplayer() const { return true; }; virtual bool IsReplay() const { return true; }; virtual void Init( bool bIsDedicated ); virtual void Clear(); virtual void Shutdown(); virtual void FillServerInfo(SVC_ServerInfo &serverinfo); virtual void GetNetStats( float &avgIn, float &avgOut ); virtual int GetChallengeType ( netadr_t &adr ); virtual const char *GetName() const; virtual 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 );
void ReplyChallenge(netadr_t &adr, int clientChallenge ); void ReplyServerChallenge(netadr_t &adr); void RejectConnection( const netadr_t &adr, int clientChallenge, const char *s ); CBaseClient *CreateFakeClient(const char *name);
public: // IGameEventListener2 interface:
void FireGameEvent( IGameEvent *event ); int m_nDebugID; int GetEventDebugID();
public: // IReplayServer interface:
virtual IServer *GetBaseServer(); virtual IReplayDirector *GetDirector() { return NULL; } virtual int GetReplaySlot(); // return entity index-1 of Replay in game
virtual float GetOnlineTime(); // seconds since broadcast started
virtual void BroadcastEvent( IGameEvent *event ) { } virtual bool IsRecording() { return m_DemoRecorder.IsRecording(); } virtual void StartRecording(); virtual void StopRecording();
public: // CBaseServer overrides:
virtual void SetMaxClients( int number ); virtual void UserInfoChanged( int nClientIndex );
public: void StartMaster(CGameClient *client); // start Replay server as master proxy
bool SendNetMsg( INetMessage &msg, bool bForceReliable = false ); void RunFrame(); void Changelevel(); CClientFrame *AddNewFrame( CClientFrame * pFrame ); // add new frame, returns Replay's copy
void LinkInstanceBaselines(); bf_write *GetBuffer( int nBuffer); CClientFrame *GetDeltaFrame( int nTick );
protected: virtual bool ShouldUpdateMasterServer(); private: void UpdateTick(); void InstallStringTables(); void RestoreTick( int tick ); void EntityPVSCheck( CClientFrame *pFrame ); void InitClientRecvTables(); void FreeClientRecvTables(); void ResyncDemoClock(); public: CGameClient *m_MasterClient; // if != NULL, this is the master Replay
CReplayDemoRecorder m_DemoRecorder; // Replay demo object for recording and playback
CGameServer *m_Server; // pointer to source server (sv.)
int m_nFirstTick; // first known server tick;
int m_nLastTick; // last tick from AddFrame()
CReplayFrame *m_CurrentFrame; // current delayed Replay frame
int m_nViewEntity; // the current entity Replay is tracking
int m_nPlayerSlot; // slot of Replay client on game server
CReplayFrame m_ReplayFrame; // 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 Replay status messages
RecvTable *m_pRecvTables[MAX_DATATABLES]; int m_nRecvTables; Vector m_vPVSOrigin; bool m_bMasterOnlyMode;
netadr_t m_RootServer; // Replay root server
int m_nGlobalSlots; int m_nGlobalClients; int m_nGlobalProxies;
CNetworkStringTableContainer m_NetworkStringTables;
CReplayDeltaEntityCache m_DeltaCache; CUtlVector<CReplayFrameCacheEntry_s> m_FrameCache;
private: void SendPendingEvents(); // Send events to clients regarding start/stop/replays available
float m_flStartRecordTime; float m_flStopRecordTime; };
extern CReplayServer *replay; // The global Replay server/object. NULL on xbox.
#endif // REPLAYSERVER_H
|