summaryrefslogtreecommitdiffstats
path: root/libkdegames/kgame/DESIGN
diff options
context:
space:
mode:
Diffstat (limited to 'libkdegames/kgame/DESIGN')
-rw-r--r--libkdegames/kgame/DESIGN407
1 files changed, 407 insertions, 0 deletions
diff --git a/libkdegames/kgame/DESIGN b/libkdegames/kgame/DESIGN
new file mode 100644
index 00000000..b1c48146
--- /dev/null
+++ b/libkdegames/kgame/DESIGN
@@ -0,0 +1,407 @@
+This document tries to describe the design of KGame - the KDE multiplayer
+library.
+This document has been written by:
+ Andreas Beckermann <b_mann@gmx.de>
+ M. Heni <martin@heni-online.de>
+ Burkhard Lehner <Burkhard.Lehner@gmx.de>
+
+This document is published under the terms of the GNU FDL
+
+!!!
+Note that this is the initial version of this document and has not yet been
+aproved by all core developers (and is far from being complete)
+AB: please remove this comments as soon as all KGame hackers have read the
+document
+!!!
+
+Please refer the API documentation of every KGame class if you want up tp date
+information.
+
+
+0. Contents
+-----------
+
+1. DEFINITIONS
+1.1 Message Server
+1.2 Client or Message Client
+1.3 Master
+1.4 Admin
+1.5 Server
+1.6 Player
+
+2. Game Negotiation (M.Heni 20.05.2001)
+
+AB: 3.x is obsolete!
+3. Game Properties (Andreas Beckermann 28.07.2001) ( not yet completed )
+3.1 Using KGameProperty
+3.2 Custom Classes
+3.3 Concepts
+
+4. KGameIO (Andreas Beckermann 10.08.2001)
+
+5. Debugging (Andreas Beckermann 06.10.2001) TODO!
+5.1 KGameDebugDialog
+5.1.1 Debug KGame
+5.1.3 Debug Messages
+
+---------------------------------------------------------------------
+1. DEFINITIONS
+--------------
+
+First we have to clear some words. The main expressions used in KGame which
+need a definition are
+
+1.1 Message Server
+1.2 Client or Message Client
+1.3 Master
+1.4 Admin
+1.5 Server
+1.6 Player
+
+The most important and confusing ones are Master, Admin and Server. We make
+quite big differerences between those inside KGame.
+
+1.1 Message Server:
+-------------------
+A game has always exactly one object of this class, for local games as well as
+for network games. For network games, this object can be on one of the users
+processes (usually inside KGame), or it can also be on an independant computer,
+that has no idea about what game is played on it.
+
+A KMessageClient object can connect to it. It's main purpose is transmitting
+messages between KMessageClient objects.
+
+The Message Server is the main communication object. It is represented by the
+class KMessageServer. Note that there is also a "Master" and a "Server" which
+both differ heavily from the Message Server!
+
+1.2 Client, Message Client:
+---------------------------
+Each process that wants to take part in the game must have a
+KMessageClient object, that is connected to the Message Server. KGame creates
+this object and connects it to the Messager Server, so that you usually don't
+need to create these of your own. Even in a local game (no network) there
+must be a message server and one message client connected to it. This is usually
+done by the KGame object itself.
+
+Each message client has a unique ID number (a positive integer value, not zero).
+The KMessageClient object, which does the communication with the Message Server
+is called "Message Client" and to simplify the use we call any KGame object (or
+even the game process) that is connected to a game (i.e. even the Master) just
+"Client".
+
+The main purpose of a Client is to connect to a Master (i.e. to a game) and to
+communicate with it. A client has always a KGame object.
+
+1.3 Master:
+-----------
+The process that contains the Message Server is called "Master". In any local
+game this is the game process. The Message Server is started by KGame using
+KGame::setMaster(true) which is automatically done on startup. The Message
+Server is deleted automatically as soon as you connect to another Master.
+So in most cases there is exactly one KGame object / Client which is Master. But
+in one case there can be no KGame object / Client that is Master - if the
+Message Server is started as an own process. This "Message-Server-only" process
+is called "Master" then, although there is no KGame object which is Master. See
+also the definition of Admin!
+
+1.4 Admin:
+----------
+One (and only one) of the Clients is the Admin. He can configure the Message
+Server and the game in general in several ways. He can limit the maximum number
+of connected message clients and can drop the connection to some other clients,
+as well as he can configure game specific ssettings (like max/min players, start
+money, ...). The Admin also initializes newly connected Clients. If the Admin
+himself disconnects, another Client becomes Admin (The Admin can himself elect
+some other Client to become Admin. He himself loses that Admin status then).
+An Admin is *alway* a KGame object. The Admin is usually the same as the Master,
+but if the Master is an own process (i.e. the Message Server has been started
+outside KGame) then Master and Admin differ. An Admin *must* be a KGame object
+while the Master doesn't have to be.
+
+1.5 Server:
+-----------
+The definition of Server differs quite much from the definition of Master.
+A Master just accepts connections and forwards messages. The Server on the other
+side checks these messages, calculates results and sends the results to the
+Clients. That means the Server does all game calculations and doesn't directly
+forward the messages from one Clients to all other Clients.
+KGamer makes it possible to write multiplayer games even without a Server. All
+Clients just send their moves to the Master which forwards them to all Clients.
+Now all Clients calculate the result.
+E.g. in a poker game a player selects two of five cards to be exchanges and
+clicks on "draw" then the client sends the message "Exchange Card-1 and Card-2"
+to the Master. A no-Server solution forwards this to all Clients, and these
+Clients exchange the cards of the player. Note that in a no-Server solution
+(you can also see it as a "every-Client-is-a-Server solution") all Clients must
+have the same random seed and must be of the same version, i.e. the result must
+be the same on all Clients.
+In a Server-Solution on the other hand the Master forwards the Message
+("Exchange Card-1 and Card-2") to the Server only. This Server now calculates
+the result, and sends the new cards back to the Client.
+Both concepts have advantages and disadvantages. It is on you - the game
+developer - to decide which way is better for you.
+E.g. the Server-Solution makes it easier for you to write games. The version
+must not necessarily be the same, you have one central computer which does the
+calcultations. The No-Server-Solution on the other hand decreases network
+traffik as the Clients just send their moves and all Clients can calculate the
+reactions. I'm sure there are a lot of advantages/disadvantages more for both
+concepts.
+
+1.6 Player:
+-----------
+A KPlayer object is always connected to a KGame object and represents a
+player that participates the game. In a network game, every KPlayer object is
+duplicated on every other KGame object connected to the message server with
+virtual KPlayer objects. So at every time in the game, every KGame object has
+the same number of KPlayer objects.
+
+
+2. Game negotiation
+-------------------
+Upon connection of a client the admin and the client try to negotiate
+the game setup. Basically this means the game of the admin is transferred
+(saved) on the client. However, the client's players are added to the game
+as far as possible. If the addition of the client's players would add more
+players than allowed some players are inactivated. Which players are
+inactivated depends on their networkPriority(). This procedure allows
+easy replacement of players in a constant number game (e.g. chess). If
+this feature is of no interest simply keep the priorities equal (all 0)
+and the client will only add only players if the number of players is
+less or equal the maximum player number.
+
+The following is the negotiation procedure as started by the connection
+of a client. It is initiated in the negotiateNetworkGame() virtual function
+of KGame:
+
+admin: client:
+------------ ------------
+IdSetupGame
+ QINT16 Library
+ Version
+ QINT32 Application
+ cookie
+ IdSetupGameContinue;
+ QValueList<int> player id's
+ QValueList<int> network priority's
+
+IdGameLoad
+ all game data
+
+IdGameReactivate
+ QValueList<int> id's
+
+IdSyncRandom
+ int randomseed
+
+
+3. Game Properties
+------------------
+A very hard task in a network game is consistency. You have to achieve that all
+properties of the game and of all players have the same value on all clients
+every time. This is because
+a) the user might be confused if he sees "Player has $0" on client A but
+"Player has $10" on client B and
+b) Often game handling depends on those values, e.g. if the example above
+happens the computer might quit the game for the Player on client A because
+he/she doesn't have enough money. But the game continues on client B.
+Another not that easy task is the network protocol itself. You have to write
+several send() and receive() functions which apply changed values of properties
+to the local property.
+
+KGameProperty is designed to do all of this for you. KGameProperty is
+implemented as a template so you can use it theoretically for every type of data
+- even for your self defined classes.
+
+
+3.1 Using KGameProperty
+-----------------------
+It is basically very easy to use a KGameProperty. You first create your own
+class containing the property, e.g:
+class MyGame : public KGame
+{
+[...]
+protected:
+ KGamePropertyInt money;
+ KGamePropertyQString name;
+ KGameProperty<AntotherClass> myProperty;
+};
+KGamePropertyInt is just a typedef for KGameProperty<int> - just like
+KGamePropertyQString. Now you need to register the properties in the constructor
+of the class to the KGamePropertyHandler:
+MyGame::MyGame() : KGame(myCookie)
+{
+ money.registerData(KGamePropertyBase::IdUser+1, dataHandler(), "Money");
+ name.registerData(KGamePropertyBase::IdUser+2, this, "Name");
+ myProperty.registerData(KGamePropertyBase::IdUser+3, dataHandler(), "MyProperty");
+}
+-> You need to specify a *unique* ID. This ID must be greater than
+KGamePropertyBase::IdUser. IDs below this are reserved for KGame. Probably this
+will be changed so that you cannot use IDs below IdUser in the future. Then you
+have to specify the dataHandler(). You can also use a KGame or KPlayer pointer.
+This will automatically use KGame::dataHandler() or KPlayer::dataHandler().
+Finally you *can* provide a name for the property. This will be used for
+debugging in KGameDebugDialog. If you want to save some memory you can leave
+this out.
+Note that if you use pointers to create the properties dynamically they are
+*not* deleted automatically! You MUST delete them yourself!
+Now you can use the KGameProperty like every variable else. See also Section
+"3.3 Concepts" for restrictions in use.
+
+3.2 Custom Classes
+------------------
+To make custom classes possible you have to implement several operators for your
+them: you need at least << and >> for QDataStream as well as "==" for your own
+class. To overload the "<<" you would e.g. do something like this:
+QDataStream& operator<<(QDataStream& stream, MyData& data)
+{
+ int type = data.type;
+ QString name = data.name;
+ stream << type << name;
+ return stream;
+}
+So you basically just have to split your class to several basic types and stream
+them.
+
+3.3 Concepts
+------------
+You can use KGameProperty basically in two completely different ways. You can
+also use a mixture of both but this is not recommended. The default behaviour
+and therefore also the recommended is the "clean" way:
+a) Always Consistent. This means that a KGameProperty has always the same value
+on *every* client. This is achieved by using KGameProperty::send() whenever you
+want to change the value using "=". You can still use changeValue() or
+setLocal() but send() will be the default. If you use send() then the value of
+the property does *NOT* change immediately. It is just sent to the
+KMessageServer which forwards the value to all clients. As soon as the new value
+is received from the message server the KGamePropertyHandler (a collection class
+for KGameProperty) calls KGameProperty::load() and changes the value of the
+property. So the game first has to go into the event loop, where the message is
+received. This means to you that you cannot do this:
+myIntProperty = 10;
+int value = myIntProperty;
+As myIntPoperty still has the old value when "value = myIntProperty" is called.
+This might seem to be quite complex, but
+KGamePropertyHandler::signalPropertyChanged() is emitted whenever a new value is
+assigned so you can connect to this and work immediately with the new value.
+You gain the certainty that the value is the same on every client every time.
+That will safe you a lot of time debugging!
+Another way is the "dirty" way:
+b) Not Always Consistent. Sometimes you really *want* to do something like
+myIntProperty = 10;
+int value = myIntProperty;
+but this is not possible with the default behaviour. If you call
+KGameProperty::setAlwaysConsistent(false) in the constructor (right after
+registerData()) you get another behaviour. "=" means changeValue() now.
+changeValue() also uses send() to change the value but additionally calls
+setLocal() to create a local copy of the property. This copy now has the value
+you supplied with "=" and is deleted again as soon as any value from the network
+is received.
+
+4. KGameIO
+----------
+The class KGameIO is used to let the players communicate with the server. You
+can plug as many KGameIO objects into a player as you want, e.g. you can plug a
+KGameMouseIO and a KGameKeyIO into a player so that you can control the player
+with the mouse and the keyboard - e.g. in a breakout game.
+You can probably see the advantage: as most of the control stuff is common in a
+lot of games you can use the same IO class in many different games with very
+small adjustments.
+You could also put all the IO stuff directly into your KPlayer object, like
+sendBet(int money) for a poker game. But there is a major disadvantage and I'm
+very sure you don't want to use a KPlayer object for your IO stuff as soon as
+you know which disadvantage:
+KGameIO is designed to be able to switch between different IOs "on the fly". So
+you might have a KGamePlayerIO, derived from KGameIO, for your game. But now
+this player (who "owns"/uses the KGamePlayerIO) leaves the game (e.g. because he
+was a remote player). So now the game would be over for every player as one
+player is now out of order. But with KGameIO you can just let any of the
+remaining clients create a KGameComputerIO and plug this into the player. So the
+player now is controlled by the computer and the game can continue.
+
+Think about it! You don't have to care about removing players when a player
+leaves as you can just replace it! The same works the other way round: imagine a
+game with 10 player (e.g. 5 human and 5 computer players) that has already
+started. You cannot add any further players without restarting. So if there are
+any additional player you can just call KPlayer::removeGameIO() which removes
+the IO of a computer player and then call KPlayer::addGameIO() for the same
+player which adds a GameIO for new human player. That's all!
+
+To achieve this you just have to make sure that you make *all* of your IO
+operations through a KGameIO! So instead of using MyPlayer::sendBet(int money)
+you should use something like MyIO::sendBet(). The amount of money would
+probably be calculated by the game IO itself.
+
+
+
+5. Debugging
+------------
+The general debugging concept (if there is one at all) or general debugging
+hints are not yet written. Feel free to do so
+
+5.1 KGameDebugDialog
+--------------------
+A nice way of debugging a KGame based game is the KGameDebugDialog. Basically
+all you have to do is to add something like "Debug" to your game's menu and add
+a slot like
+slotDebug()
+{
+ KGameDebugDialog* dialog = new KGameDebugDialog(mGame, this);
+ connect(dialog, SIGNAL(finished()), dialog, SLOT(slotDelayedDestruct()));
+ dialog->show();
+}
+that's it.
+You can now click on that menu entry and you get a non-modal dialog where you
+can start to debug :-)
+The dialog consist of several pages. You can easily add your own using
+KDialogBase::addVBoxPage() (for example).
+
+5.1.1 Debug KGame
+-----------------
+The first page, "Debug KGame" shows on the left most or even all status values of
+KGame. That contains e.g. minPlayers(), isAdmin(), gameStatus(), ...
+The right side is probably the more important one. It lists *all* KGameProperties
+which have been inserted to this KGame object (only to this KGame object - not
+the ones that have been added to the players!). Most of the status variables of
+the left side are here again as they are implemented as KGameProperty. You can
+see the name of the property (together with its ID), its value and the policy
+this property uses. Note that "unknwon" will be displayed as name of the
+property if you haven't supplied one. See KGamePropertyBase::registerData() for
+info. You probably always want to supply a name for the property to debug it
+easily. In the future there will be something like
+KGamePropertyHandler::setDebug() so that you can switch off debugging and save
+the memory of the names in a release version.
+For as long as you use standard types for your properties (int, long, bool,
+...) you should always be able to see the value of the property. If you just see
+"unknown" then this type has not been implemented. You can connect to the signal
+KGamePropertyHandler::signalRequestValue() and supply a QString with the value
+yourself. If you do so for a standard type please also submit a bug report!
+
+Currently the dialog does *not* update automatically! So you alway have to click
+the "update" button when you want a current value. There are several reasons for
+this (and one of them is that i'm too lazy to implement the update ;)). E.g.
+often (very often) a property is just in the background - stores e.g. the
+available money in a game. But you don't want it to update whenever the value
+changes (a player receives/pays money) but only when the value on the screen
+changes.
+
+5.1.2 Debug Players
+-------------------
+This page consists of three widgets. On the very left there is a list of all
+players in the game. Only the IDs are displayed to save space. If you click one
+the other widgets are filled with content. These widgets are quite much the same
+as the ones in "Debug KGame" - the left shows the value of the functions and the
+right one displays all KProperties of a player. Not much to say here - except:
+See "Debug KGame".
+
+If you change to another player the value are also updated.
+
+5.1.3 Debug Messages
+--------------------
+This page is probably not as important as the other ones. It displays *every*
+message that is sent through the KGame object. As a KGameProperry also send
+messages you probably get a lot of them...
+You can exclude message IDs from being displayed (e.g. all game properties).
+You can also change the sorting of the list to see all messages of a certain ID.
+The default is to sort by time (which is displayed on the left side).
+