File indexing completed on 2024-05-26 04:09:56
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 __KGAME_H_ 0010 #define __KGAME_H_ 0011 0012 // own 0013 #include "kdegamesprivate_export.h" 0014 #include "kgamenetwork.h" 0015 // Qt 0016 #include <QDataStream> 0017 #include <QList> 0018 #include <QString> 0019 0020 class KPlayer; 0021 class KGamePropertyBase; 0022 class KGamePropertyHandler; 0023 class KGameSequence; 0024 0025 class KGamePrivate; 0026 0027 /** 0028 * \class KGame kgame.h <KGame/KGame> 0029 * 0030 * @short The main KDE game object 0031 * 0032 * The KGame class is the central game object. A game basically 0033 * consists of following features: 0034 * - Player handling (add, remove,...) 0035 * - Game status (end,start,pause,...) 0036 * - load/save 0037 * - Move (and message) handling 0038 * - nextPlayer and gameOver() 0039 * - Network connection (for KGameNetwork) 0040 * 0041 * Example: 0042 * \code 0043 * KGame *game=new KGame; 0044 * \endcode 0045 */ 0046 class KDEGAMESPRIVATE_EXPORT KGame : public KGameNetwork 0047 { 0048 Q_OBJECT 0049 0050 public: 0051 typedef QList<KPlayer *> KGamePlayerList; 0052 0053 /** 0054 * The policy of the property. This can be PolicyClean (setVale uses 0055 * send), PolicyDirty (setValue uses changeValue) or 0056 * PolicyLocal (setValue uses setLocal). 0057 * 0058 * A "clean" policy means that the property is always the same on every 0059 * client. This is achieved by calling send which actually changes 0060 * the value only when the message from the MessageServer is received. 0061 * 0062 * A "dirty" policy means that as soon as setValue is called the 0063 * property is changed immediately. And additionally sent over network. 0064 * This can sometimes lead to bugs as the other clients do not 0065 * immediately have the same value. For more information see 0066 * changeValue. 0067 * 0068 * PolicyLocal means that a KGameProperty behaves like ever 0069 * "normal" variable. Whenever setValue is called (e.g. using "=") 0070 * the value of the property is changes immediately without sending it 0071 * over network. You might want to use this if you are sure that all 0072 * clients set the property at the same time. 0073 */ 0074 enum GamePolicy { PolicyUndefined = 0, PolicyClean = 1, PolicyDirty = 2, PolicyLocal = 3 }; 0075 0076 /** 0077 * Create a KGame object. The cookie is used to identify your 0078 * game in load/save and network operations. Change this between 0079 * games. 0080 */ 0081 explicit KGame(int cookie = 42, QObject *parent = nullptr); 0082 0083 /** 0084 * Destructs the game 0085 */ 0086 ~KGame() override; 0087 0088 /** 0089 * Gives debug output of the game status 0090 */ 0091 void Debug() override; 0092 0093 /** 0094 * Game status - Use this to Control the game flow. 0095 * The KGame e.g. sets the status to Pause when you have 0096 * less player than the minimum amount 0097 */ 0098 enum GameStatus { Init = 0, Run = 1, Pause = 2, End = 3, Abort = 4, SystemPause = 5, Intro = 6, UserStatus = 7 }; 0099 0100 // Properties 0101 /** 0102 * Returns a list of all active players 0103 * 0104 * @return the list of players 0105 */ 0106 KGamePlayerList *playerList(); 0107 0108 /** 0109 * The same as @ref playerList but returns a const pointer. 0110 */ 0111 const KGamePlayerList *playerList() const; 0112 0113 /** 0114 * Returns a list of all inactive players 0115 * @return the list of players 0116 */ 0117 KGamePlayerList *inactivePlayerList(); 0118 0119 /** 0120 * The same as @ref inactivePlayerList but returns a const pointer. 0121 */ 0122 const KGamePlayerList *inactivePlayerList() const; 0123 0124 /** 0125 * @return The KGameSequence object that is currently in use. 0126 * @see setGameSequence 0127 */ 0128 KGameSequence *gameSequence() const; 0129 0130 /** 0131 * Is the game running 0132 * @return true/false 0133 */ 0134 bool isRunning() const; 0135 0136 // Player handling 0137 /** 0138 * Returns the player object for a given player id 0139 * @param id Player id 0140 * @return player object 0141 */ 0142 KPlayer *findPlayer(quint32 id) const; 0143 0144 /** 0145 * Set a new @ref KGameSequence to control player management. By default 0146 * KGame uses a normal @ref KGameSequence object. You might want to subclass 0147 * that and provide your own object. 0148 * 0149 * The previous sequence will get deleted. 0150 * @param sequence The new game sequence object. KGame takes ownership and 0151 * will delete it on destruction! 0152 */ 0153 void setGameSequence(KGameSequence *sequence); 0154 0155 /** 0156 * Note that KPlayer::save must be implemented properly, as well as 0157 * KPlayer::rtti 0158 * This will only send a message to all clients. The player is _not_ added 0159 * directly! 0160 * See also playerInput which will be called as soon as the 0161 * player really has been added. 0162 * 0163 * Note that an added player will first get into a "queue" and won't be in 0164 * the game. It will be added to the game as soon as systemAddPlayer is 0165 * called what will happen as soon as IdAddPlayer is received. 0166 * 0167 * Note: you probably want to connect to signalPlayerJoinedGame for 0168 * further initialization! 0169 * @param newplayer The player you want to add. KGame will send a message to 0170 * all clients and add the player using systemAddPlayer 0171 */ 0172 bool addPlayer(KPlayer *newplayer); 0173 0174 /** 0175 * Sends a message over the network, msgid=IdRemovePlayer. 0176 * 0177 * As soon as this message is received by networkTransmission 0178 * systemRemovePlayer is called and the player is removed. 0179 */ 0180 // AB: TODO: make sendMessage to return if the message will be able to be 0181 // sent, eg if a socket is connected, etc. If sendMessage returns false 0182 // remove the player directly using systemRemovePlayer 0183 bool removePlayer(KPlayer *player) 0184 { 0185 return removePlayer(player, 0); 0186 } 0187 0188 /** 0189 * Called by the destructor of KPlayer to remove itself from the game 0190 * 0191 */ 0192 void playerDeleted(KPlayer *player); 0193 0194 /** 0195 * sends activate player: internal use only? 0196 */ 0197 bool activatePlayer(KPlayer *player); 0198 0199 /** 0200 * sends inactivate player: internal use only? 0201 */ 0202 bool inactivatePlayer(KPlayer *player); 0203 0204 /** 0205 * Set the maximal number of players. After this is 0206 * reached no more players can be added. You must be ADMIN to call this (@see 0207 * isAdmin). 0208 * @param maxnumber maximal number of players 0209 */ 0210 void setMaxPlayers(uint maxnumber); 0211 0212 /** 0213 * What is the maximal number of players? 0214 * @return maximal number of players 0215 */ 0216 int maxPlayers() const; 0217 0218 /** 0219 * Set the minimal number of players. A game can not be started 0220 * with less player resp. is paused when already running. You must be ADMIN 0221 * to call this (see @ref isAdmin)! 0222 * @param minnumber minimal number of players 0223 */ 0224 void setMinPlayers(uint minnumber); 0225 0226 /** 0227 * What is the minimal number of players? 0228 * @return minimal number of players 0229 */ 0230 uint minPlayers() const; 0231 0232 /** 0233 * Returns how many players are plugged into the game 0234 * @return number of players 0235 */ 0236 uint playerCount() const; 0237 0238 // Input events 0239 /** 0240 * Called by KPlayer to send a player input to the 0241 * KMessageServer. 0242 */ 0243 virtual bool sendPlayerInput(QDataStream &msg, KPlayer *player, quint32 sender = 0); 0244 0245 /** 0246 * Called when a player input arrives from KMessageServer. 0247 * 0248 * Calls prepareNext (using QTimer::singleShot) if gameOver() 0249 * returns 0. This function should normally not be used outside KGame. 0250 * It could be made non-virtual,protected in a later version. At the 0251 * moment it is a virtual function to give you more control over KGame. 0252 * 0253 * For documentation see playerInput. 0254 */ 0255 virtual bool systemPlayerInput(QDataStream &msg, KPlayer *player, quint32 sender = 0); 0256 0257 /** 0258 * This virtual function is called if the KGame needs to create a new player. 0259 * This happens only over a network and with load/save. Doing nothing 0260 * will create a default KPlayer. If you want to have your own player 0261 * you have to create one with the given rtti here. 0262 * Note: If your game uses a player class derived from KPlayer you MUST 0263 * override this function and create your player here. Otherwise the 0264 * game will crash. 0265 * Example: 0266 * \code 0267 * KPlayer *MyGame::createPlayer(int rtti,int io,bool isvirtual) 0268 * { 0269 * KPlayer *player=new MyPlayer; 0270 * if (!isvirtual) // network player ? 0271 * { 0272 * // Define something like this to add the IO modules 0273 * createIO(player,(KGameIO::IOMode)io); 0274 * } 0275 * return player; 0276 * } 0277 * \endcode 0278 * 0279 * @param rtti is the type of the player (0 means default KPlayer) 0280 * @param io is the 'or'ed rtti of the KGameIO's 0281 * @param isvirtual true if player is virtual 0282 */ 0283 virtual KPlayer *createPlayer(int rtti, int io, bool isvirtual); 0284 0285 // load/save 0286 /** 0287 * Load a saved game, from file OR network. This function has 0288 * to be overwritten or you need to connect to the load signal 0289 * if you have game data other than KGameProperty. 0290 * For file load you should reset() the game before any load attempt 0291 * to make sure you load into an clear state. 0292 * 0293 * @param stream a data stream where you can stream the game from 0294 * @param reset - shall the game be reset before loading 0295 * 0296 * @return true? 0297 */ 0298 virtual bool load(QDataStream &stream, bool reset = true); 0299 0300 /** 0301 * Same as above function but with different parameters 0302 * 0303 * @param filename - the filename of the file to be opened 0304 * @param reset - shall the game be reset before loading 0305 * 0306 * @return true? 0307 */ 0308 virtual bool load(const QString &filename, bool reset = true); 0309 0310 /** 0311 * Save a game to a file OR to network. Otherwise the same as 0312 * the load function 0313 * 0314 * @param stream a data stream to load the game from 0315 * @param saveplayers If true then all players wil be saved too 0316 * 0317 * @return true? 0318 */ 0319 virtual bool save(QDataStream &stream, bool saveplayers = true); 0320 0321 /** 0322 * Same as above function but with different parameters 0323 * 0324 * @param filename the filename of the file to be saved 0325 * @param saveplayers If true then all players wil be saved too 0326 * 0327 * @return true? 0328 */ 0329 virtual bool save(const QString &filename, bool saveplayers = true); 0330 0331 /** 0332 * Resets the game, i.e. puts it into a state where everything 0333 * can be started from, e.g. a load game 0334 * Right now it does only need to delete all players 0335 * 0336 * @return true on success 0337 */ 0338 virtual bool reset(); 0339 0340 // Game sequence 0341 /** 0342 * returns the game status, ie running,pause,ended,... 0343 * 0344 * @return game status 0345 */ 0346 int gameStatus() const; 0347 0348 /** 0349 * sets the game status 0350 * 0351 * @param status the new status 0352 */ 0353 void setGameStatus(int status); 0354 0355 /** 0356 * docu: see KPlayer 0357 */ 0358 bool addProperty(KGamePropertyBase *data); 0359 0360 /** 0361 * This is called by KPlayer::sendProperty only! Internal function! 0362 */ 0363 bool sendPlayerProperty(int msgid, QDataStream &s, quint32 playerId); 0364 0365 /** 0366 * This function allows to find the pointer to a player 0367 * property when you know its id 0368 */ 0369 KGamePropertyBase *findProperty(int id) const; 0370 0371 /** 0372 * Changes the consistency policy of a property. The 0373 * GamePolicy is one of PolicyClean (default), PolicyDirty or PolicyLocal. 0374 * 0375 * It is up to you to decide how you want to work. 0376 */ 0377 void setPolicy(GamePolicy p, bool recursive = true); 0378 0379 /** 0380 * @return The default policy of the property 0381 */ 0382 GamePolicy policy() const; 0383 0384 /** 0385 * See KGameNetwork::sendMessage 0386 * 0387 * Send a network message msg with a given message ID msgid to all players of 0388 * a given group (see KPlayer::group) 0389 * @param msg the message which will be send. See messages.txt for contents 0390 * @param msgid an id for this message 0391 * @param sender the id of the sender 0392 * @param group the group of the receivers 0393 * @return true if worked 0394 */ 0395 bool sendGroupMessage(const QByteArray &msg, int msgid, quint32 sender, const QString &group); 0396 bool sendGroupMessage(const QDataStream &msg, int msgid, quint32 sender, const QString &group); 0397 bool sendGroupMessage(int msg, int msgid, quint32 sender, const QString &group); 0398 bool sendGroupMessage(const QString &msg, int msgid, quint32 sender, const QString &group); 0399 0400 /** 0401 * This will either forward an incoming message to a specified player 0402 * (see KPlayer::networkTransmission) or 0403 * handle the message directly (e.g. if msgif==IdRemovePlayer it will remove 0404 * the (in the stream) specified player). If both is not possible (i.e. the 0405 * message is user specified data) the signal signalNetworkData is 0406 * emitted. 0407 * 0408 * This emits signalMessageUpdate <em>before</em> doing anything with 0409 * the message. You can use this signal when you want to be notified about 0410 * an update/change. 0411 * @param msgid Specifies the kind of the message. See messages.txt for 0412 * further information 0413 * @param stream The message that is being sent 0414 * @param receiver The is of the player this message is for. 0 For broadcast. 0415 * @param sender 0416 * @param clientID the client from which we received the transmission - hardly used 0417 */ 0418 void networkTransmission(QDataStream &stream, int msgid, quint32 receiver, quint32 sender, quint32 clientID) override; 0419 0420 /** 0421 * Returns a pointer to the KGame property handler 0422 */ 0423 KGamePropertyHandler *dataHandler() const; 0424 0425 protected Q_SLOTS: 0426 /** 0427 * Called by KGamePropertyHandler only! Internal function! 0428 */ 0429 void sendProperty(int msgid, QDataStream &stream, bool *sent); 0430 0431 /** 0432 * Called by KGamePropertyHandler only! Internal function! 0433 */ 0434 void emitSignal(KGamePropertyBase *me); 0435 0436 /** 0437 * Calls negotiateNetworkGame() 0438 * See KGameNetwork::signalClientConnected 0439 */ 0440 void slotClientConnected(quint32 clientId); 0441 0442 /** 0443 * This slot is called whenever the connection to a client is lost (ie the 0444 * signal KGameNetwork::signalClientDisconnected is emitted) and will remove 0445 * the players from that client. 0446 * @param clientId The client the connection has been lost to 0447 * @param broken (ignore this - not used) 0448 */ 0449 void slotClientDisconnected(quint32 clientId, bool broken); 0450 0451 /** 0452 * This slot is called whenever the connection to the server is lost (ie the 0453 * signal KGameNetwork::signalConnectionBroken is emitted) and will 0454 * switch to local game mode 0455 */ 0456 void slotServerDisconnected(); 0457 0458 Q_SIGNALS: 0459 /** 0460 * When a client disconnects from the game usually all players from that 0461 * client are removed. But if you use completely the KGame structure you 0462 * probably don't want this. You just want to replace the KGameIO of the 0463 * (human) player by a computer KGameIO. So this player continues game but 0464 * is from this point on controlled by the computer. 0465 * 0466 * You achieve this by connecting to this signal. It is emitted as soon as a 0467 * client disconnects on <em>all</em> other clients. Make sure to add a new 0468 * KGameIO only once! you might want to use @ref isAdmin for this. If you 0469 * added a new KGameIO set *remove=false otherwise the player is completely 0470 * removed. 0471 * @param player The player that is about to be removed. Add your new 0472 * KGameIO here - but only on <em>one</em> client! 0473 * @param remove Set this to FALSE if you don't want this player to be 0474 * removed completely. 0475 */ 0476 void signalReplacePlayerIO(KPlayer *player, bool *remove); 0477 0478 /** 0479 * The game will be loaded from the given stream. Load from here 0480 * the data which is NOT a game or player property. 0481 * It is not necessary to use this signal for a full property game. 0482 * 0483 * This signal is emitted <em>before</em> the players are loaded by 0484 * KGame. See also signalLoad 0485 * 0486 * You must load <em>exactly</em> the same data from the stream that you have saved 0487 * in signalSavePrePlayers. Otherwise player loading will not work 0488 * anymore. 0489 * 0490 * @param stream the load stream 0491 */ 0492 void signalLoadPrePlayers(QDataStream &stream); 0493 0494 /** 0495 * The game will be loaded from the given stream. Load from here 0496 * the data which is NOT a game or player property. 0497 * It is not necessary to use this signal for a full property game. 0498 * 0499 * @param stream the load stream 0500 */ 0501 void signalLoad(QDataStream &stream); 0502 0503 /** 0504 * The game will be saved to the given stream. Fill this with data 0505 * which is NOT a game or player property. 0506 * It is not necessary to use this signal for a full property game. 0507 * 0508 * This signal is emitted <em>before</em> the players are saved by 0509 * KGame. See also signalSave 0510 * 0511 * If you can choose between signalSavePrePlayers and signalSave then 0512 * better use signalSave 0513 * 0514 * @param stream the save stream 0515 */ 0516 void signalSavePrePlayers(QDataStream &stream); 0517 0518 /** 0519 * The game will be saved to the given stream. Fill this with data 0520 * which is NOT a game or player property. 0521 * It is not necessary to use this signal for a full property game. 0522 * 0523 * @param stream the save stream 0524 */ 0525 void signalSave(QDataStream &stream); 0526 0527 /** 0528 * Is emitted if a game with a different version cookie is loaded. 0529 * Normally this should result in an error. But maybe you do support 0530 * loading of older game versions. Here would be a good place to do a 0531 * conversion. 0532 * 0533 * @param stream - the load stream 0534 * @param network - true if this is a network connect. False for load game 0535 * @param cookie - the saved cookie. It differs from KGame::cookie() 0536 * @param result - set this to true if you managed to load the game 0537 */ 0538 void signalLoadError(QDataStream &stream, bool network, int cookie, bool &result); 0539 0540 /** 0541 * We got an user defined update message. This is usually done 0542 * by a sendData in a inherited KGame Object which defines its 0543 * own methods and has to synchronize them over the network. 0544 * Reaction to this is usually a call to a KGame function. 0545 */ 0546 void signalNetworkData(int msgid, const QByteArray &buffer, quint32 receiver, quint32 sender); 0547 0548 /** 0549 * We got an network message. this can be used to notify us that something 0550 * changed. What changed can be seen in the message id. Whether this is 0551 * the best possible method to do this is unclear... 0552 */ 0553 void signalMessageUpdate(int msgid, quint32 receiver, quint32 sender); 0554 0555 /** 0556 * a player left the game because of a broken connection or so! 0557 * 0558 * Note that when this signal is emitted the player is not part of @ref 0559 * playerList anymore but the pointer is still valid. You should do some 0560 * final cleanups here since the player is usually deleted after the signal 0561 * is emitted. 0562 * 0563 * @param player the player who left the game 0564 */ 0565 void signalPlayerLeftGame(KPlayer *player); 0566 0567 /** 0568 * a player joined the game 0569 * 0570 * @param player the player who joined the game 0571 */ 0572 void signalPlayerJoinedGame(KPlayer *player); 0573 0574 /** 0575 * This signal is emitted if a player property changes its value and 0576 * the property is set to notify this change 0577 */ 0578 void signalPropertyChanged(KGamePropertyBase *property, KGame *me); 0579 0580 /** 0581 * Is emitted after a call to gameOver() returns a non zero 0582 * return code. This code is forwarded to this signal as 'status'. 0583 * 0584 * @param status the return code of gameOver() 0585 * @param current the player who did the last move 0586 * @param me a pointer to the KGame object 0587 */ 0588 void signalGameOver(int status, KPlayer *current, KGame *me); 0589 0590 /** 0591 * Is emitted after a client is successfully connected to the game. 0592 * The client id is the id of the new game client. An easy way to 0593 * check whether that's us is 0594 * \code 0595 * if (clientid==gameid()) .. // we joined 0596 * else ... // someone joined the game 0597 * \endcode 0598 * @param clientid - The id of the new client 0599 * @param me - our game pointer 0600 */ 0601 void signalClientJoinedGame(quint32 clientid, KGame *me); 0602 0603 /** 0604 * This signal is emitted after a network partner left the 0605 * game (either by a broken connection or voluntarily). 0606 * All changes to the network players have already be done. 0607 * If there are not enough players left, the game might have 0608 * been paused. To check this you get the old gamestatus 0609 * before the disconnection as argument here. The id of the 0610 * client who left the game allows to distinguish who left the 0611 * game. If it is 0, the server disconnected and you were a client 0612 * which has been switched back to local play. 0613 * You can use this signal to, e.g. set some menus back to local 0614 * player when they were network before. 0615 * 0616 * @param clientID - 0:server left, otherwise the client who left 0617 * @param oldgamestatus - the gamestatus before the loss 0618 * @param me - our game pointer 0619 */ 0620 void signalClientLeftGame(int clientID, int oldgamestatus, KGame *me); 0621 0622 protected: 0623 /** 0624 * A player input occurred. This is the most important function 0625 * as the given message will contain the current move made by 0626 * the given player. 0627 * Note that you HAVE to overwrite this function. Otherwise your 0628 * game makes no sense at all. 0629 * Generally you have to return TRUE in this function. Only then 0630 * the game sequence is proceeded by calling @ref playerInputFinished 0631 * which in turn will check for game over or the next player 0632 * However, if you have a delayed move, because you e.g. move a 0633 * card or a piece you want to return FALSE to pause the game sequence 0634 * and then manually call @ref playerInputFinished to resume it. 0635 * Example: 0636 * \code 0637 * bool MyClass::playerInput(QDataStream &msg,KPlayer *player) 0638 * { 0639 * qint32 move; 0640 * msg >> move; 0641 * qDebug() << " Player" << player->id() << "moved to" << move; 0642 * return true; 0643 * } 0644 * \endcode 0645 * 0646 * @param msg the move message 0647 * @param player the player who did the move 0648 * @return true - input ready, false: input manual 0649 */ 0650 virtual bool playerInput(QDataStream &msg, KPlayer *player) = 0; 0651 0652 /** 0653 * Called after the player input is processed by the game. Here the 0654 * checks for game over and nextPlayer (in the case of turn base games) 0655 * are processed. 0656 * Call this manually if you have a delayed move, i.e. your playerInput 0657 * function returns FALSE. If it returns true you need not do anything 0658 * here. 0659 * 0660 * @return the current player 0661 * 0662 */ 0663 KPlayer *playerInputFinished(KPlayer *player); 0664 0665 /** 0666 * This virtual function can be overwritten for your own player management. 0667 * It is called when a new game connects to an existing network game or 0668 * to the network master. In case you do not want all players of both games 0669 * to be present in the new network game, you can deactivate players here. 0670 * This is of particular importance if you have a game with fixed number of 0671 * player like e.g. chess. A network connect needs to disable one player of 0672 * each game to make sense. 0673 * 0674 * Not overwriting this function will activate a default behaviour which 0675 * will deactivate players until the @ref maxPlayers() number is reached 0676 * according to the KPlayer::networkPriority() value. Players with a low 0677 * value will be kicked out first. With equal priority players of the new 0678 * client will leave first. This means, not setting this value and not 0679 * overwriting this function will never allow a chess game to add client 0680 * players!!! 0681 * On the other hand setting one player of each game to a networkPriorty of 0682 * say 10, already does most of the work for you. 0683 * 0684 * The parameters of this function are the playerlist of the network game, 0685 * which is @ref playerList(). The second argument is the player list of 0686 * the new client who wants to join and the third argument serves as return 0687 * parameter. All <em>player ID's</em> which are written into this list 0688 * will be <em>removed</em> from the created game. You do this by an 0689 * \code 0690 * inactivate.append(player->id()); 0691 * \endcode 0692 * 0693 * @param oldplayer - the list of the network players 0694 * @param newplayer - the list of the client players 0695 * @param inactivate - the value list of ids to be deactivated 0696 * 0697 */ 0698 virtual void newPlayersJoin(KGamePlayerList *oldplayer, KGamePlayerList *newplayer, QList<int> &inactivate) 0699 { 0700 Q_UNUSED(oldplayer); 0701 Q_UNUSED(newplayer); 0702 Q_UNUSED(inactivate); 0703 } 0704 0705 /** 0706 * Save the player list to a stream. Used for network game and load/save. 0707 * Can be overwritten if you know what you are doing 0708 * 0709 * @param stream is the stream to save the player ot 0710 * @param list the optional list is the player list to be saved, default is playerList() 0711 * 0712 */ 0713 void savePlayers(QDataStream &stream, KGamePlayerList *list = nullptr); 0714 0715 /** 0716 * Prepare a player for being added. Put all data about a player into the 0717 * stream so that it can be sent to the KGameCommunicationServer using 0718 * addPlayer (e.g.) 0719 * 0720 * This function ensures that the code for adding a player is the same in 0721 * addPlayer as well as in negotiateNetworkGame 0722 * @param stream is the stream to add the player 0723 * @param player The player to add 0724 */ 0725 void savePlayer(QDataStream &stream, KPlayer *player); 0726 0727 /** 0728 * Load the player list from a stream. Used for network game and load/save. 0729 * Can be overwritten if you know what you are doing 0730 * 0731 * @param stream is the stream to save the player to 0732 * @param isvirtual will set the virtual flag true/false 0733 * 0734 */ 0735 KPlayer *loadPlayer(QDataStream &stream, bool isvirtual = false); 0736 0737 /** 0738 * inactivates player. Use @ref inactivatePlayer instead! 0739 */ 0740 bool systemInactivatePlayer(KPlayer *player); 0741 0742 /** 0743 * activates player. Use @ref activatePlayer instead! 0744 */ 0745 bool systemActivatePlayer(KPlayer *player); 0746 0747 /** 0748 * Adds a player to the game 0749 * 0750 * Use @ref addPlayer to send @ref KGameMessage::IdAddPlayer. As soon as 0751 * this Id is received this function is called, where the player (see @ref 0752 * KPlayer::rtti) is added as well as its properties (see @ref KPlayer::save 0753 * and @ref KPlayer::load) 0754 * 0755 * This method calls the overloaded @ref systemAddPlayer with the created 0756 * player as argument. That method will really add the player. 0757 * If you need to do some changes to your newly added player just connect to 0758 * @ref signalPlayerJoinedGame 0759 */ 0760 0761 /** 0762 * Finally adds a player to the game and therefore to the list. 0763 */ 0764 bool systemAddPlayer(KPlayer *newplayer); 0765 0766 /** 0767 * Removes a player from the game 0768 * 0769 * Use removePlayer to send KGameMessage::IdRemovePlayer. As soon 0770 * as this Id is received systemRemovePlayer is called and the player is 0771 * removed directly. 0772 */ 0773 void systemRemovePlayer(KPlayer *player, bool deleteit); 0774 0775 /** 0776 * This member function will transmit e.g. all players to that client, as well as 0777 * all properties of these players (at least if they have been added by 0778 * @ref KPlayer::addProperty) so that the client will finally have the same 0779 * status as the master. You want to overwrite this function if you expand 0780 * KGame by any properties which have to be known by all clients. 0781 * 0782 * Only the ADMIN is allowed to call this. 0783 * @param clientID The ID of the message client which has connected 0784 */ 0785 virtual void negotiateNetworkGame(quint32 clientID); 0786 0787 void deletePlayers(); 0788 void deleteInactivePlayers(); 0789 0790 /** 0791 * Load a saved game, from file OR network. Internal. 0792 * Warning: loadgame must not rely that all players all already 0793 * activated. Actually the network will activate a player AFTER 0794 * the loadgame only. This is not true anymore. But be careful 0795 * anyway. 0796 * 0797 * @param stream a data stream where you can stream the game from 0798 * @param network is it a network call -> make players virtual 0799 * @param reset shall the game be reset before loading 0800 * 0801 * @return true? 0802 */ 0803 virtual bool loadgame(QDataStream &stream, bool network, bool reset); 0804 0805 /** 0806 * Save a game, to file OR network. Internal. 0807 * 0808 * @param stream a data stream where you can stream the game from 0809 * @param network is it a call from the network or from a file (unused but informative) 0810 * @param saveplayers shall the players be saved too (should be TRUE) 0811 * 0812 * @return true? 0813 */ 0814 virtual bool savegame(QDataStream &stream, bool network, bool saveplayers); 0815 0816 private: 0817 // AB: this is to hide the "receiver" parameter from the user. It shouldn't be 0818 // used if possible (except for init). 0819 /** 0820 * This is an overloaded function. Id differs from the public one only in 0821 * its parameters: 0822 * 0823 * @param receiver The Client that will receive the message. You will hardly 0824 * ever need this. It it internally used to initialize a newly connected 0825 * client. 0826 */ 0827 // void addPlayer(KPlayer* newplayer, quint32 receiver); 0828 0829 /** 0830 * Just the same as the public one except receiver: 0831 * @param receiver 0 for broadcast, otherwise the receiver. Should only be 0832 * used in special circumstances and not outside KGame. 0833 */ 0834 bool removePlayer(KPlayer *player, quint32 receiver); 0835 0836 /** 0837 * Helping function - game negotiation 0838 */ 0839 void setupGame(quint32 sender); 0840 0841 /** 0842 * Helping function - game negotiation 0843 */ 0844 void setupGameContinue(QDataStream &msg, quint32 sender); 0845 0846 /** 0847 * Removes a player from all lists, removes the @ref KGame pointer from the 0848 * @ref KPlayer and deletes the player. Used by (e.g.) @ref 0849 * systemRemovePlayer 0850 * @return True if the player has been removed, false if the current is not 0851 * found 0852 */ 0853 bool systemRemove(KPlayer *player, bool deleteit); 0854 0855 private: 0856 KGamePrivate *const d; 0857 }; 0858 0859 #endif