summaryrefslogtreecommitdiff
path: root/engine/baseclientstate.h
blob: 7b0151f69bcea413080e6f724357434e3adec789 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: 
//
//=============================================================================//

#ifndef BASECLIENTSTATE_H
#define BASECLIENTSTATE_H
#ifdef _WIN32
#pragma once
#endif

#include <inetmsghandler.h>
#include <protocol.h>
#include <client_class.h>
#include <cdll_int.h>
#include <netadr.h>
#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