0ad/source/network/NetServer.h
Ykkrosh 1e3cd00c72 Set svn:eol-style=native
This was SVN commit r6816.
2009-04-11 17:00:39 +00:00

346 lines
10 KiB
C++

/**
*-----------------------------------------------------------------------------
* FILE : NetServer.h
* PROJECT : 0 A.D.
* DESCRIPTION : Network server class interface file
*-----------------------------------------------------------------------------
*/
#ifndef NETSERVER_H
#define NETSERVER_H
// INCLUDES
#include "Network.h"
#include "NetSession.h"
#include "simulation/TurnManager.h"
#include "scripting/ScriptableObject.h"
#include "ps/GameAttributes.h"
#include "ps/scripting/JSMap.h"
#include "ps/Player.h"
#include "ps/Game.h"
#include "simulation/ScriptObject.h"
#include <map>
#include <vector>
// DECLARATIONS
#define SERVER_SESSIONID 1
#define CLIENT_MIN_SESSIONID 100
#define MAX_CLIENTS 8
#define MAX_OBSERVERS 5
#define DEFAULT_SERVER_SESSION_ID 1
#define DEFAULT_SERVER_NAME L"Noname Server"
#define DEFAULT_PLAYER_NAME L"Noname Player"
#define DEFAULT_WELCOME_MESSAGE L"Noname Server Welcome Message"
#define DEFAULT_HOST_PORT 0x5073
enum NetServerState
{
// We haven't opened the port yet, we're just setting some stuff up.
// This is probably equivalent to the first "Start Network Game" screen
SERVER_STATE_PREBIND,
// The server is open and accepting connections. This is the screen where
// rules are set up by the operator and where players join and select civs
// and stuff.
SERVER_STATE_PREGAME,
// The one with all the killing ;-)
SERVER_STATE_INGAME,
// The game is over and someone has won. Players might linger to chat or
// download the replay log.
SERVER_STATE_POSTGAME
};
enum
{
NSS_HANDSHAKE = 1300,
NSS_AUTHENTICATE = 1400,
NSS_PREGAME = 1500,
NSS_INGAME = 1600
};
enum
{
NMT_APP_PLAYER_LEAVE = NMT_LAST + 100,
NMT_APP_PREGAME = NMT_LAST + 200,
NMT_APP_OBSERVER = NMT_LAST + 300
};
typedef std::map< uint, CNetSession* > IDSessionMap;
typedef std::vector< CNetSession* > SessionList;
/*
CLASS : CNetServer
DESCRIPTION : CNetServer implements a network server for the game.
It receives data and connection requests from clients.
Under the hood, it uses ENet library to manage connected
peers and bandwidth among these.
NOTES :
*/
class CNetServer : public CNetHost,
public CJSObject<CNetServer>,
public CTurnManager
{
public:
CNetServer( CGame* pGame, CGameAttributes* pGameAttributes );
virtual ~CNetServer( void );
bool Start ( JSContext *pContext, uintN argc, jsval *argv );
// void Shutdown ( void );
/**
* Returns true indicating the host acts as a server
*
* @return Always true
*/
virtual bool IsServer( void ) const { return true; }
/**
* Adds a new session to the list of sessions
*
* @param pSession New session to add
*/
void AddSession( CNetSession* pSession );
/**
* Removes the specified session from the list of sessions. If the session
* isn't found it returns NULL otherwise it returns the session object found.
*
* @param pSession Session to remove
* @return The session object if found, NULL otherwise
*/
CNetSession* RemoveSession( CNetSession* pSession );
/**
* Removes all the sessions managed by the network server
*
*/
//void RemoveAllSessions( void );
/**
* Returns the number of session the server manages
*
* @return The number of sessions
*/
//uint GetSessionCount( void ) const;
/**
* Returns the session object for the specified ID
*
* @param sessionID The session ID
* @return A pointer to session for the specified ID or
* NULL if not found
*/
CNetSession* GetSessionByID( uint sessionID );
protected:
virtual bool SetupSession ( CNetSession* pSession );
virtual bool HandleConnect ( CNetSession* pSession );
virtual bool HandleDisconnect ( CNetSession *pSession );
private:
// Not implemented
CNetServer( const CNetServer& );
CNetServer& operator=( const CNetServer& );
//void ClientConnect ( ENetPeer* pPeer );
//void ClientDisconnect ( ENetPeer* pPeer );
//void ClientReceive ( ENetPeer* pPeer, ENetPacket* pPacket );
/**
* Returns the session associated with the specified ENet peer
*
* @param pPeer ENet peer
* @return The session object if found or NULL
*/
//CNetSession* GetSessionByPeer( const ENetPeer* pPeer );
/**
* Setup client game by sending the apropiate network messages. It also
* inform the client about the other connected clients as well as player
* slot assignment and attributes.
*
*/
//void SetupNewSession( CNetSession* pSession );
/**
* Loads the player properties into the specified message
*
* @param pMessage Message where to load player properties
* @param pPlayer Player for which we load the properties
*/
void BuildPlayerConfigMessage(
CPlayerConfigMessage* pMessage,
CPlayer* pPlayer );
/**
* Callback function used by the BuildPlayerSetupMessage to iterate over
* the player properties. It will be called for each property of the player
*
* @param name Property name
* @param pProperty Pointer to player property
* @param pData Context pointer passed on iteration startup
*/
static void PlayerConfigMessageCallback(
const CStrW& name,
ISynchedJSProperty* pProperty,
void* pData );
/**
* Loads game properties into the specified message
*
* @param pMessage Message where to load game properties
*/
void BuildGameSetupMessage( CGameSetupMessage* pMessage );
/**
* Loads player slot properties into the specified message
*
* @param pMessage Message where to load player properties
* @param pPlayerSlot Player slot properties
*/
void BuildPlayerSlotAssignmentMessage(
CAssignPlayerSlotMessage* pMessage,
CPlayerSlot* pPlayerSlot );
/**
* Callback function used by the BuildGameSetupMessage to iterate over the
* game properties. It will be called for each property of the game
*
* @param name Property name
* @param pProperty Pointer to game property
* @param pData Context pointer passed on iteration startup
*/
// IterateCB GameSetupMessageCallbak;
static void GameSetupMessageCallback(
const CStrW& name,
ISynchedJSProperty *pProperty,
void *pData );
/**
* Retrieves a free session ID from the recycled sessions list
*
* @return Free session ID
*/
uint GetFreeSessionID( void ) const;
IDSessionMap m_IDSessions; // List of connected ID and session pairs
//CScriptObject m_ScriptConnect; // Script client connect dispatch
//CScriptObject m_ScriptDisconnect; // Script client disconnect dispatch
//CScriptObject m_ScriptChat; // Script client chat dispatch
CPlayer* m_Player; // Server player
public:
/**
*
*
* @param addr Address where to bind
* @return PS_OK if bind successfully, error code otherwise
*/
//PS_RESULT Bind( const CSocketAddress& addr );
void SetPlayerPassword ( const CStr& password );
CStrW GetPlayerName ( void ) const { return m_PlayerName; }
NetServerState GetState ( void ) const { return m_State; }
int StartGame ( void );
static void ScriptingInit ( void );
protected:
// Assign a session ID to the session. Do this just before calling AddSession
void AssignSessionID( CNetSession* pSession );
// Add the session. This will be called after the session passes the
// handshake and authentication stages. AssignSessionID should've been called
// on the session prior to calling this method.
//void AddSession( CNetServerSession* pSession );
// Remove the session from the server
//void RemoveSession( CNetServerSession* pSession );
// Queue a command coming in from the wire. The command has been validated
// by the caller.
void QueueIncomingCommand( CNetMessage* pMessage );
// Call the JS callback for incoming events
void OnPlayerChat ( const CStrW& from, const CStrW& message );
void OnPlayerJoin ( CNetSession* pSession );
void OnPlayerLeave ( CNetSession* pSession );
void SetupPlayer ( CNetSession* pSession );
//static bool OnPlayerJoin ( void* pContext, CFsmEvent* pEvent );
static bool OnError ( void* pContext, CFsmEvent* pEvent );
static bool OnHandshake ( void* pContext, CFsmEvent* pEvent );
static bool OnAuthenticate ( void* pContext, CFsmEvent* pEvent );
static bool OnPreGame ( void* pContext, CFsmEvent* pEvent );
static bool OnInGame ( void* pContext, CFsmEvent* pEvent );
static bool OnChat ( void* pContext, CFsmEvent* pEvent );
// OVERRIDES FROM CServerSocket
//virtual void OnAccept( const CSocketAddress& address );
// OVERRIDES FROM CTurnManager
virtual void NewTurn( void );
virtual bool NewTurnReady( void );
virtual void QueueLocalCommand( CNetMessage* pMessage );
// Will only be called from the Network Thread, by the OnAccept handler
//virtual CNetServerSession* CreateSession( CSocketInternal* pSocketInternal);
// Ask the server if the session is allowed to start observing.
//
// Returns:
// true if the session should be made an observer
// false otherwise
virtual bool AllowObserver( CNetSession* pSession );
private:
CGameAttributes* m_GameAttributes; // Stores game attributes
//int m_LastSessionID; // Stores the last session ID
//SessionMap m_Sessions; // Managed sessions
CJSMap< IDSessionMap > m_JsSessions;
CMutex m_Mutex; // Synchronization object for batches
/*
All sessions that have observer status (observer as in watcher - simple
chatters don't have an entry here, only in m_Sessions).
Sessions are added here after they have successfully requested observer
status.
*/
SessionList m_Observers;
uint m_MaxObservers; // Maximum number of observers
CGame* m_Game; // Pointer to actual game
NetServerState m_State; // Holds server state
CStrW m_Name; // Server name
CStrW m_WelcomeMessage; // Nice welcome message
//CPlayer* m_Player; // Pointer to 'server' player
CStrW m_PlayerName; // Player name
CStrW m_PlayerPassword; // Player password
int m_Port; // The listening port
CScriptObject m_OnChat;
CScriptObject m_OnClientConnect;
CScriptObject m_OnClientDisconnect;
// static CGameAttributes::UpdateCallback AttributeUpdate;
// static CPlayer::UpdateCallback PlayerAttributeUpdate;
// static PlayerSlotAssignmentCB PlayerSlotAssignmentCallback;
static void AttributeUpdate ( const CStrW& name, const CStrW& newValue, void* pData);
static void PlayerAttributeUpdate ( const CStrW& name, const CStrW& value, CPlayer* pPlayer, void* pData );
static void PlayerSlotAssignment ( void* pData, CPlayerSlot* pPlayerSlot );
};
extern CNetServer *g_NetServer;
#endif // NETSERVER_H