From kde-games-devel Mon Feb 26 08:37:20 2007 From: Josef Spillner Date: Mon, 26 Feb 2007 08:37:20 +0000 To: kde-games-devel Subject: [Kde-games-devel] Tutorials for GGZ-in-kdegames Message-Id: <200702260937.21776.spillner () kde ! org> X-MARC-Message: https://marc.info/?l=kde-games-devel&m=117247904901225 MIME-Version: 1 Content-Type: multipart/mixed; boundary="--Boundary-00=_Bxp4FrQGR0hfH6T" --Boundary-00=_Bxp4FrQGR0hfH6T Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline Hi, I felt like writing some tutorials on the matter now that the sources have been imported into SVN. The next goal for me is to implement the gameplay in KReversi. This will in turn need some decisions about how to let the UI reflect the multiplayer status. For example, will we simply grey out the multiplayer dialogs when the game is run in singleplayer mode, or will we hide them completely? Likewise, certain actions like "new game" will behave differently in a multiplayer setting. Josef --Boundary-00=_Bxp4FrQGR0hfH6T Content-Type: text/plain; charset="us-ascii"; name="tutorial0.txt" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="tutorial0.txt" GGZ Gaming Zone for KDE 4 - Tutorial 0 -------------------------------------- There will be 3 tutorials for GGZ in KDE, one for each library (kggzmod, kggznet, kggzgames). We will start with kggzmod since this is probably the most interesting one. However, before starting, this tutorial 0 should give some information about the build system and general GGZ game module information. At some point the tutorials, currently sent by e-mail, will be converted to HTML and put onto developernew.kde.org or games.kde.org, depending on where game development documentation should go to. Note that in addition to the tutorials, the GGZ libraries all ship with full API docs now, which can be consulted online at: http://www.ggzgamingzone.org/docs/api/kggzmod/ http://www.ggzgamingzone.org/docs/api/kggznet/ http://www.ggzgamingzone.org/docs/api/kggzgames/ Simply running 'doxygen' for each library will also work of course. The API docs will end up somewhere at api.kde.org in the standard KDE apidox format eventually. Build system ------------ All build issues are handled by GGZ.cmake, which at the time of writing lives under kdegames/cmake/modules. For some reason, calling include (../cmake/modules/GGZ.cmake) or similar seems to be necessary for each CMakeLists.txt which wants to make use of it. This will be improved in the future. GGZ.cmake sets up some variables and helps with GGZ module registration. Modules are game clients which can run on GGZ and which are registered in a central system-wide file so every GGZ core client can find them. All that is needed for KDE games making use of GGZ is to link against the kggz* libraries in kdegames and to install a module.dsc file containing the registration data. In terms of CMake, this looks like this: register_ggz_module(module.dsc) target_link_libraries(mygame ... ${KGGZGAMES_LIBS}) The include directories must include libkdegames, but usually this is already the case. If not (e.g. for games not in KDE SVN), the following helps: include_directories(${KGGZGAMES_INCLUDE_DIR}) GGZ modules ----------- At the moment, this tutorial assumes that game clients are written for game servers which already exist, or that the developer knows how to write GGZ game servers. Either way, the client and server are identified on the basis of a protocol engine and an associated version number, both of which must match exactly. A module.dsc file contains this information and some more: [ModuleInfo] Name = ... Author = ... CommandLine = Frontend = kde Homepage = http://games.kde.org/... ProtocolEngine = Reversi ProtocolVersion = 4 Version = ... In the example above, Reversi:4 is determined by the server, and the client confirms this combination by stating that it will understand the Reversi protocol as of version 4. Should the protocol change on the server, the user will be notified accordingly. GGZ game servers ---------------- Help out getting network code into as many games as possible! Several KDE games look like they could match GGZ game servers, so development will be easy. Have a look at http://www.ggzgamingzone.org/gameservers/ for a full list of GGZ and external game servers. If you write a game server, make sure to have it added there (assuming it runs on GGZ). --Boundary-00=_Bxp4FrQGR0hfH6T Content-Type: text/plain; charset="us-ascii"; name="tutorial3.txt" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="tutorial3.txt" GGZ Gaming Zone for KDE 4 - Tutorial 3 -------------------------------------- This is the third tutorial for GGZ in KDE, this dealing with kggzgames. The tutorial is a really dull one, since kggzgames offers so little currently that one line of code seems sufficient :) The kggzgames library is supposed to contain the graphical widgets and dialogs needed for good multiplayer support in game clients. Currently, it only contains the KGGZSeatsDialog class. KGGZSeatsDialog --------------- This dialog is a very autonomous one. Given an active GGZ connection, calling its constructor is already enough to let it perform all work on its own. It will list all the participating players/bots/spectators for a game, but also unused seats (empty/reserved/abandoned). If the privileges of the player are sufficient, then the seat configuration can be changed, e.g. by kicking some players or bots or by filling up empty seats with new bots. Highscores/ratings/rankings are also shown in this dialog. In the future, several more classes could be added here. For example, libkdegames already provides a chat widget and a chat dialog. Using kggzgames, it could be possible to use the chat dialog on an existing GGZ connection, preconfiguring it to know all present players and automatically sending to and receiving from the game server (if it's game chat) or the GGZ server (if it's table or room chat). Likewise, a global highscore dialog and a connection dialog could go in here. --Boundary-00=_Bxp4FrQGR0hfH6T Content-Type: text/plain; charset="us-ascii"; name="tutorial1.txt" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="tutorial1.txt" GGZ Gaming Zone for KDE 4 - Tutorial 1 -------------------------------------- This is the first of the three tutorials about the kggz* libraries in libkdegames, and it covers the kggzmod library. What kggzmod is used for is to connect your game to the gaming zone, to let it receive information about the players and spectators and scores, and to let it submit requests to change the seat configuration or similarly. It doesn't do anything else, in particular it doesn't let your game client communicate with your game server. There are other libraries for this task, some of them being part of kggznet. The kggzmod library also doesn't offer graphical interfaces to display the information or let the user modify anything - this would be the task of the kggzgames library. Therefore, kggzmod is a non-graphical base component for GGZ integration of game clients. KGGZMod::Module --------------- Strictly spoken, this is the only class in kggzmod which must be known by the game author. There are other classes, but some are used by kggzgames on its own and some are only necessary for advanced features, so implementing everything which KGGZMod::Module has to offer is already all of the work for good GGZ integration. A module object should only be created if the game runs in GGZ mode. The static method ::isGGZ() can be used to check for this condition. A module will offer two signals, one for data from the game server and one for errors which might happen anywhere. Therefore, a good initialisation code looks like: void initMultiplayer() { if(KGGZMod::Module::isGGZ()) { KGGZMod::Module *mod = new KGGZMod::Module("mygame"); connect(mod, SIGNAL(signalError()), SLOT(slotError())); connect(mod, SIGNAL(signalNetwork(int)), SLOT(slotNetwork(int))); } } Advanced usage is possible by also connecting the signalEvent() signal, which will deliver a KGGZMod::Event object which might be casted to more specialised KGGZMod::FooEvent objects. The module object also allows to print out information about the player via ::self() or about other players via ::players(), the first one being a KGGZMod::Player* object and the second one being a list of them which contains oneself. In order to finish GGZ mode, simply delete the KGGZMod::Module::instance() object. One word about the parameter to the constructor: Right now, this is a meaningless string somehow related to the name of the game. In the future, we want this to refer to the *.dsc file (see tutorial 0) so we can make the game self-aware of its own version number and features. The API for this hasn't been decided on yet. --Boundary-00=_Bxp4FrQGR0hfH6T Content-Type: text/plain; charset="us-ascii"; name="tutorial2.txt" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="tutorial2.txt" GGZ Gaming Zone for KDE 4 - Tutorial 2 -------------------------------------- This is the second tutorial for GGZ in KDE, now dealing with kggznet, after kggzmod was handled already. Actually kggzmod uses kggznet internally but this is not relevant for us to know. We will only look at how kggznet can be used in games. The task of kggznet is an easy one: networking. It provides some C++ classes for handling the communication between a game server and a game client. It is important to know that the kggznet libraries do not have to be used with every game. However, they should be used whenever compatibility with existing game servers (or clients) is needed which already use the same protocols. Those protocols are 'easysock' and 'dio' from the GGZ Gaming Zone project and are in use with several games in GGZ, GNOME games and various other game projects. Both are binary protocols. This makes them efficient but terribly hard to debug. Some debugging facilities are included in kggznet to help out. In the future, we want to have abstract game protocol descriptions and generate the actual networking code automatically from it. This is possible to some extent already in an experimental fashion, but not ready for production yet, using the GGZComm protocol generator. Therefore, we recommend to use kggznet right now and switch to generated code later. KGGZRaw ------- This is one of the two classes in kggznet. It can be used similary to a QDataStream. However, QDataStream works best with buffered sockets, whereas there are certain conditions when unbuffered sockets are wanted - for example, if after reading a certain value the socket handling should be switched to another handler, or if partial value reads should be forbidden. KGGZRaw doesn't offer all Qt type serialisations mostly because the Qt types serialise themselves to QDataStream instead of letting QDataStream serialise them, and therefore have QDataStream hardcoded. If you need Qt types in KGGZRaw, they could be added, but keep in mind that other implementations of the same class will likely not be able to read them! Therefore, adding is only possible when the type can easily be deconstructed into two parts, for example writing a QSize in a KDE game and reading two integers (x, y) in a game server written in plain C. Usage example: Add a KGGZRaw* pointer to your class and initialise it to NULL. When the KGGZMod::Module object reports the file descriptor to the game server via signalNetwork(), check if the pointer is still NULL, and if so, create the KGGZRaw object and assign the file descriptor. Just in case, the error signal should also be slotted in somewhere. // matches KGGZMod::Module::signalNetwork(fd) void slotNetwork(int fd) { if(!m_raw) { m_raw = new KGGZRaw(); m_raw->setNetwork(fd); connect(m_raw, SIGNAL(signalError()), SLOT(slotError())); } // now read from m_raw int opcode; m_raw >> opcode; // and write back the answer int answer = 42; m_raw << answer; } // called by kggzraw in case of read/write errors void slotError() { delete m_raw; m_raw = NULL; // don't forget to inform the user! // in GGZ game clients, we likely want to terminate everything now delete KGGZMod::Module::instance(); } KGGZPacket ---------- KGGZRaw has serious drawbacks: due to it being unbuffered, it might block the GUI if an integer (4 bytes) is read but only 3 bytes are in the buffer at this time, which might actually happen in practice on TCP/IP connections! Blocking is not bad if it happens in a dedicated thread only, but usually game clients are single-threaded and we want non-blocking network operations. Enter KGGZPacket: Each 'packet' is a collection of integers, characters and strings which somehow fit together as a logical unit. The format of the packets is left up to the game authors. Packets are used in Freeciv, for example, but also in other games. The interface is similar to KGGZRaw, but is not the same one. The reason behind the difference is that KGGZPacket might need to read several times before a packet is finished. Since buffering is not an issue, the developer also gets access to a standard QDataStream, one for reading and one for writing. The example from above would read as follows, in case we have a KGGZPacket *m_packet member in our class and want to read whenever KGGZMod::Module *m_mod reports data from the game server: void initNetwork() { m_packet = new KGGZPacket(); connect(m_mod, SIGNAL(signalNetwork(int)), m_packet, SLOT(slotNetwork(int))); connect(m_packet, SIGNAL(signalPacket()), SLOT(slotPacket())); } void slotPacket() { // now read from m_packet - which is guaranteed to be successful int opcode; *m_packet->inputstream() >> opcode; // and write back our answer packet int answer = 42; *m_packet->outputstream() << answer; *m_packet->flush(); // don't forget this! } So basically, KGGZPacket is used as a redirector for the network traffic which takes the raw traffic and cuts it into nicely usable packets with a known size but unknown content. A higher-level protocol code could also deliver known content, that is, one special struct or object on the stack for each incoming message. However, this is specific for each game, and can be implemented by game developers as needed. GGZComm-generated code will support such higher-level packets. --Boundary-00=_Bxp4FrQGR0hfH6T Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ kde-games-devel mailing list kde-games-devel@kde.org https://mail.kde.org/mailman/listinfo/kde-games-devel --Boundary-00=_Bxp4FrQGR0hfH6T--