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