#ifndef _Network_NetServer_H #define _Network_NetServer_H #include "Network/Session.h" #include "Game.h" #include "TurnManager.h" #include "scripting/JSMap.h" enum ENetServerState { // 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 NSS_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. NSS_PreGame, // In-Game state: the one with all the killing ;-) NSS_InGame, // The game is over and someone has won. Players might linger to chat or // download the replay log. NSS_PostGame }; class CNetServerSession; class CNetServer: protected CServerSocket, protected CTurnManager, public CJSObject { private: typedef std::map SessionMap; /* Every connected session is in m_Sessions as soon as the Handshake and Authentication stages are complete. */ SessionMap m_Sessions; CJSMap m_JSI_Sessions; /* 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. */ std::vector m_Observers; uint m_MaxObservers; int m_LastSessionID; ENetServerState m_ServerState; CGame *m_pGame; CGameAttributes *m_pGameAttributes; CPlayer *m_pServerPlayer; CStrW m_Password; CStrW m_ServerPlayerName; CStrW m_ServerName; CStrW m_WelcomeMessage; int m_Port; CScriptObject m_OnChat; CScriptObject m_OnClientConnect; CScriptObject m_OnClientDisconnect; static CGameAttributes::UpdateCallback AttributeUpdate; static CPlayer::UpdateCallback PlayerAttributeUpdate; static PlayerSlotAssignmentCB PlayerSlotAssignmentCallback; void FillSetGameConfig(CSetGameConfig *pMsg); void FillSetPlayerConfig(CSetPlayerConfig *pMsg, CPlayer *pPlayer); static CNetMessage *CreatePlayerSlotAssignmentMessage(CPlayerSlot *slot); // JS Interface Methods bool JSI_Open(JSContext *cx, uintN argc, jsval *argv); static void ScriptingInit(); protected: friend class CNetServerSession; // Assign a session ID to the session. Do this just before calling AddSession void AssignSessionID(CNetServerSession *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 *pMsg); // Call the JS callback for incoming events void OnChat(CStrW from, CStrW message); void OnClientConnect(CNetServerSession *pSession); void OnClientDisconnect(CNetServerSession *pSession); // OVERRIDES FROM CServerSocket virtual void OnAccept(const CSocketAddress &); // OVERRIDES FROM CTurnManager virtual void NewTurn(); virtual void QueueLocalCommand(CNetMessage *pMsg); // OVERRIDABLES // Will only be called from the Network Thread, by the OnAccept handler virtual CNetServerSession *CreateSession(CSocketInternal *pInt); // 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(CNetServerSession *pSession); public: CNetServer(CGame *pGame, CGameAttributes *pGameAttribs); virtual ~CNetServer(); static void GetDefaultListenAddress(CSocketAddress &address); PS_RESULT Bind(const CSocketAddress &address); inline void SetPassword(CStr password) { m_Password=password; } inline CStrW GetServerPlayerName() { return m_ServerPlayerName; } inline ENetServerState GetServerState() { return m_ServerState; } int StartGame(); void Broadcast(CNetMessage *); }; extern CNetServer *g_NetServer; #endif // _Network_NetServer_H