diff options
Diffstat (limited to 'libksirtet/lib/mp_interface.h')
-rw-r--r-- | libksirtet/lib/mp_interface.h | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/libksirtet/lib/mp_interface.h b/libksirtet/lib/mp_interface.h new file mode 100644 index 00000000..ad925cba --- /dev/null +++ b/libksirtet/lib/mp_interface.h @@ -0,0 +1,246 @@ +#ifndef MP_INTERFACE_H +#define MP_INTERFACE_H + +#include <qwidget.h> +#include <qvaluelist.h> +#include <qptrlist.h> + +#include "mp_board.h" +#include "mp_option.h" + +class QHBoxLayout; +class Local; +class ConnectionData; +class RemoteHostData; +class KeyData; +class KeyCollection; +class KKeyDialog; +class KAction; + +struct ActionData { + const char *label, *name; + const char *slot, *slotRelease; // if slotRelease!=0 + // : use keyPress/ReleaseEvent mecanism +}; + +/** + * This structure contains information about the game + * configuration. + */ +typedef struct { + /** The game version id used for identification (e.g. "4"). + * You should change this id when the game is made incompatible + * with previous version. (changes in data for example). + */ + const char *gameId; + + /** Maximum number of local players. */ + uint maxNbLocalPlayers; + + /** Interval (in msec.) between data exchange. */ + uint interval; + + /** If there are built-in artificial intelligences that can play. */ + bool AIAllowed; + + /** Slot for player/AI additional configuration. These must be SLOTs which + * take an "int" as parameter. It must open a setting + * dialog for the corresponding local player/computer and save the + * new settings in the config file. It should probably create a group + * with the given number in its name. + * If such a pointer is set to 0 : it means there is no perticular + * setting. + */ + const char *humanSettingSlot, *AISettingSlot; +} MPGameInfo; + +/** + * The MPInterface class is useful for multiplayers game + * management. Each game is represented by a class you have inherited + * from the @ref MPBoard class. + * + * Multiplayers games can take place with several (humans or eventually + * AIs) players on the same computer (they use the same keyboard and have + * each a @ref MPBoard widget on the screen) or/and network players. + * + * This class is intended to do all the hard work of sending/receiving data + * between the players and to send the keyboard events to the right + * @ref MPBoard. So multiplayers game should be completely transparent + * from your point of view. + * + * Note : The data exchange is done in background with a timer calling at given + * intervals the read/write methods. Obviously this kind of things can be done + * easily with threads but I have no experience with thread programming + * and not all people have thread libraries and a thread-safe system. + */ +class MPInterface : public QWidget +{ + Q_OBJECT + + public: + /** Constructor which takes a MPGameInfo struct as parameter. + */ + MPInterface(const MPGameInfo &gameInfo, + uint nbActions, const ActionData *data, + QWidget *parent = 0, const char *name = 0); + virtual ~MPInterface(); + + public slots: + /** Create a single player game for a human being. + * Call @ref stop if a game is already created. */ + void singleHuman() { specialLocalGame(1, 0); } + /** Create a local game opposing two human beings. + * Call @ref stop if a game is already created. */ + void humanVsHuman() { specialLocalGame(2, 0); } + /** Create a local game opposing a human with an AI. + * Call @ref stop if a game is already created. */ + void humanVsComputer() { specialLocalGame(1, 1); } + + /** Open a dialog to create a multiplayer game. + * Call @ref stop if a game is already created. */ + void dialog(); + + public: + virtual void addKeys(KKeyDialog &); + void saveKeys(); + + /** Called when a new game is created. At this point + * the number of players is known. */ + virtual void init() {} + + /** Called just before a new game is created (called by + * singleHuman, humanVsHuman, humanVsComputer and dialog). */ + virtual void stop() {} + + /** Called when the start button of the netmeeting is pressed. */ + virtual void start() {} + + /** + * Set keys configuration for the given number of human players. + * The size of the array is the number of defined actions. + */ + void setDefaultKeycodes(uint nbHumans, uint human, const int *keycodes); + + /** + * @return the total number of players. + * (If called from client : return the number of local boards). + */ + uint nbPlayers() const; + + /** + * @return true if the interface is the server. + */ + bool server() const { return _server; } + + /** @return the player name. + Do not call from client ! + */ + QString playerName(uint i) const; + + /** + * Create a new @ref MPBoard. + * + * @param i is the game index that goes from 0 to the number of + * local players : it can be used to retrieve configuration settings. + */ + virtual MPBoard *newBoard(uint i) = 0; + + /** + * This method must read data from each client with method + * @ref readingStream, do the needed treatement + * (for instance which players has lost, which data to be resent, ...) and + * then write the useful data to each client with method + * @ref writingStream. + * + * NB: this method is also called for single player games but + * you probably only want to check for game over condition (it depends + * on game implementation that you really return data to the board). + */ + virtual void treatData() = 0; + + /** @return the reading stream for board #i. + * Do not call from client ! + */ + QDataStream &readingStream(uint i) const; + + /** @return the writing stream for board #i. + */ + QDataStream &writingStream(uint i) const; + + /** + * Read data sent from server to clients "MultiplayersInterface" + * (this data is not addressed to boards). + * These are meta data that are not directly used in game. + * It can be used to display "game over" infos for all + * local games. + * NB: the use of this method is optional. + */ + virtual void dataFromServer(QDataStream &) {} + + /** Used by the server to write meta data to clients. + * NB: the use of this method is optional. + * Do not call from client ! + */ + QDataStream &dataToClientsStream() const; + + /** Write immediately data to clients and local boards. + * It is unlike the normal exchange which is driven + * by the timer of the server. Be aware of possible + * interactions. + */ + void immediateWrite(); + + /** + * This method should be overload if an option widget is used in the + * the "netmeeting" dialog). By default a + * null pointer is returned and so no option widget is shown. + * The option widget must be inherited from the @ref MPOptionWidget class. + */ + virtual MPOptionWidget *newOptionWidget() const { return 0; } + + /** Called when a network error occurred or when a host gets disconnected. + * The default implementation displays a message and calls singleHumans() + * ie it stops the current game. By overloading this method, it is + * possible to continue the game at this point with the remaining players. + */ + virtual void hostDisconnected(uint i, const QString &msg); + + protected: + void paintEvent(QPaintEvent *); + void keyPressEvent(QKeyEvent *); + void keyReleaseEvent(QKeyEvent *); + + private slots: + void enableKeys(bool enable); + void singleHumanSlot(); + + public: + class Data { + public: + Data() {} + MPBoard *ptr; + int humanIndex; + QString name; + }; + + private: + Local *internal; + const MPGameInfo gameInfo; + QValueList<Data> boards; + uint nbLocalHumans; + QHBoxLayout *hbl; + bool _server, disconnected; + + KeyData *_keyData; + QMemArray<KeyCollection *> _keyCol; + + void createServerGame(const QPtrList<RemoteHostData> &); + void createClientGame(const RemoteHostData &); + void createLocalGame(const ConnectionData &); + void specialLocalGame(uint nbHumans, uint nbComputers); + + void clear(); + void initKeys(uint nbHumans); +}; + +#endif // MP_INTERFACE_H |