/* Crystal Space Entity Layer Copyright (C) 2005 by Christian Van Brussel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __CEL_PL_NETWORK__ #define __CEL_PL_NETWORK__ #include "cstypes.h" #include "csutil/scf.h" #include "csutil/strset.h" struct iCelEntity; struct iCelDataBuffer; enum celNetworkGameType; enum celServerNetworkState; enum celPlayerNetworkState; struct celGame; class celGameInfo; class celPlayer; struct iCelPlayerList; class celServerEventData; class celClientEventData; class celNetworkLinkData; class celGameFactoryManager; class celGameClientManager; class celGameServerManager; struct celNetworkServerStats; struct celNetworkPlayerStats; struct celNetworkServerTotalStats; SCF_VERSION (iCelGame, 0, 0, 1); /** * A networked game. It maintains the main data of a game: game type, game * info and pointers to the local client and server. */ struct iCelGame : public iBase { /** * Return the type of the game. */ virtual celNetworkGameType GetGameType () const = 0; /** * Return the general info of the game. */ virtual celGameInfo* GetGameInfo () = 0; /** * Return true if a local server is available in this process, * false otherwise. */ virtual bool IsServerAvailable () const = 0; /** * Return the local server if available, 0 otherwise. */ virtual iCelGameServer* GetGameServer () const = 0; /** * Return true if a local client is available in this process, * false otherwise. */ virtual bool IsClientAvailable () const = 0; /** * Return the local client if available, 0 otherwise. */ virtual iCelGameClient* GetGameClient () const = 0; }; SCF_VERSION (iCelGameFactory, 0, 0, 1); /** * A factory to manage game sessions. You can use it to: *
There should be only one game factory in an application. */ struct iCelGameFactory : public iBase { /** * Set the name of the game. Client and server instances can talk * together only if they have the same game name and protocol version. *
A game name must be set before any operation on the factory. * \param game_name an arbitrary game name, like "Crystal Core". */ virtual void SetGameName (csString game_name) = 0; /** * Return the name of the game. Client and server instances can talk * together only if they have the same game name and protocol version. */ virtual csString GetGameName () const = 0; /** * Set the name of the network protocol version used by this application. * Client and server instances can talk together only if they have the * same game name and protocol version. *
A protocol version must be set before any operation on the factory. *
The protocol version should be changed each time something has been * changed in the network protocol of the game, ie in the meaning of the * network events, like changes in the implementation of the network * plugin, the selection of property classes of the entities, the client * and server events, the network links and the baselines. * \param protocol_version an arbitrary protocol version name, like "v0.3". */ virtual void SetProtocolVersion (const csString protocol_version) = 0; /** * Return the network protocol version used by this application. Client * and server instances can talk together only if they have the same game * name and protocol version. */ virtual csString GetProtocolVersion () const = 0; /** * Register a manager for this game factory. The manager will be notified * when events are thrown from the game factory. Only one manager can be * registered at a time. *
A manager must be registered before any operation on the factory. */ virtual void RegisterGameFactoryManager ( celGameFactoryManager* manager) = 0; /** * Start to search for the list of available games with the same game name, * protocol version and game type. The registered celGameFactoryManager * will be notified through celGameFactoryManager::GameInfoReceived each * time a game has been found. A celGameInfo object can be provided to * filter the games. * \param filter a new game info will be received only if * celGameInfo::MatchFilter returns true with this filter. */ virtual void StartSearchForGameList (celNetworkGameType game_type, celGameInfo* filter = 0) = 0; /** * Stop searching for the list of available games. No more * celGameFactoryManager::GameInfoReceived will be raised. */ virtual void StopSearchForGameList () = 0; /** * Return the current game or 0 if no game is available. */ virtual iCelGame* GetCurrentGame () const = 0; /** * Create a new game, ie at least a server, but also a client if a player is * provided. Only one game can be created at a time, so if a game is already * running, it will be closed before the new game is launched. If the game * factory was searching for games, it will stop its search. * \param game_type the type of the game. It can be CEL_NET_SINGLEPLAYER, * CEL_NET_LOCAL or CEL_NET_PUBLIC. * \param game_info the informations on the game. * \param player the player launching the game. He can be given special * access rights to modify the game. If player is different from 0, then * a client will also be created. * \return true if the game can be created. */ virtual bool CreateNewGame (celNetworkGameType game_type, celGameInfo* game_info, celPlayer* player = 0) = 0; /** * Connect the player to the game specified in game_info. If a game is * already running, it will be closed before the new game is launched. The * game_info field must contain the necessary data to find the server, ie a * game_id field previously returned by * celGameFactoryManager::GameInfoReceived, or the ip_address and port_nb * fields. If the game factory was searching for games, it will stop its * search. * \param game_info the informations on the game we want to connect to. * \param player the player which is connecting to the game. * \return true if the game can be connected. */ virtual bool ConnectGame (celGameInfo* game_info, celPlayer* player) = 0; /** * The player leaves the current game or playback. If a server was also set, * it will be closed. * \return true if the game can be closed, false otherwise. */ virtual bool CloseGame () = 0; /** * Incoming events are recorded in a file. A game must previously be running. */ virtual void StartRecordingGame (csString filename) = 0; /** * Incoming events are no more recorded in a file. */ virtual void StopRecordingGame () = 0; /** * Start a game where incoming events are read from a file from start_time to * stop_time. CloseGame can be used to stop the playback. If the game * factory was searching for available games or if a game was running, they * will be stopped. */ virtual void StartPlayBackGame (csString filename, csTicks start_time, csTicks stop_time) = 0; }; /** * This is an interface you should implement in order to manage the events from * the factory of game sessions. You can use it to: *
You should create here a physical layer which will be the copy of the * physical layer of the server. You should wait for network links from the * server before adding most entities, but you can start loading the level, * ie the static entities. If the type of the game is CEL_NET_SINGLEPLAYER, * you do not need to create a physical layer and you can access directly * the one from the server. *
You should register here the client manager. */ virtual bool InitClient (iCelGame* game) { return true; } /** * A server is created and has to be initialized. The iCelGameServer object * is accessible from the celGame object. *
You should create here the physical layer, the initial entities and * their behaviors. *
You should register here the server manager. */ virtual bool InitServer (iCelGame* game) { return true; } /** * Return the baseline of a client event. Baselines are the default types and * values of the fields of an event. They are used to limit the network * traffic by delta-compression and by allowing the system to not be forced * to send the types of the data. *
It is not obligatory to provide the baselines and this
* function can return 0, but this can result in some network overhead.
*/
virtual csPtr If the entity is controlled on the client side, the network link will
* be in the other direction and the state of the entity will be sent
* periodically from the client side to the server side.
* If a link between the entity and the player is already present, the
* previous link will be removed.
* \param player the player linked to the entity
* \param link_data the data of the network link
* \param player_controlled false if the entity is controlled by the server,
* true if it is by the client (ie this is the client that will update the
* entity and send its state to the server, instead of the contrary).
*/
virtual void SetNetworkLink (celPlayer* player,
celNetworkLinkData &link_data, bool player_controlled) = 0;
/**
* Define if it is the client or the server that will update the entity. A
* network link between the player and the entity must be present.
* \param entity the entity network linked to the player
* \param player the player network linked to the entity
* \param player_controlled false if the entity is controlled by the server,
* true if it is by the client (ie this is the client that will update the
* entity and send its state to the server, instead of the contrary).
*/
virtual void ChangeLinkControl (iCelEntity* entity, celPlayer* player,
bool player_controlled) = 0;
/**
* Establish a link between a source entity and the players in a list. When a
* link is set up, a copy entity will be created on each client side and the
* server manager will send periodically a part of the state of the entity
* to the copy entity.
* If a link between the entity and the channel is already present, the
* previous link will be removed.
* \param channel_id the ID of the channel
* \param link_data the data of the network link
*/
virtual void SetNetworkLink (csStringID channel_id,
celNetworkLinkData &link_data) = 0;
/**
* Remove the existing link between the entity and the player, ie the state
* of the entity will no more be sent to the player.
*/
virtual void RemoveNetworkLink (iCelEntity* entity, celPlayer* player) = 0;
/**
* Remove the existing link between the entity and the channel, ie the state
* of the entity will no more be sent to the players in the list.
*/
virtual void RemoveNetworkLink (iCelEntity* entity,
csStringID channel_id) = 0;
/**
* Level change, the game is re-initialized. Clear all pending network links
* and server events. The iCelGameClientManager of all players will be called
* with celGameClientManager::LevelChanged. All the players are marked as
* CEL_NET_PLAYER_CONNECTING, they will need to do iCelGameClient::SetReady.
* \param level_name a significant name for the new level.
*/
virtual void ChangeLevel (celGameInfo* new_game) = 0;
/**
* Specify the maximum frequency at which the server can send data to clients.
* \param period the number of ticks between two updates from the
* server. A period of 0 means "as soon as possible".
*/
virtual void SetNetworkPeriod (csTicks period) = 0;
/**
* Specify the maximum bandwidth of the network data transmission in bytes per
* second. A bandwidth of 0 means that it is unlimited.
*/
virtual void SetMaximumBandwidth (size_t width) = 0;
/**
* The server will consider a client connected until the connection is
* broken (network state CEL_NET_PLAYER_UNREACHABLE) during the specified
* time.
*/
virtual void SetClientTimeOut (csTicks timeout) = 0;
/**
* Return the network stats of the specified player.
*/
virtual void GetNetworkPlayerStats (celPlayer* player,
celNetworkPlayerStats& stats) const = 0;
/**
* Return the network stats of this server.
*/
virtual void GetNetworkTotalStats (
celNetworkPlayerTotalStats& stats) const = 0;
};
SCF_VERSION (iCelGameClient, 0, 0, 1);
/**
* The main object to manage the client game logic. You can use it to:
* If the server is available in the same process, you can simply use the
* entity of the server and then return 0 to this function.
* \param link_type the type of the network link. You should use it to know
* what type of entity has to be created.
* \param creation_time the time at which the network link is created.
* \param creation_data the persistent data of the entity at the creation of
* the network link.
* \param player_controlled true if the entity is controlled on the client
* side, false it is controlled on the server side.
* \return the copy entity.
*/
virtual iCelEntity* CreateNetworkLinkTarget (celNetworkLinkType link_type,
csTicks creation_time, iCelPersistentDataList* creation_data,
bool player_controlled) = 0;
/**
* There is a change in the way the entity is controlled, ie if it is
* controlled by the client or by the server side.
* If the entity is now controlled on the client side, you should then set
* a behavior to it. Most presumably, the behavior will catch the actions of
* the player and update accordingly the entity.
* If the entity is now controlled on the server side, you should then
* remove any behavior from the entity and let the client update it from the
* server.
* \param entity the entity which is networked linked.
* \param player_controlled true if the entity is controlled by the client
* side, false if it is controlled by the server side.
*/
virtual void NetworkLinkControlChanged (iCelEntity* entity,
bool player_controlled) = 0;
/**
* The network link to the specified entity is closing. The client can remove
* the entity from the physical layer.
*/
virtual void NetworkLinkRemoved (csTicks deletion_time,
iCelEntity* entity) = 0;
/**
* The level has changed. The client need to do iCelGameClient::SetReady when
* the new level is loaded.
*/
virtual void LevelChanged (celGameInfo* new_game) = 0;
/**
* The client will be closed. You should delete here the physical layer
* of the client.
*/
virtual void ClientEnd () = 0;
};
#endif // __CEL_PL_NETWORK__
*
* You should define and register a celGameServerManager which will catch
* the events from this server.
*/
struct iCelGameServer : public iBase
{
/**
* Register the manager of this server. Only one manager can be registered
* at a time.
*/
virtual void RegisterServerManager (celGameServerManager* manager) = 0;
/**
* Set the administrator of the game. It doesn't need to be a player already
* connected.
*/
virtual void SetAdministrator (celPlayer* new_admin) = 0;
/**
* Return the administrator of the game. The return value can be 0 if no
* administrator was defined in iCelGameFactory::CreateGame.
*/
virtual celPlayer* GetAdministrator () = 0;
/**
* Return the list of players connected to the server.
*/
virtual iCelPlayerList* GetPlayerList () = 0;
/**
* Return the state of the network connection to the player.
*/
virtual celPlayerNetworkState GetPlayerState (celPlayer* player) = 0;
/**
* Kick the player from the game, ie the player will be forced to
* disconnect from the game. A text explaining the reason can be
* specified.
*/
virtual void KickPlayer (celPlayer* player, csString reason) = 0;
/**
* Create a channel, ie a list of players. The list will be managed by the
* server which will listen to players disconnecting and will so remove them
* from the list. Channels are useful to send the same server events or
* create the same network links to a list of players.
* \param channel_id the ID of the channel
*/
virtual iCelPlayerList* CreateChannel (csStringID channel_id) = 0;
/**
* Stop managing the list of players and delete it. Any existing network
* links to this channel will also be removed.
*/
virtual void RemoveChannel (csStringID channel_id) = 0;
/**
* A server event has to be sent to a player.
*/
virtual void LaunchServerEvent (celPlayer* player,
celServerEventData &event_data) = 0;
/**
* A server event has to be sent to the players in the channel.
*/
virtual void LaunchServerEvent (csStringID channel_id,
celServerEventData &event_data) = 0;
/**
* Establish a link between an entity and a player. When a link is set up,
* a copy entity will be created on the client side and the server manager
* will send periodically a part of the state of the entity to the copy
* entity.
*
*
* You should define and register a celGameClientManager which will catch
* the events from this client.
*/
struct iCelGameClient : public iBase
{
/**
* Register the manager of this client. Only one manager can be registered at
* a time.
*/
virtual void RegisterClientManager (celGameClientManager* manager) = 0;
/**
* Return the current player associated with this client.
*/
virtual celPlayer* GetPlayer () = 0;
/**
* Update the data of the current player. The server will check if the new
* data are valid and a subsequent celGameClientManager::PlayerUpdated will
* be called with the validated data.
*/
virtual void UpdatePlayer (celPlayer* player) = 0;
/**
* Convert a time from the server clock to the client clock.
*/
virtual csTicks ConvertServerClock (csTicks server_time) const = 0;
/**
* Return the ID of the entity on the client side that is network linked with
* an entity with ID entity_id on the server side.
*/
virtual uint GetMappedID (uint entity_id) const = 0;
/**
* Return the entity on the client side that is network linked with an entity
* with ID entity_id on the server side.
*/
virtual iCelEntity* GetMappedEntity (uint entity_id) const = 0;
/**
* Indicate that the client has loaded everything and is ready to play.
*/
virtual void SetReady () = 0;
/**
* Ask the game client to send an event to the server.
*/
virtual void LaunchClientEvent (celClientEventData &event_data) = 0;
/**
* Specify the maximum frequency at which the client can send data.
*/
virtual void SetNetworkPeriod (csTicks period) = 0;
/**
* The maximum bandwidth of the network data transmission in bytes per
* second. A bandwidth of 0 means that it is unlimited.
*/
virtual void SetMaximumBandwidth (size_t width) = 0;
/**
* The client will consider itself connected to the server until the
* connection is broken during specified time.
*/
virtual void SetServerTimeOut (csTicks timeout) = 0;
/**
* Return the network stats of this client.
*/
virtual void GetNetworkStats (celNetworkServerStats& stats) const = 0;
};
/**
* This is an interface you should implement in order to manage the events from
* the server. You can use it to:
*
*
*/
class celGameServerManager
{
public:
/**
* A player is asking to join the game. Return true if the new player is
* accepted, false otherwise (for example, because the player has been
* banned). A text explaining the reason of a negative answer can be
* specified.
*/
virtual bool AuthorizePlayer (celPlayer* player, csString &reason) = 0;
/**
* Check if the new data of a player are valid. It happens when
* iCelGameClient::UpdatePlayer has been called on the client side.
* \return the validated data of the player.
*/
virtual celPlayer* ValidatePlayerUpdate (celPlayer* previous_player_data) = 0;
/**
* The state of the network connection to the player has changed.
*/
virtual void PlayerNetworkStateChanged (celPlayer* player,
celPlayerNetworkState new_state,
celPlayerNetworkState previous_state) = 0;
/**
* A client event has been catched.
*/
virtual void HandleClientEvent (celPlayer* player,
celClientEventType event_type, csTicks event_time,
iCelDataBuffer* event_data) = 0;
/**
* An entity is controlled by a player and a problem was encountered while
* updating the data of this entity.
* \param player The player controlling the entity.
* \param entity The entity controlled by the player.
* \param pc The property class updated while the problem was encountered.
* \param persist_code The code of the problem.
*/
virtual void PersistenceProblem (celPlayer* player, iCelEntity* entity,
iCelPropertyClass* pc, celPersistenceResult persist_code) = 0;
/**
* The game is finished and the server will be closed. You should delete
* here all entities and the physical layer.
*/
virtual void ServerEnd () = 0;
};
/**
* This is an interface you should implement in order to manage the events from
* the client. You can use it to:
*
*
*/
class celGameClientManager
{
public:
/**
* The data of the player has been validated by the server.
*/
virtual void PlayerValidated (celPlayer* player) = 0;
/**
* A server event has been catched.
*/
virtual void HandleServerEvent (celServerEventType event_type,
csTicks event_time, iCelDataBuffer* event_data) = 0;
/**
* A network link has been set up on the server side between a server entity
* and this client. A copy entity must be created on this client side. This
* copy entity will be the adressee of the updates from the network link.
*