KDEGames

kgame.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 __KGAME_H_
10 #define __KGAME_H_
11 
12 // own
13 #include "kgamenetwork.h"
14 #include "libkdegamesprivate_export.h"
15 // KF
16 #include <kcoreaddons_export.h> // for KCOREADDONS_ENABLE_DEPRECATED_SINCE
17 // Qt
18 #include <QDataStream>
19 #include <QList>
20 #include <QLoggingCategory>
21 #include <QString>
22 
23 Q_DECLARE_LOGGING_CATEGORY(GAMES_PRIVATE_KGAME)
24 
25 #if KDEGAMESPRIVATE_ENABLE_DEPRECATED_SINCE(7, 3)
26 class KRandomSequence;
27 #endif
28 
29 class KPlayer;
30 class KGamePropertyBase;
32 class KGameSequence;
33 
34 class KGamePrivate;
35 
36 /**
37  * \class KGame kgame.h <KGame/KGame>
38  *
39  * @short The main KDE game object
40  *
41  * The KGame class is the central game object. A game basically
42  * consists of following features:
43  * - Player handling (add, remove,...)
44  * - Game status (end,start,pause,...)
45  * - load/save
46  * - Move (and message) handling
47  * - nextPlayer and gameOver()
48  * - Network connection (for KGameNetwork)
49  *
50  * Example:
51  * \code
52  * KGame *game=new KGame;
53  * \endcode
54  */
55 class KDEGAMESPRIVATE_EXPORT KGame : public KGameNetwork
56 {
57  Q_OBJECT
58 
59 public:
61 
62  /**
63  * The policy of the property. This can be PolicyClean (setVale uses
64  * send), PolicyDirty (setValue uses changeValue) or
65  * PolicyLocal (setValue uses setLocal).
66  *
67  * A "clean" policy means that the property is always the same on every
68  * client. This is achieved by calling send which actually changes
69  * the value only when the message from the MessageServer is received.
70  *
71  * A "dirty" policy means that as soon as setValue is called the
72  * property is changed immediately. And additionally sent over network.
73  * This can sometimes lead to bugs as the other clients do not
74  * immediately have the same value. For more information see
75  * changeValue.
76  *
77  * PolicyLocal means that a KGameProperty behaves like ever
78  * "normal" variable. Whenever setValue is called (e.g. using "=")
79  * the value of the property is changes immediately without sending it
80  * over network. You might want to use this if you are sure that all
81  * clients set the property at the same time.
82  */
83  enum GamePolicy { PolicyUndefined = 0, PolicyClean = 1, PolicyDirty = 2, PolicyLocal = 3 };
84 
85  /**
86  * Create a KGame object. The cookie is used to identify your
87  * game in load/save and network operations. Change this between
88  * games.
89  */
90  explicit KGame(int cookie = 42, QObject *parent = nullptr);
91 
92  /**
93  * Destructs the game
94  */
95  ~KGame() override;
96 
97  /**
98  * Gives debug output of the game status
99  */
100  void Debug() override;
101 
102  /**
103  * Game status - Use this to Control the game flow.
104  * The KGame e.g. sets the status to Pause when you have
105  * less player than the minimum amount
106  */
107  enum GameStatus { Init = 0, Run = 1, Pause = 2, End = 3, Abort = 4, SystemPause = 5, Intro = 6, UserStatus = 7 };
108 
109  // Properties
110  /**
111  * Returns a list of all active players
112  *
113  * @return the list of players
114  */
115  KGamePlayerList *playerList();
116 
117  /**
118  * The same as @ref playerList but returns a const pointer.
119  */
120  const KGamePlayerList *playerList() const;
121 
122  /**
123  * Returns a list of all inactive players
124  * @return the list of players
125  */
126  KGamePlayerList *inactivePlayerList();
127 
128  /**
129  * The same as @ref inactivePlayerList but returns a const pointer.
130  */
131  const KGamePlayerList *inactivePlayerList() const;
132 
133 #if KDEGAMESPRIVATE_ENABLE_DEPRECATED_SINCE(7, 3)
134 #if KCOREADDONS_ENABLE_DEPRECATED_SINCE(5, 75)
135  /**
136  * Returns a pointer to the game's KRandomSequence. This sequence is
137  * identical for all network players!
138  * @return KRandomSequence pointer
139  * @deprecated Since 7.3, no known users. Any replacement should use QRandomGenerator.
140  */
141  KDEGAMESPRIVATE_DEPRECATED_VERSION(7, 3, "No known users. Any replacement should use QRandomGenerator.")
142  KRandomSequence *random() const;
143 #endif
144 #endif
145 
146  /**
147  * @return The KGameSequence object that is currently in use.
148  * @see setGameSequence
149  */
150  KGameSequence *gameSequence() const;
151 
152  /**
153  * Is the game running
154  * @return true/false
155  */
156  bool isRunning() const;
157 
158  // Player handling
159  /**
160  * Returns the player object for a given player id
161  * @param id Player id
162  * @return player object
163  */
164  KPlayer *findPlayer(quint32 id) const;
165 
166  /**
167  * Set a new @ref KGameSequence to control player management. By default
168  * KGame uses a normal @ref KGameSequence object. You might want to subclass
169  * that and provide your own object.
170  *
171  * The previous sequence will get deleted.
172  * @param sequence The new game sequence object. KGame takes ownership and
173  * will delete it on destruction!
174  */
175  void setGameSequence(KGameSequence *sequence);
176 
177  /**
178  * Note that KPlayer::save must be implemented properly, as well as
179  * KPlayer::rtti
180  * This will only send a message to all clients. The player is _not_ added
181  * directly!
182  * See also playerInput which will be called as soon as the
183  * player really has been added.
184  *
185  * Note that an added player will first get into a "queue" and won't be in
186  * the game. It will be added to the game as soon as systemAddPlayer is
187  * called what will happen as soon as IdAddPlayer is received.
188  *
189  * Note: you probably want to connect to signalPlayerJoinedGame for
190  * further initialization!
191  * @param newplayer The player you want to add. KGame will send a message to
192  * all clients and add the player using systemAddPlayer
193  */
194  bool addPlayer(KPlayer *newplayer);
195 
196  /**
197  * Sends a message over the network, msgid=IdRemovePlayer.
198  *
199  * As soon as this message is received by networkTransmission
200  * systemRemovePlayer is called and the player is removed.
201  */
202  // AB: TODO: make sendMessage to return if the message will be able to be
203  // sent, eg if a socket is connected, etc. If sendMessage returns false
204  // remove the player directly using systemRemovePlayer
205  bool removePlayer(KPlayer *player)
206  {
207  return removePlayer(player, 0);
208  }
209 
210  /**
211  * Called by the destructor of KPlayer to remove itself from the game
212  *
213  */
214  void playerDeleted(KPlayer *player);
215 
216  /**
217  * sends activate player: internal use only?
218  */
219  bool activatePlayer(KPlayer *player);
220 
221  /**
222  * sends inactivate player: internal use only?
223  */
224  bool inactivatePlayer(KPlayer *player);
225 
226  /**
227  * Set the maximal number of players. After this is
228  * reached no more players can be added. You must be ADMIN to call this (@see
229  * isAdmin).
230  * @param maxnumber maximal number of players
231  */
232  void setMaxPlayers(uint maxnumber);
233 
234  /**
235  * What is the maximal number of players?
236  * @return maximal number of players
237  */
238  int maxPlayers() const;
239 
240  /**
241  * Set the minimal number of players. A game can not be started
242  * with less player resp. is paused when already running. You must be ADMIN
243  * to call this (see @ref isAdmin)!
244  * @param minnumber minimal number of players
245  */
246  void setMinPlayers(uint minnumber);
247 
248  /**
249  * What is the minimal number of players?
250  * @return minimal number of players
251  */
252  uint minPlayers() const;
253 
254  /**
255  * Returns how many players are plugged into the game
256  * @return number of players
257  */
258  uint playerCount() const;
259 
260 #if KDEGAMESPRIVATE_BUILD_DEPRECATED_SINCE(3, 2)
261  /**
262  * @deprecated Since 3.2, use KGameSequence::nextPlayer() instead
263  */
264  KDEGAMESPRIVATE_DEPRECATED_VERSION(3, 2, "Use KGameSequence::nextPlayer()")
265  virtual KPlayer *nextPlayer(KPlayer *last, bool exclusive = true);
266 #endif
267 
268  // Input events
269  /**
270  * Called by KPlayer to send a player input to the
271  * KMessageServer.
272  */
273  virtual bool sendPlayerInput(QDataStream &msg, KPlayer *player, quint32 sender = 0);
274 
275  /**
276  * Called when a player input arrives from KMessageServer.
277  *
278  * Calls prepareNext (using QTimer::singleShot) if gameOver()
279  * returns 0. This function should normally not be used outside KGame.
280  * It could be made non-virtual,protected in a later version. At the
281  * moment it is a virtual function to give you more control over KGame.
282  *
283  * For documentation see playerInput.
284  */
285  virtual bool systemPlayerInput(QDataStream &msg, KPlayer *player, quint32 sender = 0);
286 
287  /**
288  * This virtual function is called if the KGame needs to create a new player.
289  * This happens only over a network and with load/save. Doing nothing
290  * will create a default KPlayer. If you want to have your own player
291  * you have to create one with the given rtti here.
292  * Note: If your game uses a player class derived from KPlayer you MUST
293  * override this function and create your player here. Otherwise the
294  * game will crash.
295  * Example:
296  * \code
297  * KPlayer *MyGame::createPlayer(int rtti,int io,bool isvirtual)
298  * {
299  * KPlayer *player=new MyPlayer;
300  * if (!isvirtual) // network player ?
301  * {
302  * // Define something like this to add the IO modules
303  * createIO(player,(KGameIO::IOMode)io);
304  * }
305  * return player;
306  * }
307  * \endcode
308  *
309  * @param rtti is the type of the player (0 means default KPlayer)
310  * @param io is the 'or'ed rtti of the KGameIO's
311  * @param isvirtual true if player is virtual
312  */
313  virtual KPlayer *createPlayer(int rtti, int io, bool isvirtual);
314 
315  // load/save
316  /**
317  * Load a saved game, from file OR network. This function has
318  * to be overwritten or you need to connect to the load signal
319  * if you have game data other than KGameProperty.
320  * For file load you should reset() the game before any load attempt
321  * to make sure you load into an clear state.
322  *
323  * @param stream a data stream where you can stream the game from
324  * @param reset - shall the game be reset before loading
325  *
326  * @return true?
327  */
328  virtual bool load(QDataStream &stream, bool reset = true);
329 
330  /**
331  * Same as above function but with different parameters
332  *
333  * @param filename - the filename of the file to be opened
334  * @param reset - shall the game be reset before loading
335  *
336  * @return true?
337  */
338  virtual bool load(const QString &filename, bool reset = true);
339 
340  /**
341  * Save a game to a file OR to network. Otherwise the same as
342  * the load function
343  *
344  * @param stream a data stream to load the game from
345  * @param saveplayers If true then all players wil be saved too
346  *
347  * @return true?
348  */
349  virtual bool save(QDataStream &stream, bool saveplayers = true);
350 
351  /**
352  * Same as above function but with different parameters
353  *
354  * @param filename the filename of the file to be saved
355  * @param saveplayers If true then all players wil be saved too
356  *
357  * @return true?
358  */
359  virtual bool save(const QString &filename, bool saveplayers = true);
360 
361  /**
362  * Resets the game, i.e. puts it into a state where everything
363  * can be started from, e.g. a load game
364  * Right now it does only need to delete all players
365  *
366  * @return true on success
367  */
368  virtual bool reset();
369 
370  // Game sequence
371  /**
372  * returns the game status, ie running,pause,ended,...
373  *
374  * @return game status
375  */
376  int gameStatus() const;
377 
378  /**
379  * sets the game status
380  *
381  * @param status the new status
382  */
383  void setGameStatus(int status);
384 
385  /**
386  * docu: see KPlayer
387  */
388  bool addProperty(KGamePropertyBase *data);
389 
390  /**
391  * This is called by KPlayer::sendProperty only! Internal function!
392  */
393  bool sendPlayerProperty(int msgid, QDataStream &s, quint32 playerId);
394 
395  /**
396  * This function allows to find the pointer to a player
397  * property when you know its id
398  */
399  KGamePropertyBase *findProperty(int id) const;
400 
401  /**
402  * Changes the consistency policy of a property. The
403  * GamePolicy is one of PolicyClean (default), PolicyDirty or PolicyLocal.
404  *
405  * It is up to you to decide how you want to work.
406  */
407  void setPolicy(GamePolicy p, bool recursive = true);
408 
409  /**
410  * @return The default policy of the property
411  */
412  GamePolicy policy() const;
413 
414  /**
415  * See KGameNetwork::sendMessage
416  *
417  * Send a network message msg with a given message ID msgid to all players of
418  * a given group (see KPlayer::group)
419  * @param msg the message which will be send. See messages.txt for contents
420  * @param msgid an id for this message
421  * @param sender the id of the sender
422  * @param group the group of the receivers
423  * @return true if worked
424  */
425  bool sendGroupMessage(const QByteArray &msg, int msgid, quint32 sender, const QString &group);
426  bool sendGroupMessage(const QDataStream &msg, int msgid, quint32 sender, const QString &group);
427  bool sendGroupMessage(int msg, int msgid, quint32 sender, const QString &group);
428  bool sendGroupMessage(const QString &msg, int msgid, quint32 sender, const QString &group);
429 
430  /**
431  * This will either forward an incoming message to a specified player
432  * (see KPlayer::networkTransmission) or
433  * handle the message directly (e.g. if msgif==IdRemovePlayer it will remove
434  * the (in the stream) specified player). If both is not possible (i.e. the
435  * message is user specified data) the signal signalNetworkData is
436  * emitted.
437  *
438  * This emits signalMessageUpdate <em>before</em> doing anything with
439  * the message. You can use this signal when you want to be notified about
440  * an update/change.
441  * @param msgid Specifies the kind of the message. See messages.txt for
442  * further information
443  * @param stream The message that is being sent
444  * @param receiver The is of the player this message is for. 0 For broadcast.
445  * @param sender
446  * @param clientID the client from which we received the transmission - hardly used
447  */
448  void networkTransmission(QDataStream &stream, int msgid, quint32 receiver, quint32 sender, quint32 clientID) override;
449 
450  /**
451  * Returns a pointer to the KGame property handler
452  */
453  KGamePropertyHandler *dataHandler() const;
454 
455 protected Q_SLOTS:
456  /**
457  * Called by KGamePropertyHandler only! Internal function!
458  */
459  void sendProperty(int msgid, QDataStream &stream, bool *sent);
460 
461  /**
462  * Called by KGamePropertyHandler only! Internal function!
463  */
464  void emitSignal(KGamePropertyBase *me);
465 
466 #if KDEGAMESPRIVATE_BUILD_DEPRECATED_SINCE(3, 2)
467  /**
468  * @deprecated Since 3.2, use KGameSequence::nextPlayer() & KGameSequence::currentPlayer() instead
469  */
470  KDEGAMESPRIVATE_DEPRECATED_VERSION(3, 2, "Use KGameSequence::nextPlayer() & KGameSequence::currentPlayer()")
471  virtual void prepareNext();
472 #endif
473 
474  /**
475  * Calls negotiateNetworkGame()
476  * See KGameNetwork::signalClientConnected
477  */
478  void slotClientConnected(quint32 clientId);
479 
480  /**
481  * This slot is called whenever the connection to a client is lost (ie the
482  * signal KGameNetwork::signalClientDisconnected is emitted) and will remove
483  * the players from that client.
484  * @param clientId The client the connection has been lost to
485  * @param broken (ignore this - not used)
486  */
487  void slotClientDisconnected(quint32 clientId, bool broken);
488 
489  /**
490  * This slot is called whenever the connection to the server is lost (ie the
491  * signal KGameNetwork::signalConnectionBroken is emitted) and will
492  * switch to local game mode
493  */
494  void slotServerDisconnected();
495 
496 Q_SIGNALS:
497  /**
498  * When a client disconnects from the game usually all players from that
499  * client are removed. But if you use completely the KGame structure you
500  * probably don't want this. You just want to replace the KGameIO of the
501  * (human) player by a computer KGameIO. So this player continues game but
502  * is from this point on controlled by the computer.
503  *
504  * You achieve this by connecting to this signal. It is emitted as soon as a
505  * client disconnects on <em>all</em> other clients. Make sure to add a new
506  * KGameIO only once! you might want to use @ref isAdmin for this. If you
507  * added a new KGameIO set *remove=false otherwise the player is completely
508  * removed.
509  * @param player The player that is about to be removed. Add your new
510  * KGameIO here - but only on <em>one</em> client!
511  * @param remove Set this to FALSE if you don't want this player to be
512  * removed completely.
513  */
514  void signalReplacePlayerIO(KPlayer *player, bool *remove);
515 
516  /**
517  * The game will be loaded from the given stream. Load from here
518  * the data which is NOT a game or player property.
519  * It is not necessary to use this signal for a full property game.
520  *
521  * This signal is emitted <em>before</em> the players are loaded by
522  * KGame. See also signalLoad
523  *
524  * You must load <em>exactly</em> the same data from the stream that you have saved
525  * in signalSavePrePlayers. Otherwise player loading will not work
526  * anymore.
527  *
528  * @param stream the load stream
529  */
530  void signalLoadPrePlayers(QDataStream &stream);
531 
532  /**
533  * The game will be loaded from the given stream. Load from here
534  * the data which is NOT a game or player property.
535  * It is not necessary to use this signal for a full property game.
536  *
537  * @param stream the load stream
538  */
539  void signalLoad(QDataStream &stream);
540 
541  /**
542  * The game will be saved to the given stream. Fill this with data
543  * which is NOT a game or player property.
544  * It is not necessary to use this signal for a full property game.
545  *
546  * This signal is emitted <em>before</em> the players are saved by
547  * KGame. See also signalSave
548  *
549  * If you can choose between signalSavePrePlayers and signalSave then
550  * better use signalSave
551  *
552  * @param stream the save stream
553  */
554  void signalSavePrePlayers(QDataStream &stream);
555 
556  /**
557  * The game will be saved to the given stream. Fill this with data
558  * which is NOT a game or player property.
559  * It is not necessary to use this signal for a full property game.
560  *
561  * @param stream the save stream
562  */
563  void signalSave(QDataStream &stream);
564 
565  /**
566  * Is emitted if a game with a different version cookie is loaded.
567  * Normally this should result in an error. But maybe you do support
568  * loading of older game versions. Here would be a good place to do a
569  * conversion.
570  *
571  * @param stream - the load stream
572  * @param network - true if this is a network connect. False for load game
573  * @param cookie - the saved cookie. It differs from KGame::cookie()
574  * @param result - set this to true if you managed to load the game
575  */
576  void signalLoadError(QDataStream &stream, bool network, int cookie, bool &result);
577 
578  /**
579  * We got an user defined update message. This is usually done
580  * by a sendData in a inherited KGame Object which defines its
581  * own methods and has to synchronize them over the network.
582  * Reaction to this is usually a call to a KGame function.
583  */
584  void signalNetworkData(int msgid, const QByteArray &buffer, quint32 receiver, quint32 sender);
585 
586  /**
587  * We got an network message. this can be used to notify us that something
588  * changed. What changed can be seen in the message id. Whether this is
589  * the best possible method to do this is unclear...
590  */
591  void signalMessageUpdate(int msgid, quint32 receiver, quint32 sender);
592 
593  /**
594  * a player left the game because of a broken connection or so!
595  *
596  * Note that when this signal is emitted the player is not part of @ref
597  * playerList anymore but the pointer is still valid. You should do some
598  * final cleanups here since the player is usually deleted after the signal
599  * is emitted.
600  *
601  * @param player the player who left the game
602  */
603  void signalPlayerLeftGame(KPlayer *player);
604 
605  /**
606  * a player joined the game
607  *
608  * @param player the player who joined the game
609  */
610  void signalPlayerJoinedGame(KPlayer *player);
611 
612  /**
613  * This signal is emitted if a player property changes its value and
614  * the property is set to notify this change
615  */
616  void signalPropertyChanged(KGamePropertyBase *property, KGame *me);
617 
618  /**
619  * Is emitted after a call to gameOver() returns a non zero
620  * return code. This code is forwarded to this signal as 'status'.
621  *
622  * @param status the return code of gameOver()
623  * @param current the player who did the last move
624  * @param me a pointer to the KGame object
625  */
626  void signalGameOver(int status, KPlayer *current, KGame *me);
627 
628  /**
629  * Is emitted after a client is successfully connected to the game.
630  * The client id is the id of the new game client. An easy way to
631  * check whether that's us is
632  * \code
633  * if (clientid==gameid()) .. // we joined
634  * else ... // someone joined the game
635  * \endcode
636  * @param clientid - The id of the new client
637  * @param me - our game pointer
638  */
639  void signalClientJoinedGame(quint32 clientid, KGame *me);
640 
641  /**
642  * This signal is emitted after a network partner left the
643  * game (either by a broken connection or voluntarily).
644  * All changes to the network players have already be done.
645  * If there are not enough players left, the game might have
646  * been paused. To check this you get the old gamestatus
647  * before the disconnection as argument here. The id of the
648  * client who left the game allows to distinguish who left the
649  * game. If it is 0, the server disconnected and you were a client
650  * which has been switched back to local play.
651  * You can use this signal to, e.g. set some menus back to local
652  * player when they were network before.
653  *
654  * @param clientID - 0:server left, otherwise the client who left
655  * @param oldgamestatus - the gamestatus before the loss
656  * @param me - our game pointer
657  */
658  void signalClientLeftGame(int clientID, int oldgamestatus, KGame *me);
659 
660 protected:
661  /**
662  * A player input occurred. This is the most important function
663  * as the given message will contain the current move made by
664  * the given player.
665  * Note that you HAVE to overwrite this function. Otherwise your
666  * game makes no sense at all.
667  * Generally you have to return TRUE in this function. Only then
668  * the game sequence is proceeded by calling @ref playerInputFinished
669  * which in turn will check for game over or the next player
670  * However, if you have a delayed move, because you e.g. move a
671  * card or a piece you want to return FALSE to pause the game sequence
672  * and then manually call @ref playerInputFinished to resume it.
673  * Example:
674  * \code
675  * bool MyClass::playerInput(QDataStream &msg,KPlayer *player)
676  * {
677  * qint32 move;
678  * msg >> move;
679  * qDebug() << " Player" << player->id() << "moved to" << move;
680  * return true;
681  * }
682  * \endcode
683  *
684  * @param msg the move message
685  * @param player the player who did the move
686  * @return true - input ready, false: input manual
687  */
688  virtual bool playerInput(QDataStream &msg, KPlayer *player) = 0;
689 
690  /**
691  * Called after the player input is processed by the game. Here the
692  * checks for game over and nextPlayer (in the case of turn base games)
693  * are processed.
694  * Call this manually if you have a delayed move, i.e. your playerInput
695  * function returns FALSE. If it returns true you need not do anything
696  * here.
697  *
698  * @return the current player
699  *
700  */
701  KPlayer *playerInputFinished(KPlayer *player);
702 
703  /**
704  * This virtual function can be overwritten for your own player management.
705  * It is called when a new game connects to an existing network game or
706  * to the network master. In case you do not want all players of both games
707  * to be present in the new network game, you can deactivate players here.
708  * This is of particular importance if you have a game with fixed number of
709  * player like e.g. chess. A network connect needs to disable one player of
710  * each game to make sense.
711  *
712  * Not overwriting this function will activate a default behaviour which
713  * will deactivate players until the @ref maxPlayers() number is reached
714  * according to the KPlayer::networkPriority() value. Players with a low
715  * value will be kicked out first. With equal priority players of the new
716  * client will leave first. This means, not setting this value and not
717  * overwriting this function will never allow a chess game to add client
718  * players!!!
719  * On the other hand setting one player of each game to a networkPriorty of
720  * say 10, already does most of the work for you.
721  *
722  * The parameters of this function are the playerlist of the network game,
723  * which is @ref playerList(). The second argument is the player list of
724  * the new client who wants to join and the third argument serves as return
725  * parameter. All <em>player ID's</em> which are written into this list
726  * will be <em>removed</em> from the created game. You do this by an
727  * \code
728  * inactivate.append(player->id());
729  * \endcode
730  *
731  * @param oldplayer - the list of the network players
732  * @param newplayer - the list of the client players
733  * @param inactivate - the value list of ids to be deactivated
734  *
735  */
736  virtual void newPlayersJoin(KGamePlayerList *oldplayer, KGamePlayerList *newplayer, QList<int> &inactivate)
737  {
738  Q_UNUSED(oldplayer);
739  Q_UNUSED(newplayer);
740  Q_UNUSED(inactivate);
741  }
742 
743  /**
744  * Save the player list to a stream. Used for network game and load/save.
745  * Can be overwritten if you know what you are doing
746  *
747  * @param stream is the stream to save the player ot
748  * @param list the optional list is the player list to be saved, default is playerList()
749  *
750  */
751  void savePlayers(QDataStream &stream, KGamePlayerList *list = nullptr);
752 
753  /**
754  * Prepare a player for being added. Put all data about a player into the
755  * stream so that it can be sent to the KGameCommunicationServer using
756  * addPlayer (e.g.)
757  *
758  * This function ensures that the code for adding a player is the same in
759  * addPlayer as well as in negotiateNetworkGame
760  * @param stream is the stream to add the player
761  * @param player The player to add
762  */
763  void savePlayer(QDataStream &stream, KPlayer *player);
764 
765  /**
766  * Load the player list from a stream. Used for network game and load/save.
767  * Can be overwritten if you know what you are doing
768  *
769  * @param stream is the stream to save the player to
770  * @param isvirtual will set the virtual flag true/false
771  *
772  */
773  KPlayer *loadPlayer(QDataStream &stream, bool isvirtual = false);
774 
775  /**
776  * inactivates player. Use @ref inactivatePlayer instead!
777  */
778  bool systemInactivatePlayer(KPlayer *player);
779 
780  /**
781  * activates player. Use @ref activatePlayer instead!
782  */
783  bool systemActivatePlayer(KPlayer *player);
784 
785  /**
786  * Adds a player to the game
787  *
788  * Use @ref addPlayer to send @ref KGameMessage::IdAddPlayer. As soon as
789  * this Id is received this function is called, where the player (see @ref
790  * KPlayer::rtti) is added as well as its properties (see @ref KPlayer::save
791  * and @ref KPlayer::load)
792  *
793  * This method calls the overloaded @ref systemAddPlayer with the created
794  * player as argument. That method will really add the player.
795  * If you need to do some changes to your newly added player just connect to
796  * @ref signalPlayerJoinedGame
797  */
798 
799  /**
800  * Finally adds a player to the game and therefore to the list.
801  */
802  bool systemAddPlayer(KPlayer *newplayer);
803 
804  /**
805  * Removes a player from the game
806  *
807  * Use removePlayer to send KGameMessage::IdRemovePlayer. As soon
808  * as this Id is received systemRemovePlayer is called and the player is
809  * removed directly.
810  */
811  void systemRemovePlayer(KPlayer *player, bool deleteit);
812 
813  /**
814  * This member function will transmit e.g. all players to that client, as well as
815  * all properties of these players (at least if they have been added by
816  * @ref KPlayer::addProperty) so that the client will finally have the same
817  * status as the master. You want to overwrite this function if you expand
818  * KGame by any properties which have to be known by all clients.
819  *
820  * Only the ADMIN is allowed to call this.
821  * @param clientID The ID of the message client which has connected
822  */
823  virtual void negotiateNetworkGame(quint32 clientID);
824 
825 #if KDEGAMESPRIVATE_ENABLE_DEPRECATED_SINCE(7, 3)
826  /**
827  * synchronize the random numbers with all network clients
828  * not used by KGame - if it should be kept then as public method
829  * @deprecated Since 7.3, no known users.
830  */
831  KDEGAMESPRIVATE_DEPRECATED_VERSION(7, 3, "No known users")
832  void syncRandom();
833 #endif
834 
835  void deletePlayers();
836  void deleteInactivePlayers();
837 
838 #if KDEGAMESPRIVATE_BUILD_DEPRECATED_SINCE(3, 2)
839  /**
840  * @param player the player who made the last move
841  * @return anything else but 0 is considered as game over
842  *
843  * @deprecated Since 3.2, use KGameSequence instead.
844  */
845  KDEGAMESPRIVATE_DEPRECATED_VERSION(3, 2, "Use KGameSequence")
846  virtual int checkGameOver(KPlayer *player);
847 #endif
848 
849  /**
850  * Load a saved game, from file OR network. Internal.
851  * Warning: loadgame must not rely that all players all already
852  * activated. Actually the network will activate a player AFTER
853  * the loadgame only. This is not true anymore. But be careful
854  * anyway.
855  *
856  * @param stream a data stream where you can stream the game from
857  * @param network is it a network call -> make players virtual
858  * @param reset shall the game be reset before loading
859  *
860  * @return true?
861  */
862  virtual bool loadgame(QDataStream &stream, bool network, bool reset);
863 
864  /**
865  * Save a game, to file OR network. Internal.
866  *
867  * @param stream a data stream where you can stream the game from
868  * @param network is it a call from the network or from a file (unused but informative)
869  * @param saveplayers shall the players be saved too (should be TRUE)
870  *
871  * @return true?
872  */
873  virtual bool savegame(QDataStream &stream, bool network, bool saveplayers);
874 
875 private:
876  // AB: this is to hide the "receiver" parameter from the user. It shouldn't be
877  // used if possible (except for init).
878  /**
879  * This is an overloaded function. Id differs from the public one only in
880  * its parameters:
881  *
882  * @param receiver The Client that will receive the message. You will hardly
883  * ever need this. It it internally used to initialize a newly connected
884  * client.
885  */
886  // void addPlayer(KPlayer* newplayer, quint32 receiver);
887 
888  /**
889  * Just the same as the public one except receiver:
890  * @param receiver 0 for broadcast, otherwise the receiver. Should only be
891  * used in special circumstances and not outside KGame.
892  */
893  bool removePlayer(KPlayer *player, quint32 receiver);
894 
895  /**
896  * Helping function - game negotiation
897  */
898  void setupGame(quint32 sender);
899 
900  /**
901  * Helping function - game negotiation
902  */
903  void setupGameContinue(QDataStream &msg, quint32 sender);
904 
905  /**
906  * Removes a player from all lists, removes the @ref KGame pointer from the
907  * @ref KPlayer and deletes the player. Used by (e.g.) @ref
908  * systemRemovePlayer
909  * @return True if the player has been removed, false if the current is not
910  * found
911  */
912  bool systemRemove(KPlayer *player, bool deleteit);
913 
914 private:
915  KGamePrivate *const d;
916 };
917 
918 #endif
bool removePlayer(KPlayer *player)
Sends a message over the network, msgid=IdRemovePlayer.
Definition: kgame.h:205
GameStatus
Game status - Use this to Control the game flow.
Definition: kgame.h:107
Q_SLOTSQ_SLOTS
virtual void newPlayersJoin(KGamePlayerList *oldplayer, KGamePlayerList *newplayer, QList< int > &inactivate)
This virtual function can be overwritten for your own player management.
Definition: kgame.h:736
GamePolicy
The policy of the property.
Definition: kgame.h:83
The main KDE game object.
Definition: kgame.h:55
Base class for a game player.
Definition: kplayer.h:59
A collection class for KGameProperty objects.
Q_SCRIPTABLE CaptureState status()
Base class of KGameProperty.
Definition: kgameproperty.h:36
Q_SIGNALSQ_SIGNALS
virtual void Debug()
Gives debug output of the game status.
The main KDE game object.
Definition: kgamenetwork.h:38
virtual void networkTransmission(QDataStream &, int, quint32, quint32, quint32 clientID)=0
Called by ReceiveNetworkTransmission().
Round/move management class.
Definition: kgamesequence.h:35
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Tue Feb 7 2023 03:55:25 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.