File: NetClient.h

package info (click to toggle)
0ad 0.0.17-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 51,248 kB
  • ctags: 46,933
  • sloc: cpp: 223,208; ansic: 31,240; python: 16,343; perl: 4,083; sh: 1,011; makefile: 915; xml: 733; java: 621; ruby: 229; erlang: 53; sql: 40
file content (227 lines) | stat: -rw-r--r-- 6,748 bytes parent folder | download | duplicates (2)
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
/* Copyright (C) 2011 Wildfire Games.
 * This file is part of 0 A.D.
 *
 * 0 A.D. is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * 0 A.D. is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef NETCLIENT_H
#define NETCLIENT_H

#include "network/fsm.h"
#include "network/NetFileTransfer.h"
#include "network/NetHost.h"
#include "scriptinterface/ScriptVal.h"

#include "ps/CStr.h"

#include <deque>

class CGame;
class CNetClientSession;
class CNetClientTurnManager;
class CNetServer;
class ScriptInterface;

// NetClient session FSM states
enum
{
	NCS_UNCONNECTED,
	NCS_CONNECT,
	NCS_HANDSHAKE,
	NCS_AUTHENTICATE,
	NCS_INITIAL_GAMESETUP,
	NCS_PREGAME,
	NCS_LOADING,
	NCS_JOIN_SYNCING,
	NCS_INGAME
};

/**
 * Network client.
 * This code is run by every player (including the host, if they are not
 * a dedicated server).
 * It provides an interface between the GUI, the network (via CNetClientSession),
 * and the game (via CGame and CNetClientTurnManager).
 */
class CNetClient : public CFsm
{
	NONCOPYABLE(CNetClient);

	friend class CNetFileReceiveTask_ClientRejoin;

public:
	/**
	 * Construct a client associated with the given game object.
	 * The game must exist for the lifetime of this object.
	 */
	CNetClient(CGame* game);

	virtual ~CNetClient();

	/**
	 * Set the user's name that will be displayed to all players.
	 * This must not be called after the connection setup.
	 */
	void SetUserName(const CStrW& username);

	/**
	 * Set up a connection to the remote networked server.
	 * @param server IP address or host name to connect to
	 * @return true on success, false on connection failure
	 */
	bool SetupConnection(const CStr& server);

	/**
	 * Destroy the connection to the server.
	 * This client probably cannot be used again.
	 */
	void DestroyConnection();

	/**
	 * Poll the connection for messages from the server and process them, and send
	 * any queued messages.
	 * This must be called frequently (i.e. once per frame).
	 */
	void Poll();

	/**
	 * Flush any queued outgoing network messages.
	 * This should be called soon after sending a group of messages that may be batched together.
	 */
	void Flush();

	/**
	 * Retrieves the next queued GUI message, and removes it from the queue.
	 * The returned value is in the GetScriptInterface() JS context.
	 *
	 * This is the only mechanism for the networking code to send messages to
	 * the GUI - it is pull-based (instead of push) so the engine code does not
	 * need to know anything about the code structure of the GUI scripts.
	 *
	 * The structure of the messages is <code>{ "type": "...", ... }</code>.
	 * The exact types and associated data are not specified anywhere - the
	 * implementation and GUI scripts must make the same assumptions.
	 *
	 * @return next message, or the value 'undefined' if the queue is empty
	 */
	CScriptValRooted GuiPoll();

	/**
	 * Add a message to the queue, to be read by GuiPoll.
	 * The script value must be in the GetScriptInterface() JS context.
	 */
	void PushGuiMessage(const CScriptValRooted& message);

	/**
	 * Return a concatenation of all messages in the GUI queue,
	 * for test cases to easily verify the queue contents.
	 */
	std::wstring TestReadGuiMessages();

	/**
	 * Get the script interface associated with this network client,
	 * which is equivalent to the one used by the CGame in the constructor.
	 */
	ScriptInterface& GetScriptInterface();

	/**
	 * Send a message to the server.
	 * @param message message to send
	 * @return true on success
	 */
	bool SendMessage(const CNetMessage* message);

	/**
	 * Call when the network connection has been successfully initiated.
	 */
	void HandleConnect();

	/**
	 * Call when the network connection has been lost.
	 */
	void HandleDisconnect(u32 reason);

	/**
	 * Call when a message has been received from the network.
	 */
	bool HandleMessage(CNetMessage* message);

	/**
	 * Call when the game has started and all data files have been loaded,
	 * to signal to the server that we are ready to begin the game.
	 */
	void LoadFinished();

	void SendChatMessage(const std::wstring& text);
	
	void SendReadyMessage(const int status);

private:
	// Net message / FSM transition handlers
	static bool OnConnect(void* context, CFsmEvent* event);
	static bool OnHandshake(void* context, CFsmEvent* event);
	static bool OnHandshakeResponse(void* context, CFsmEvent* event);
	static bool OnAuthenticate(void* context, CFsmEvent* event);
	static bool OnChat(void* context, CFsmEvent* event);
	static bool OnReady(void* context, CFsmEvent* event);
	static bool OnGameSetup(void* context, CFsmEvent* event);
	static bool OnPlayerAssignment(void* context, CFsmEvent* event);
	static bool OnInGame(void* context, CFsmEvent* event);
	static bool OnGameStart(void* context, CFsmEvent* event);
	static bool OnJoinSyncStart(void* context, CFsmEvent* event);
	static bool OnJoinSyncEndCommandBatch(void* context, CFsmEvent* event);
	static bool OnLoadedGame(void* context, CFsmEvent* event);

	/**
	 * Take ownership of a session object, and use it for all network communication.
	 */
	void SetAndOwnSession(CNetClientSession* session);

	/**
	 * Push a message onto the GUI queue listing the current player assignments.
	 */
	void PostPlayerAssignmentsToScript();

	CGame *m_Game;
	CStrW m_UserName;

	/// Current network session (or NULL if not connected)
	CNetClientSession* m_Session;

	/// Turn manager associated with the current game (or NULL if we haven't started the game yet)
	CNetClientTurnManager* m_ClientTurnManager;

	/// Unique-per-game identifier of this client, used to identify the sender of simulation commands
	u32 m_HostID;

	/// Latest copy of game setup attributes heard from the server
	CScriptValRooted m_GameAttributes;

	/// Latest copy of player assignments heard from the server
	PlayerAssignmentMap m_PlayerAssignments;

	/// Globally unique identifier to distinguish users beyond the lifetime of a single network session
	CStr m_GUID;

	/// Queue of messages for GuiPoll
	std::deque<CScriptValRooted> m_GuiMessageQueue;

	/// Serialized game state received when joining an in-progress game
	std::string m_JoinSyncBuffer;
};

/// Global network client for the standard game
extern CNetClient *g_NetClient;

#endif	// NETCLIENT_H