KDEGames

kgamenetwork.h
1 /*
2  This file is part of the KDE games library
3  SPDX-FileCopyrightText: 2001 Martin Heni <kde at heni-online.de>
4  SPDX-FileCopyrightText: 2001 Andreas Beckermann <[email protected]>
5 
6  SPDX-License-Identifier: LGPL-2.0-only
7 */
8 
9 #ifndef __KGAMENETWORK_H_
10 #define __KGAMENETWORK_H_
11 
12 // own
13 #include "libkdegamesprivate_export.h"
14 // Qt
15 #include <QObject>
16 #include <QString>
17 // Std
18 #include <memory>
19 
20 class KGameIO;
21 class KMessageIO;
22 class KMessageClient;
23 class KMessageServer;
24 
25 class KGameNetworkPrivate;
26 
27 /**
28  * \class KGameNetwork kgamenetwork.h <KGame/KGameNetwork>
29  *
30  * The KGameNetwork class is the KGame class with network
31  * support. All other features are the same but they are
32  * now network transparent. It is not used directly but
33  * only via a KGame object. So you do not really have
34  * to bother with this object.
35  *
36  * @short The main KDE game object
37  */
38 class KDEGAMESPRIVATE_EXPORT KGameNetwork : public QObject
39 {
40  Q_OBJECT
41 
42 public:
43  /**
44  * Create a KGameNetwork object
45  */
46  explicit KGameNetwork(int cookie = 42, QObject *parent = nullptr);
47  ~KGameNetwork() override;
48 
49  /**
50  * Gives debug output of the game status
51  */
52  virtual void Debug();
53 
54  /**
55  * @return TRUE if this is a network game - i.e. you are either MASTER or
56  * connected to a remote MASTER.
57  */
58  bool isNetwork() const;
59 
60  /**
61  * Is this the game MASTER (i.e. has started theKMessageServer). A
62  * game has always exactly one MASTER. This is either a KGame object (i.e. a
63  * Client) or an own MessageServer-process. A KGame object that has the
64  * MASTER status is always admin.
65  *
66  * You probably don't want to use this. It is a mostly internal method which
67  * will probably become protected. Better use isAdmin
68  *
69  * @see isAdmin
70  * @return Whether this client has started the KMessageServer
71  */
72  bool isMaster() const;
73 
74  /**
75  * The admin of a game is the one who initializes newly connected clients
76  * using negotiateNetworkGame and is allowed to configure the game.
77  * E.g. only the admin is allowed to use KGame::setMaxPlayers.
78  *
79  * If one KGame object in the game is MASTER then this client is the admin
80  * as well. isMaster and isAdmin differ only if the KMessageServer
81  * is running in an own process.
82  * @return Whether this client (KGame object) is the admin
83  */
84  bool isAdmin() const;
85 
86  /**
87  * The unique ID of this game
88  *
89  * @return int id
90  */
91  quint32 gameId() const;
92 
93  /**
94  * Inits a network game as network MASTER. Note that if the
95  * KMessageServer is not yet started it will be started here (see
96  * setMaster). Any existing connection will be disconnected.
97  *
98  * If you already offer connections the port is changed.
99  *
100  * @param port The port on which the service is offered
101  * @return true if it worked
102  */
103  bool offerConnections(quint16 port);
104 
105  void setDiscoveryInfo(const QString &type, const QString &name = QString());
106 
107  /**
108  * Inits a network game as a network CLIENT
109  *
110  * @param host the host to which we want to connect
111  * @param port the port we want to connect to
112  *
113  * @return true if connected
114  */
115  bool connectToServer(const QString &host, quint16 port);
116  bool connectToServer(KMessageIO *connection);
117 
118  /**
119  * @return The port we are listening to if offerConnections was called
120  * or the port we are connected to if connectToServer was called.
121  * Otherwise 0.
122  */
123  quint16 port() const;
124 
125  /**
126  * @return The name of the host that we are currently connected to is
127  * isNetwork is TRUE and we are not the MASTER, i.e. if connectToServer
128  * was called. Otherwise this will return "localhost".
129  */
130  QString hostName() const;
131 
132  /**
133  * Stops offering server connections - only for game MASTER
134  * @return true
135  */
136  bool stopServerConnection();
137 
138  /**
139  * Changes the maximal connection number of the KMessageServer to max.
140  * -1 Means infinite connections are possible. Note that existing
141  * connections are not affected, so even if you set this to 0 in a running
142  * game no client is being disconnected. You can call this only if you are
143  * the ADMIN!
144  *
145  * @see KMessageServer::setMaxClients
146  * @param max The maximal number of connections possible.
147  */
148  void setMaxClients(int max);
149 
150  // AB: is this now internal only? Can we make it protected (maybe with
151  // friends)? sendSystemMessage AND sendMessage is very confusing to the
152  // user.
153  /**
154  * Sends a network message msg with a given msg id msgid to all clients.
155  * Use this to communicate with KGame (e.g. to add a player ot to configure
156  * the game - usually not necessary).
157  *
158  * For your own messages use sendMessage instead! This is mostly
159  * internal!
160  *
161  * @param buffer the message which will be send. See messages.txt for contents
162  * @param msgid an id for this message. See
163  * KGameMessage::GameMessageIds
164  * @param receiver the KGame / KPlayer this message is for.
165  * @param sender The KGame / KPlayer this message is from (i.e.
166  * you). You
167  * probably want to leave this 0, then KGameNetwork will create the correct
168  * value for you. You might want to use this if you send a message from a
169  * specific player.
170  * @return true if worked
171  */
172  // AB: TODO: doc on how "receiver" and "sender" should be created!
173  bool sendSystemMessage(const QByteArray &buffer, int msgid, quint32 receiver = 0, quint32 sender = 0);
174 
175  /**
176  * @overload
177  */
178  bool sendSystemMessage(int data, int msgid, quint32 receiver = 0, quint32 sender = 0);
179 
180  /**
181  * @overload
182  */
183  bool sendSystemMessage(const QDataStream &msg, int msgid, quint32 receiver = 0, quint32 sender = 0);
184 
185  /**
186  * @overload
187  */
188  bool sendSystemMessage(const QString &msg, int msgid, quint32 receiver = 0, quint32 sender = 0);
189 
190  /**
191  * Sends a network message
192  * @param error The error code
193  * @param message The error message - use KGameError
194  * @param receiver the KGame / KPlayer this message is for. 0 For
195  * all
196  * @param sender The KGame / KPlayer this message is from (i.e.
197  * you). You probably want to leave this 0, then KGameNetwork will create
198  * the correct value for you. You might want to use this if you send a
199  * message from a specific player.
200  */
201  void sendError(int error, const QByteArray &message, quint32 receiver = 0, quint32 sender = 0);
202 
203  /**
204  * Are we still offer offering server connections - only for game MASTER
205  * @return true/false
206  */
207  bool isOfferingConnections() const;
208 
209  /**
210  * Application cookie. this identifies the game application. It
211  * help to distinguish between e.g. KPoker and KWin4
212  * @return the application cookie
213  */
214  int cookie() const;
215 
216  /**
217  * Send a network message msg with a given message ID msgid to all clients.
218  * You want to use this to send a message to the clients.
219  *
220  * Note that a message is always sent to ALL clients! This is necessary so
221  * that all clients always have the same data and can easily be changed from
222  * network to non-network without restarting the game. If you want a
223  * specific KGame / KPlayer to react to the message use the
224  * receiver and sender parameters. See KGameMessage::calsMessageId
225  *
226  * SendMessage differs from sendSystemMessage only by the msgid parameter.
227  * sendSystemMessage is thought as a KGame only method while
228  * sendMessage is for public use. The msgid parameter will be
229  * +=KGameMessage::IdUser and in KGame::signalNetworkData msgid will
230  * be -= KGameMessage::IdUser again, so that one can easily distinguish
231  * between system and user messages.
232  *
233  * Use sendSystemMessage to communicate with KGame (e.g. by adding a
234  * player) and sendMessage for your own user message.
235  *
236  * Note: a player should send messages through a KGameIO!
237  *
238  * @param buffer the message which will be send. See messages.txt for contents
239  * @param msgid an id for this message. See KGameMessage::GameMessageIds
240  * @param receiver the KGame / KPlayer this message is for.
241  * @param sender The KGame / KPlayer this message is from (i.e.
242  * you). You
243  * probably want to leave this 0, then KGameNetwork will create the correct
244  * value for you. You might want to use this if you send a message from a
245  * specific player.
246  * @return true if worked
247  */
248  // AB: TODO: doc on how "receiver" and "sender" should be created!
249  bool sendMessage(const QByteArray &buffer, int msgid, quint32 receiver = 0, quint32 sender = 0);
250 
251  /**
252  * This is an overloaded member function, provided for convenience.
253  */
254  bool sendMessage(const QDataStream &msg, int msgid, quint32 receiver = 0, quint32 sender = 0);
255 
256  /**
257  * This is an overloaded member function, provided for convenience.
258  */
259  bool sendMessage(const QString &msg, int msgid, quint32 receiver = 0, quint32 sender = 0);
260 
261  /**
262  * This is an overloaded member function, provided for convenience.
263  */
264  bool sendMessage(int data, int msgid, quint32 receiver = 0, quint32 sender = 0);
265 
266  /**
267  * Called by ReceiveNetworkTransmission(). Will be overwritten by
268  * KGame and handle the incoming message.
269  */
270  virtual void networkTransmission(QDataStream &, int, quint32, quint32, quint32 clientID) = 0;
271 
272  /**
273  * Disconnect the current connection and establish a new local one.
274  */
275  void disconnect();
276 
277  /**
278  * If you are the ADMIN of the game you can give the ADMIN status away to
279  * another client. Use this e.g. if you want to quit the game or if you want
280  * another client to administrate the game (note that disconnect calls
281  * this automatically).
282  * @param clientID the ID of the new ADMIN (note: this is the _client_ID
283  * which has nothing to do with the player IDs. See KMessageServer)
284  */
285  void electAdmin(quint32 clientID);
286 
287  /**
288  * Don't use this unless you really know what you're doing! You might
289  * experience some strange behaviour if you send your messages directly
290  * through the KMessageClient!
291  *
292  * @return a pointer to the KMessageClient used internally to send the
293  * messages. You should rather use one of the send functions!
294  */
295  KMessageClient *messageClient() const;
296 
297  /**
298  * Don't use this unless you really know what you are doing! You might
299  * experience some strange behaviour if you use the message server directly!
300  *
301  * @return a pointer to the message server if this is the MASTER KGame
302  * object. Note that it might be possible that no KGame object contains
303  * the KMessageServer at all! It might even run stand alone!
304  */
305  KMessageServer *messageServer() const;
306 
307  /**
308  * You should call this before doing thigs like, e.g. qApp->processEvents().
309  * Don't forget to call unlock once you are done!
310  *
311  * @see KMessageClient::lock
312  */
313  virtual void lock();
314 
315  /**
316  * @see KMessageClient::unlock
317  */
318  virtual void unlock();
319 
320 Q_SIGNALS:
321  /**
322  * A network error occurred
323  * @param error the error code
324  * @param text the error text
325  */
326  void signalNetworkErrorMessage(int error, const QString &text);
327 
328  /**
329  * Our connection to the KMessageServer has broken.
330  * See KMessageClient::connectionBroken
331  */
332  void signalConnectionBroken();
333 
334  /**
335  * This signal is emitted whenever the KMessageServer sends us a message that a
336  * new client connected. KGame uses this to call KGame::negotiateNetworkGame
337  * for the newly connected client if we are admin (see isAdmin)
338  *
339  * @see KMessageClient::eventClientConnected
340  *
341  * @param clientID the ID of the newly connected client
342  */
343  void signalClientConnected(quint32 clientID);
344 
345  /**
346  * This signal is emitted whenever the KMessageServer sends us a message
347  * that a connection to a client was detached. The second parameter can be used
348  * to distinguish between network errors or removing on purpose.
349  *
350  * @see KMessageClient::eventClientDisconnected
351  *
352  * @param clientID the client that has disconnected
353  * @param broken true if the connection was lost because of a network error, false
354  * if the connection was closed by the message server admin.
355  */
356  void signalClientDisconnected(quint32 clientID, bool broken);
357 
358  /**
359  * This client gets or loses the admin status.
360  * @see KMessageClient::adminStatusChanged
361  * @param isAdmin True if this client gets the ADMIN status otherwise FALSE
362  */
363  void signalAdminStatusChanged(bool isAdmin);
364 
365 protected:
366  /**
367  * @internal
368  * Start a KMessageServer object and use it as the MASTER of the game.
369  * Note that you must not call this if there is already another master
370  * running!
371  */
372  void setMaster();
373 
374 protected Q_SLOTS:
375  /**
376  * Called by KMessageClient::broadcastReceived() and will check if the
377  * message format is valid. If it is not, it will generate an error (see
378  * signalNetworkVersionError and signalNetworkErorrMessage).
379  * If it is valid, the pure virtual method networkTransmission() is called.
380  * (This one is overwritten in KGame.)
381  */
382  void receiveNetworkTransmission(const QByteArray &a, quint32 clientID);
383 
384  /**
385  * This KGame object receives or loses the admin status.
386  * @param isAdmin Whether we are admin or not
387  */
388  void slotAdminStatusChanged(bool isAdmin);
389 
390  /**
391  * Called when the network connection is about to terminate. Is used
392  * to store the network parameter like the game id
393  */
394  void aboutToLoseConnection(quint32 id);
395 
396  /**
397  * Called when the network connection is terminated. Used to clean
398  * up the disconnect parameter
399  */
400  void slotResetConnection();
401 
402 private:
403  void tryPublish();
404  void tryStopPublishing();
405 
406 private:
407  std::unique_ptr<KGameNetworkPrivate> const d;
408 };
409 
410 #endif
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
Q_SLOTSQ_SLOTS
Base class for IO devices for games.
Definition: kgameio.h:56
Q_SIGNALSQ_SIGNALS
ScriptableExtension * host() const
The main KDE game object.
Definition: kgamenetwork.h:38
A server for message sending and broadcasting, using TCP/IP connections.
A client to connect to a KMessageServer.
QString message
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Mar 27 2023 04:19:37 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.