Matei
207d1367ec
- The server will no longer send a new turn until the previous one has been "acknowledged". (TODO: this may create lag between turns in its current form; investigate and possibly allow executing two turns while the third is being negotiated). - Mutexes are now being used in NetServer and NetClient to ensure commands go into the right batches. - Commented out some orders in the GUI code that should not be there and are not 100% working anyway (they were part of the follow/formation system). - Units that spawn or are created by scripts now have net-safe position and orientation. - Added a debug flag that can be turned on to print details about when commands are received and executed (DEBUG_SYNCHRONIZATION). This is especially useful if you diff the stdouts of two running games. There should be no differences if everything is in synch. This was SVN commit r5463.
153 lines
4.2 KiB
C++
153 lines
4.2 KiB
C++
#ifndef INCLUDED_NETWORK_SERVER
|
|
#define INCLUDED_NETWORK_SERVER
|
|
|
|
#include "Session.h"
|
|
#include "ps/GameAttributes.h"
|
|
#include "simulation/TurnManager.h"
|
|
#include "ps/scripting/JSMap.h"
|
|
#include "simulation/ScriptObject.h"
|
|
|
|
class CGame;
|
|
|
|
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<CNetServer>
|
|
{
|
|
private:
|
|
typedef std::map<int, CNetServerSession *> SessionMap;
|
|
|
|
/*
|
|
Every connected session is in m_Sessions as soon as the Handshake and
|
|
Authentication stages are complete.
|
|
*/
|
|
SessionMap m_Sessions;
|
|
CJSMap<SessionMap> 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 <CNetServerSession *> m_Observers;
|
|
|
|
ENetServerState m_ServerState;
|
|
|
|
CGame *m_pGame;
|
|
CGameAttributes *m_pGameAttributes;
|
|
|
|
uint m_MaxObservers;
|
|
int m_LastSessionID;
|
|
|
|
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();
|
|
|
|
// Synchronization object for batches
|
|
CMutex m_Mutex;
|
|
|
|
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(const CStrW& from, const CStrW& message);
|
|
void OnClientConnect(CNetServerSession *pSession);
|
|
void OnClientDisconnect(CNetServerSession *pSession);
|
|
|
|
// OVERRIDES FROM CServerSocket
|
|
virtual void OnAccept(const CSocketAddress &);
|
|
|
|
// OVERRIDES FROM CTurnManager
|
|
virtual bool NewTurnReady();
|
|
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(const CStr& password)
|
|
{ m_Password=password; }
|
|
|
|
inline const CStrW& GetServerPlayerName()
|
|
{ return m_ServerPlayerName; }
|
|
|
|
inline ENetServerState GetServerState()
|
|
{ return m_ServerState; }
|
|
|
|
int StartGame();
|
|
|
|
void Broadcast(CNetMessage *);
|
|
};
|
|
|
|
extern CNetServer *g_NetServer;
|
|
|
|
#endif // INCLUDED_NETWORK_SERVER
|