File indexing completed on 2024-06-16 03:57:55
0001 /* 0002 This file is part of the KDE games library 0003 SPDX-FileCopyrightText: 2001 Martin Heni <kde at heni-online.de> 0004 SPDX-FileCopyrightText: 2001 Andreas Beckermann <b_mann@gmx.de> 0005 0006 SPDX-License-Identifier: LGPL-2.0-only 0007 */ 0008 0009 #ifndef __KGAMENETWORK_H_ 0010 #define __KGAMENETWORK_H_ 0011 0012 // own 0013 #include "kdegamesprivate_export.h" 0014 // Qt 0015 #include <QObject> 0016 #include <QString> 0017 // Std 0018 #include <memory> 0019 0020 class KGameIO; 0021 class KMessageIO; 0022 class KMessageClient; 0023 class KMessageServer; 0024 0025 class KGameNetworkPrivate; 0026 0027 /** 0028 * \class KGameNetwork kgamenetwork.h <KGame/KGameNetwork> 0029 * 0030 * The KGameNetwork class is the KGame class with network 0031 * support. All other features are the same but they are 0032 * now network transparent. It is not used directly but 0033 * only via a KGame object. So you do not really have 0034 * to bother with this object. 0035 * 0036 * @short The main KDE game object 0037 */ 0038 class KDEGAMESPRIVATE_EXPORT KGameNetwork : public QObject 0039 { 0040 Q_OBJECT 0041 0042 public: 0043 /** 0044 * Create a KGameNetwork object 0045 */ 0046 explicit KGameNetwork(int cookie = 42, QObject *parent = nullptr); 0047 ~KGameNetwork() override; 0048 0049 /** 0050 * Gives debug output of the game status 0051 */ 0052 virtual void Debug(); 0053 0054 /** 0055 * @return TRUE if this is a network game - i.e. you are either MASTER or 0056 * connected to a remote MASTER. 0057 */ 0058 bool isNetwork() const; 0059 0060 /** 0061 * Is this the game MASTER (i.e. has started theKMessageServer). A 0062 * game has always exactly one MASTER. This is either a KGame object (i.e. a 0063 * Client) or an own MessageServer-process. A KGame object that has the 0064 * MASTER status is always admin. 0065 * 0066 * You probably don't want to use this. It is a mostly internal method which 0067 * will probably become protected. Better use isAdmin 0068 * 0069 * @see isAdmin 0070 * @return Whether this client has started the KMessageServer 0071 */ 0072 bool isMaster() const; 0073 0074 /** 0075 * The admin of a game is the one who initializes newly connected clients 0076 * using negotiateNetworkGame and is allowed to configure the game. 0077 * E.g. only the admin is allowed to use KGame::setMaxPlayers. 0078 * 0079 * If one KGame object in the game is MASTER then this client is the admin 0080 * as well. isMaster and isAdmin differ only if the KMessageServer 0081 * is running in an own process. 0082 * @return Whether this client (KGame object) is the admin 0083 */ 0084 bool isAdmin() const; 0085 0086 /** 0087 * The unique ID of this game 0088 * 0089 * @return int id 0090 */ 0091 quint32 gameId() const; 0092 0093 /** 0094 * Inits a network game as network MASTER. Note that if the 0095 * KMessageServer is not yet started it will be started here (see 0096 * setMaster). Any existing connection will be disconnected. 0097 * 0098 * If you already offer connections the port is changed. 0099 * 0100 * @param port The port on which the service is offered 0101 * @return true if it worked 0102 */ 0103 bool offerConnections(quint16 port); 0104 0105 void setDiscoveryInfo(const QString &type, const QString &name = QString()); 0106 0107 /** 0108 * Inits a network game as a network CLIENT 0109 * 0110 * @param host the host to which we want to connect 0111 * @param port the port we want to connect to 0112 * 0113 * @return true if connected 0114 */ 0115 bool connectToServer(const QString &host, quint16 port); 0116 bool connectToServer(KMessageIO *connection); 0117 0118 /** 0119 * @return The port we are listening to if offerConnections was called 0120 * or the port we are connected to if connectToServer was called. 0121 * Otherwise 0. 0122 */ 0123 quint16 port() const; 0124 0125 /** 0126 * @return The name of the host that we are currently connected to is 0127 * isNetwork is TRUE and we are not the MASTER, i.e. if connectToServer 0128 * was called. Otherwise this will return "localhost". 0129 */ 0130 QString hostName() const; 0131 0132 /** 0133 * Stops offering server connections - only for game MASTER 0134 * @return true 0135 */ 0136 bool stopServerConnection(); 0137 0138 /** 0139 * Changes the maximal connection number of the KMessageServer to max. 0140 * -1 Means infinite connections are possible. Note that existing 0141 * connections are not affected, so even if you set this to 0 in a running 0142 * game no client is being disconnected. You can call this only if you are 0143 * the ADMIN! 0144 * 0145 * @see KMessageServer::setMaxClients 0146 * @param max The maximal number of connections possible. 0147 */ 0148 void setMaxClients(int max); 0149 0150 // AB: is this now internal only? Can we make it protected (maybe with 0151 // friends)? sendSystemMessage AND sendMessage is very confusing to the 0152 // user. 0153 /** 0154 * Sends a network message msg with a given msg id msgid to all clients. 0155 * Use this to communicate with KGame (e.g. to add a player ot to configure 0156 * the game - usually not necessary). 0157 * 0158 * For your own messages use sendMessage instead! This is mostly 0159 * internal! 0160 * 0161 * @param buffer the message which will be send. See messages.txt for contents 0162 * @param msgid an id for this message. See 0163 * KGameMessage::GameMessageIds 0164 * @param receiver the KGame / KPlayer this message is for. 0165 * @param sender The KGame / KPlayer this message is from (i.e. 0166 * you). You 0167 * probably want to leave this 0, then KGameNetwork will create the correct 0168 * value for you. You might want to use this if you send a message from a 0169 * specific player. 0170 * @return true if worked 0171 */ 0172 // AB: TODO: doc on how "receiver" and "sender" should be created! 0173 bool sendSystemMessage(const QByteArray &buffer, int msgid, quint32 receiver = 0, quint32 sender = 0); 0174 0175 /** 0176 * @overload 0177 */ 0178 bool sendSystemMessage(int data, int msgid, quint32 receiver = 0, quint32 sender = 0); 0179 0180 /** 0181 * @overload 0182 */ 0183 bool sendSystemMessage(const QDataStream &msg, int msgid, quint32 receiver = 0, quint32 sender = 0); 0184 0185 /** 0186 * @overload 0187 */ 0188 bool sendSystemMessage(const QString &msg, int msgid, quint32 receiver = 0, quint32 sender = 0); 0189 0190 /** 0191 * Sends a network message 0192 * @param error The error code 0193 * @param message The error message - use KGameError 0194 * @param receiver the KGame / KPlayer this message is for. 0 For 0195 * all 0196 * @param sender The KGame / KPlayer this message is from (i.e. 0197 * you). You probably want to leave this 0, then KGameNetwork will create 0198 * the correct value for you. You might want to use this if you send a 0199 * message from a specific player. 0200 */ 0201 void sendError(int error, const QByteArray &message, quint32 receiver = 0, quint32 sender = 0); 0202 0203 /** 0204 * Are we still offer offering server connections - only for game MASTER 0205 * @return true/false 0206 */ 0207 bool isOfferingConnections() const; 0208 0209 /** 0210 * Application cookie. this identifies the game application. It 0211 * help to distinguish between e.g. KPoker and KWin4 0212 * @return the application cookie 0213 */ 0214 int cookie() const; 0215 0216 /** 0217 * Send a network message msg with a given message ID msgid to all clients. 0218 * You want to use this to send a message to the clients. 0219 * 0220 * Note that a message is always sent to ALL clients! This is necessary so 0221 * that all clients always have the same data and can easily be changed from 0222 * network to non-network without restarting the game. If you want a 0223 * specific KGame / KPlayer to react to the message use the 0224 * receiver and sender parameters. See KGameMessage::calsMessageId 0225 * 0226 * SendMessage differs from sendSystemMessage only by the msgid parameter. 0227 * sendSystemMessage is thought as a KGame only method while 0228 * sendMessage is for public use. The msgid parameter will be 0229 * +=KGameMessage::IdUser and in KGame::signalNetworkData msgid will 0230 * be -= KGameMessage::IdUser again, so that one can easily distinguish 0231 * between system and user messages. 0232 * 0233 * Use sendSystemMessage to communicate with KGame (e.g. by adding a 0234 * player) and sendMessage for your own user message. 0235 * 0236 * Note: a player should send messages through a KGameIO! 0237 * 0238 * @param buffer the message which will be send. See messages.txt for contents 0239 * @param msgid an id for this message. See KGameMessage::GameMessageIds 0240 * @param receiver the KGame / KPlayer this message is for. 0241 * @param sender The KGame / KPlayer this message is from (i.e. 0242 * you). You 0243 * probably want to leave this 0, then KGameNetwork will create the correct 0244 * value for you. You might want to use this if you send a message from a 0245 * specific player. 0246 * @return true if worked 0247 */ 0248 // AB: TODO: doc on how "receiver" and "sender" should be created! 0249 bool sendMessage(const QByteArray &buffer, int msgid, quint32 receiver = 0, quint32 sender = 0); 0250 0251 /** 0252 * This is an overloaded member function, provided for convenience. 0253 */ 0254 bool sendMessage(const QDataStream &msg, int msgid, quint32 receiver = 0, quint32 sender = 0); 0255 0256 /** 0257 * This is an overloaded member function, provided for convenience. 0258 */ 0259 bool sendMessage(const QString &msg, int msgid, quint32 receiver = 0, quint32 sender = 0); 0260 0261 /** 0262 * This is an overloaded member function, provided for convenience. 0263 */ 0264 bool sendMessage(int data, int msgid, quint32 receiver = 0, quint32 sender = 0); 0265 0266 /** 0267 * Called by ReceiveNetworkTransmission(). Will be overwritten by 0268 * KGame and handle the incoming message. 0269 */ 0270 virtual void networkTransmission(QDataStream &, int, quint32, quint32, quint32 clientID) = 0; 0271 0272 /** 0273 * Disconnect the current connection and establish a new local one. 0274 */ 0275 void disconnect(); 0276 0277 /** 0278 * If you are the ADMIN of the game you can give the ADMIN status away to 0279 * another client. Use this e.g. if you want to quit the game or if you want 0280 * another client to administrate the game (note that disconnect calls 0281 * this automatically). 0282 * @param clientID the ID of the new ADMIN (note: this is the _client_ID 0283 * which has nothing to do with the player IDs. See KMessageServer) 0284 */ 0285 void electAdmin(quint32 clientID); 0286 0287 /** 0288 * Don't use this unless you really know what you're doing! You might 0289 * experience some strange behaviour if you send your messages directly 0290 * through the KMessageClient! 0291 * 0292 * @return a pointer to the KMessageClient used internally to send the 0293 * messages. You should rather use one of the send functions! 0294 */ 0295 KMessageClient *messageClient() const; 0296 0297 /** 0298 * Don't use this unless you really know what you are doing! You might 0299 * experience some strange behaviour if you use the message server directly! 0300 * 0301 * @return a pointer to the message server if this is the MASTER KGame 0302 * object. Note that it might be possible that no KGame object contains 0303 * the KMessageServer at all! It might even run stand alone! 0304 */ 0305 KMessageServer *messageServer() const; 0306 0307 /** 0308 * You should call this before doing thigs like, e.g. qApp->processEvents(). 0309 * Don't forget to call unlock once you are done! 0310 * 0311 * @see KMessageClient::lock 0312 */ 0313 virtual void lock(); 0314 0315 /** 0316 * @see KMessageClient::unlock 0317 */ 0318 virtual void unlock(); 0319 0320 Q_SIGNALS: 0321 /** 0322 * A network error occurred 0323 * @param error the error code 0324 * @param text the error text 0325 */ 0326 void signalNetworkErrorMessage(int error, const QString &text); 0327 0328 /** 0329 * Our connection to the KMessageServer has broken. 0330 * See KMessageClient::connectionBroken 0331 */ 0332 void signalConnectionBroken(); 0333 0334 /** 0335 * This signal is emitted whenever the KMessageServer sends us a message that a 0336 * new client connected. KGame uses this to call KGame::negotiateNetworkGame 0337 * for the newly connected client if we are admin (see isAdmin) 0338 * 0339 * @see KMessageClient::eventClientConnected 0340 * 0341 * @param clientID the ID of the newly connected client 0342 */ 0343 void signalClientConnected(quint32 clientID); 0344 0345 /** 0346 * This signal is emitted whenever the KMessageServer sends us a message 0347 * that a connection to a client was detached. The second parameter can be used 0348 * to distinguish between network errors or removing on purpose. 0349 * 0350 * @see KMessageClient::eventClientDisconnected 0351 * 0352 * @param clientID the client that has disconnected 0353 * @param broken true if the connection was lost because of a network error, false 0354 * if the connection was closed by the message server admin. 0355 */ 0356 void signalClientDisconnected(quint32 clientID, bool broken); 0357 0358 /** 0359 * This client gets or loses the admin status. 0360 * @see KMessageClient::adminStatusChanged 0361 * @param isAdmin True if this client gets the ADMIN status otherwise FALSE 0362 */ 0363 void signalAdminStatusChanged(bool isAdmin); 0364 0365 protected: 0366 /** 0367 * @internal 0368 * Start a KMessageServer object and use it as the MASTER of the game. 0369 * Note that you must not call this if there is already another master 0370 * running! 0371 */ 0372 void setMaster(); 0373 0374 protected Q_SLOTS: 0375 /** 0376 * Called by KMessageClient::broadcastReceived() and will check if the 0377 * message format is valid. If it is not, it will generate an error (see 0378 * signalNetworkVersionError and signalNetworkErorrMessage). 0379 * If it is valid, the pure virtual method networkTransmission() is called. 0380 * (This one is overwritten in KGame.) 0381 */ 0382 void receiveNetworkTransmission(const QByteArray &a, quint32 clientID); 0383 0384 /** 0385 * This KGame object receives or loses the admin status. 0386 * @param isAdmin Whether we are admin or not 0387 */ 0388 void slotAdminStatusChanged(bool isAdmin); 0389 0390 /** 0391 * Called when the network connection is about to terminate. Is used 0392 * to store the network parameter like the game id 0393 */ 0394 void aboutToLoseConnection(quint32 id); 0395 0396 /** 0397 * Called when the network connection is terminated. Used to clean 0398 * up the disconnect parameter 0399 */ 0400 void slotResetConnection(); 0401 0402 private: 0403 void tryPublish(); 0404 void tryStopPublishing(); 0405 0406 private: 0407 std::unique_ptr<KGameNetworkPrivate> const d; 0408 }; 0409 0410 #endif