Remove materials from particle actors to prevent useless warnings.
[0ad.git] / source / network / NetClient.h
blob37fae11530de2482e8a26e941c0d39cd4e10d090
1 /* Copyright (C) 2022 Wildfire Games.
2 * This file is part of 0 A.D.
4 * 0 A.D. is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
9 * 0 A.D. is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
18 #ifndef NETCLIENT_H
19 #define NETCLIENT_H
21 #include "network/FSM.h"
22 #include "network/NetFileTransfer.h"
23 #include "network/NetHost.h"
24 #include "scriptinterface/Object.h"
26 #include "ps/CStr.h"
28 #include <ctime>
29 #include <deque>
30 #include <thread>
32 class CGame;
33 class CNetClientSession;
34 class CNetClientTurnManager;
35 class ScriptInterface;
37 typedef struct _ENetHost ENetHost;
39 // NetClient session FSM states
40 enum
42 NCS_UNCONNECTED,
43 NCS_CONNECT,
44 NCS_HANDSHAKE,
45 NCS_AUTHENTICATE,
46 NCS_PREGAME,
47 NCS_LOADING,
48 NCS_JOIN_SYNCING,
49 NCS_INGAME
52 /**
53 * Network client.
54 * This code is run by every player (including the host, if they are not
55 * a dedicated server).
56 * It provides an interface between the GUI, the network (via CNetClientSession),
57 * and the game (via CGame and CNetClientTurnManager).
59 class CNetClient : public CFsm
61 NONCOPYABLE(CNetClient);
63 friend class CNetFileReceiveTask_ClientRejoin;
65 public:
66 /**
67 * Construct a client associated with the given game object.
68 * The game must exist for the lifetime of this object.
70 CNetClient(CGame* game);
72 virtual ~CNetClient();
74 /**
75 * We assume that adding a tracing function that's only called
76 * during GC is better for performance than using a
77 * PersistentRooted<T> where each value needs to be added to
78 * the root set.
80 static void Trace(JSTracer *trc, void *data)
82 reinterpret_cast<CNetClient*>(data)->TraceMember(trc);
85 void TraceMember(JSTracer *trc);
87 /**
88 * Set the user's name that will be displayed to all players.
89 * This must not be called after the connection setup.
91 void SetUserName(const CStrW& username);
93 /**
94 * Store the JID of the host.
95 * This is needed for the secure lobby authentication.
97 void SetHostJID(const CStr& jid);
99 void SetControllerSecret(const std::string& secret);
101 bool IsController() const { return m_IsController; }
104 * Set the game password.
105 * Must be called after SetUserName, as that is used to hash further.
107 void SetGamePassword(const CStr& hashedPassword);
110 * Returns the GUID of the local client.
111 * Used for distinguishing observers.
113 CStr GetGUID() const { return m_GUID; }
116 * Set connection data to the remote networked server.
117 * @param address IP address or host name to connect to
119 void SetupServerData(CStr address, u16 port, bool stun);
122 * Set up a connection to the remote networked server.
123 * Must call SetupServerData first.
124 * @return true on success, false on connection failure
126 bool SetupConnection(ENetHost* enetClient);
129 * Request connection information over the lobby.
131 void SetupConnectionViaLobby();
134 * Connect to the remote networked server using lobby.
135 * Push netstatus messages on failure.
136 * @param localNetwork - if true, assume we are trying to connect on the local network.
137 * @return true on success, false on connection failure
139 bool TryToConnect(const CStr& hostJID, bool localNetwork);
142 * Destroy the connection to the server.
143 * This client probably cannot be used again.
145 void DestroyConnection();
148 * Poll the connection for messages from the server and process them, and send
149 * any queued messages.
150 * This must be called frequently (i.e. once per frame).
152 void Poll();
155 * Locally triggers a GUI message if the connection to the server is being lost or has bad latency.
157 void CheckServerConnection();
160 * Retrieves the next queued GUI message, and removes it from the queue.
161 * The returned value is in the GetScriptInterface() JS context.
163 * This is the only mechanism for the networking code to send messages to
164 * the GUI - it is pull-based (instead of push) so the engine code does not
165 * need to know anything about the code structure of the GUI scripts.
167 * The structure of the messages is <code>{ "type": "...", ... }</code>.
168 * The exact types and associated data are not specified anywhere - the
169 * implementation and GUI scripts must make the same assumptions.
171 * @return next message, or the value 'undefined' if the queue is empty
173 void GuiPoll(JS::MutableHandleValue);
176 * Add a message to the queue, to be read by GuiPoll.
177 * The script value must be in the GetScriptInterface() JS context.
179 template<typename... Args>
180 void PushGuiMessage(Args const&... args)
182 ScriptRequest rq(GetScriptInterface());
184 JS::RootedValue message(rq.cx);
185 Script::CreateObject(rq, &message, args...);
186 m_GuiMessageQueue.push_back(JS::Heap<JS::Value>(message));
190 * Return a concatenation of all messages in the GUI queue,
191 * for test cases to easily verify the queue contents.
193 std::string TestReadGuiMessages();
196 * Get the script interface associated with this network client,
197 * which is equivalent to the one used by the CGame in the constructor.
199 const ScriptInterface& GetScriptInterface();
202 * Send a message to the server.
203 * @param message message to send
204 * @return true on success
206 bool SendMessage(const CNetMessage* message);
209 * Call when the network connection has been successfully initiated.
211 void HandleConnect();
214 * Call when the network connection has been lost.
216 void HandleDisconnect(u32 reason);
219 * Call when a message has been received from the network.
221 bool HandleMessage(CNetMessage* message);
224 * Call when the game has started and all data files have been loaded,
225 * to signal to the server that we are ready to begin the game.
227 void LoadFinished();
229 void SendGameSetupMessage(JS::MutableHandleValue attrs, const ScriptInterface& scriptInterface);
231 void SendAssignPlayerMessage(const int playerID, const CStr& guid);
233 void SendChatMessage(const std::wstring& text);
235 void SendReadyMessage(const int status);
237 void SendClearAllReadyMessage();
239 void SendStartGameMessage(const CStr& initAttribs);
242 * Call when the client has rejoined a running match and finished
243 * the loading screen.
245 void SendRejoinedMessage();
248 * Call to kick/ban a client
250 void SendKickPlayerMessage(const CStrW& playerName, bool ban);
253 * Call when the client has paused or unpaused the game.
255 void SendPausedMessage(bool pause);
258 * @return Whether the NetClient is shutting down.
260 bool ShouldShutdown() const;
263 * Called when fetching connection data from the host failed, to inform JS code.
265 void HandleGetServerDataFailed(const CStr& error);
266 private:
268 void SendAuthenticateMessage();
270 // Net message / FSM transition handlers
271 static bool OnConnect(void* context, CFsmEvent* event);
272 static bool OnHandshake(void* context, CFsmEvent* event);
273 static bool OnHandshakeResponse(void* context, CFsmEvent* event);
274 static bool OnAuthenticateRequest(void* context, CFsmEvent* event);
275 static bool OnAuthenticate(void* context, CFsmEvent* event);
276 static bool OnChat(void* context, CFsmEvent* event);
277 static bool OnReady(void* context, CFsmEvent* event);
278 static bool OnGameSetup(void* context, CFsmEvent* event);
279 static bool OnPlayerAssignment(void* context, CFsmEvent* event);
280 static bool OnInGame(void* context, CFsmEvent* event);
281 static bool OnGameStart(void* context, CFsmEvent* event);
282 static bool OnJoinSyncStart(void* context, CFsmEvent* event);
283 static bool OnJoinSyncEndCommandBatch(void* context, CFsmEvent* event);
284 static bool OnRejoined(void* context, CFsmEvent* event);
285 static bool OnKicked(void* context, CFsmEvent* event);
286 static bool OnClientTimeout(void* context, CFsmEvent* event);
287 static bool OnClientPerformance(void* context, CFsmEvent* event);
288 static bool OnClientsLoading(void* context, CFsmEvent* event);
289 static bool OnClientPaused(void* context, CFsmEvent* event);
290 static bool OnLoadedGame(void* context, CFsmEvent* event);
293 * Take ownership of a session object, and use it for all network communication.
295 void SetAndOwnSession(CNetClientSession* session);
298 * Push a message onto the GUI queue listing the current player assignments.
300 void PostPlayerAssignmentsToScript();
302 CGame *m_Game;
303 CStrW m_UserName;
305 CStr m_HostJID;
306 CStr m_ServerAddress;
307 u16 m_ServerPort;
308 bool m_UseSTUN;
311 * Password to join the game.
313 CStr m_Password;
315 /// The 'secret' used to identify the controller of the game.
316 std::string m_ControllerSecret;
318 /// Note that this is just a "gui hint" with no actual impact on being controller.
319 bool m_IsController = false;
321 /// Current network session (or NULL if not connected)
322 CNetClientSession* m_Session;
324 std::thread m_PollingThread;
326 /// Turn manager associated with the current game (or NULL if we haven't started the game yet)
327 CNetClientTurnManager* m_ClientTurnManager;
329 /// Unique-per-game identifier of this client, used to identify the sender of simulation commands
330 u32 m_HostID;
332 /// True if the player is currently rejoining or has already rejoined the game.
333 bool m_Rejoin;
335 /// Latest copy of player assignments heard from the server
336 PlayerAssignmentMap m_PlayerAssignments;
338 /// Globally unique identifier to distinguish users beyond the lifetime of a single network session
339 CStr m_GUID;
341 /// Queue of messages for GuiPoll
342 std::deque<JS::Heap<JS::Value>> m_GuiMessageQueue;
344 /// Serialized game state received when joining an in-progress game
345 std::string m_JoinSyncBuffer;
347 /// Time when the server was last checked for timeouts and bad latency
348 std::time_t m_LastConnectionCheck;
351 /// Global network client for the standard game
352 extern CNetClient *g_NetClient;
354 #endif // NETCLIENT_H