You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdegames/libtdegames/kgame/kgamenetwork.h

433 lines
15 KiB

/*
This file is part of the KDE games library
Copyright (C) 2001 Martin Heni (martin@heni-online.de)
Copyright (C) 2001 Andreas Beckermann (b_mann@gmx.de)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
/*
$Id$
*/
#ifndef __KGAMENETWORK_H_
#define __KGAMENETWORK_H_
#include <tqstring.h>
#include <tqobject.h>
#include <kdemacros.h>
class KGameIO;
class KMessageClient;
class KMessageServer;
class KGameNetworkPrivate;
/**
* The KGameNetwork class is the KGame class with network
* support. All other features are the same but they are
* now network transparent. It is not used directly but
* only via a KGame object. So you do not really have
* to bother with this object.
*
* @short The main KDE game object
* @author Martin Heni <martin@heni-online.de>
* @version $Id$
*/
class KDE_EXPORT KGameNetwork : public TQObject
{
Q_OBJECT
TQ_OBJECT
public:
/**
* Create a KGameNetwork object
*/
KGameNetwork(int cookie=42,TQObject* parent=0);
virtual ~KGameNetwork();
/**
* Gives debug output of the game status
**/
virtual void Debug();
/**
* @return TRUE if this is a network game - i.e. you are either MASTER or
* connected to a remote MASTER.
**/
bool isNetwork() const;
/**
* Is this the game MASTER (i.e. has started theKMessageServer). A
* game has always exactly one MASTER. This is either a KGame object (i.e. a
* Client) or an own MessageServer-process. A KGame object that has the
* MASTER status is always admin.
*
* You probably don't want to use this. It is a mostly internal method which
* will probably become protected. Better use isAdmin
*
* @see isAdmin
* @return Whether this client has started the KMessageServer
**/
bool isMaster() const;
/**
* The admin of a game is the one who initializes newly connected clients
* using negotiateNetworkGame and is allowed to configure the game.
* E.g. only the admin is allowed to use KGame::setMaxPlayers.
*
* If one KGame object in the game is MASTER then this client is the admin
* as well. isMaster and isAdmin differ only if the KMessageServer
* is running in an own process.
* @return Whether this client (KGame object) is the admin
**/
bool isAdmin() const;
/**
* The unique ID of this game
*
* @return int id
**/
TQ_UINT32 gameId() const;
/**
* Inits a network game as network MASTER. Note that if the
* KMessageServer is not yet started it will be started here (see
* setMaster). Any existing connection will be disconnected.
*
* If you already offer connections the port is changed.
*
* @param port The port on which the service is offered
* @return true if it worked
**/
bool offerConnections (TQ_UINT16 port);
/**
* Announces game MASTER on network using DNS-SD. Clients then can discover it using
* DNSSD::ServiceBrowser (or KGameConnectWidget) instead of manually entering
* IP address.
* @param type service type (something like _twin4._tcp).
* It should be unique for application.
* @param name game name that will be displayed by clients. If not
* set hostname will be used. In case of name conflict -2, -3 and so on will be added to name.
* @since 3.4
**/
void setDiscoveryInfo(const TQString& type, const TQString& name=TQString());
/**
* Inits a network game as a network CLIENT
*
* @param host the host to which we want to connect
* @param port the port we want to connect to
*
* @return true if connected
**/
bool connectToServer(const TQString& host, TQ_UINT16 port);
/**
* @since 3.2
* @return The port we are listening to if offerConnections was called
* or the port we are connected to if connectToServer was called.
* Otherwise 0.
**/
TQ_UINT16 port() const;
/**
* @since 3.2
* @return The name of the host that we are currently connected to is
* isNetwork is TRUE and we are not the MASTER, i.e. if connectToServer
* was called. Otherwise this will return "localhost".
**/
TQString hostName() const;
/**
* Stops offering server connections - only for game MASTER
* @return true
**/
bool stopServerConnection();
/**
* Changes the maximal connection number of the KMessageServer to max.
* -1 Means infinite connections are possible. Note that existing
* connections are not affected, so even if you set this to 0 in a running
* game no client is being disconnected. You can call this only if you are
* the ADMIN!
*
* @see KMessageServer::setMaxClients
* @param max The maximal number of connections possible.
**/
void setMaxClients(int max);
//AB: is this now internal only? Can we make it protected (maybe with
//friends)? sendSystemMessage AND sendMessage is very confusing to the
//user.
/**
* Sends a network message msg with a given msg id msgid to all clients.
* Use this to communicate with KGame (e.g. to add a player ot to configure
* the game - usually not necessary).
*
* For your own messages use sendMessage instead! This is mostly
* internal!
*
* @param buffer the message which will be send. See messages.txt for contents
* @param msgid an id for this message. See
* KGameMessage::GameMessageIds
* @param receiver the KGame / KPlayer this message is for.
* @param sender The KGame / KPlayer this message is from (i.e.
* you). You
* probably want to leave this 0, then KGameNetwork will create the correct
* value for you. You might want to use this if you send a message from a
* specific player.
* @return true if worked
*/
// AB: TODO: doc on how "receiver" and "sender" should be created!
bool sendSystemMessage(const TQByteArray& buffer, int msgid, TQ_UINT32 receiver=0, TQ_UINT32 sender=0);
/**
* @overload
**/
bool sendSystemMessage(int data, int msgid, TQ_UINT32 receiver=0, TQ_UINT32 sender=0);
/**
* @overload
**/
bool sendSystemMessage(const TQDataStream &msg, int msgid, TQ_UINT32 receiver=0, TQ_UINT32 sender=0);
/**
* @overload
**/
bool sendSystemMessage(const TQString& msg, int msgid, TQ_UINT32 receiver=0, TQ_UINT32 sender=0);
/**
* Sends a network message
* @param error The error code
* @param message The error message - use KGameError
* @param receiver the KGame / KPlayer this message is for. 0 For
* all
* @param sender The KGame / KPlayer this message is from (i.e.
* you). You probably want to leave this 0, then KGameNetwork will create
* the correct value for you. You might want to use this if you send a
* message from a specific player.
**/
void sendError(int error, const TQByteArray& message, TQ_UINT32 receiver=0, TQ_UINT32 sender=0);
/**
* Are we still offer offering server connections - only for game MASTER
* @return true/false
**/
bool isOfferingConnections() const;
/**
* Application cookie. this idendifies the game application. It
* help to distinguish between e.g. KPoker and KWin4
* @return the application cookie
**/
int cookie() const;
/**
* Send a network message msg with a given message ID msgid to all clients.
* You want to use this to send a message to the clients.
*
* Note that a message is always sent to ALL clients! This is necessary so
* that all clients always have the same data and can easily be changed from
* network to non-network without restarting the game. If you want a
* specific KGame / KPlayer to react to the message use the
* receiver and sender parameters. See KGameMessage::calsMessageId
*
* SendMessage differs from sendSystemMessage only by the msgid parameter.
* sendSystemMessage is thought as a KGame only mehtod while
* sendMessage is for public use. The msgid parameter will be
* +=KGameMessage::IdUser and in KGame::signalNetworkData msgid will
* be -= KGameMessage::IdUser again, so that one can easily distinguish
* between system and user messages.
*
* Use sendSystemMessage to comunicate with KGame (e.g. by adding a
* player) and sendMessage for your own user message.
*
* Note: a player should send messages through a KGameIO!
*
* @param buffer the message which will be send. See messages.txt for contents
* @param msgid an id for this message. See KGameMessage::GameMessageIds
* @param receiver the KGame / KPlayer this message is for.
* @param sender The KGame / KPlayer this message is from (i.e.
* you). You
* probably want to leave this 0, then KGameNetwork will create the correct
* value for you. You might want to use this if you send a message from a
* specific player.
* @return true if worked
**/
// AB: TODO: doc on how "receiver" and "sender" should be created!
bool sendMessage(const TQByteArray& buffer, int msgid, TQ_UINT32 receiver=0, TQ_UINT32 sender=0);
/**
* This is an overloaded member function, provided for convenience.
**/
bool sendMessage(const TQDataStream &msg, int msgid, TQ_UINT32 receiver=0, TQ_UINT32 sender=0);
/**
* This is an overloaded member function, provided for convenience.
**/
bool sendMessage(const TQString& msg, int msgid, TQ_UINT32 receiver=0, TQ_UINT32 sender=0);
/**
* This is an overloaded member function, provided for convenience.
**/
bool sendMessage(int data, int msgid, TQ_UINT32 receiver=0, TQ_UINT32 sender=0);
/**
* Called by ReceiveNetworkTransmission(). Will be overwritten by
* KGame and handle the incoming message.
**/
virtual void networkTransmission(TQDataStream&, int, TQ_UINT32, TQ_UINT32, TQ_UINT32 clientID) = 0;
/**
* Disconnect the current connection and establish a new local one.
**/
void disconnect();
/**
* If you are the ADMIN of the game you can give the ADMIN status away to
* another client. Use this e.g. if you want to quit the game or if you want
* another client to administrate the game (note that disconnect calls
* this automatically).
* @param clientID the ID of the new ADMIN (note: this is the _client_ID
* which has nothing to do with the player IDs. See KMessageServer)
**/
void electAdmin(TQ_UINT32 clientID);
/**
* Don't use this unless you really know what youre doing! You might
* experience some strange behaviour if you send your messages directly
* through the KMessageClient!
*
* @return a pointer to the KMessageClient used internally to send the
* messages. You should rather use one of the send functions!
**/
KMessageClient* messageClient() const;
/**
* Don't use this unless you really know what you are doing! You might
* experience some strange behaviour if you use the message server directly!
*
* @return a pointer to the message server if this is the MASTER KGame
* object. Note that it might be possible that no KGame object contains
* the KMessageServer at all! It might even run stand alone!
**/
KMessageServer* messageServer() const;
/**
* You should call this before doing thigs like, e.g. tqApp->processEvents().
* Don't forget to call unlock once you are done!
*
* @see KMessageClient::lock
**/
virtual void lock();
/**
* @see KMessageClient::unlock
**/
virtual void unlock();
signals:
/**
* A network error occurred
* @param error the error code
* @param text the error text
*/
void signalNetworkErrorMessage(int error, TQString text);
/**
* Our connection to the KMessageServer has broken.
* See KMessageClient::connectionBroken
**/
void signalConnectionBroken();
/**
* This signal is emitted whenever the KMessageServer sends us a message that a
* new client connected. KGame uses this to call KGame::negotiateNetworkGame
* for the newly connected client if we are admin (see isAdmin)
*
* @see KMessageClient::eventClientConnected
*
* @param clientID the ID of the newly connected client
**/
void signalClientConnected(TQ_UINT32 clientID);
/**
* This signal is emitted whenever the KMessageServer sends us a message
* that a connection to a client was detached. The second parameter can be used
* to distinguish between network errors or removing on purpose.
*
* @see KMessageClient::eventClientDisconnected
*
* @param clientID the client that has disconnected
* @param broken true if the connection was lost because of a network error, false
* if the connection was closed by the message server admin.
*/
void signalClientDisconnected(TQ_UINT32 clientID, bool broken);
/**
* This client gets or loses the admin status.
* @see KMessageClient::adminStatusChanged
* @param isAdmin True if this client gets the ADMIN status otherwise FALSE
**/
void signalAdminStatusChanged(bool isAdmin);
protected:
/**
* @internal
* Start a KMessageServer object and use it as the MASTER of the game.
* Note that you must not call this if there is already another master
* running!
**/
void setMaster();
protected slots:
/**
* Called by KMessageClient::broadcastReceived() and will check if the
* message format is valid. If it is not, it will generate an error (see
* signalNetworkVersionError and signalNetworkErorrMessage).
* If it is valid, the pure virtual method networkTransmission() is called.
* (This one is overwritten in KGame.)
**/
void receiveNetworkTransmission(const TQByteArray& a, TQ_UINT32 clientID);
/**
* This KGame object receives or loses the admin status.
* @param isAdmin Whether we are admin or not
**/
void slotAdminStatusChanged(bool isAdmin);
/**
* Called when the network connection is about to terminate. Is used
* to store the network parameter like the game id
*/
void aboutToLoseConnection(TQ_UINT32 id);
/**
* Called when the network connection is terminated. Used to clean
* up the disconnect parameter
*/
void slotResetConnection();
private:
void tryPublish();
void tryStopPublishing();
KGameNetworkPrivate* d;
};
#endif