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

KDE's Doxygen guidelines are available online.