18 #include "precompiled.h"
46 #define NETTURN_LOG(args) debug_printf args
48 #define NETTURN_LOG(args)
51 static std::wstring
Hexify(
const std::string& s)
53 std::wstringstream str;
55 for (
size_t i = 0; i < s.size(); ++i)
56 str << std::setfill(L
'0') << std::setw(2) << (int)(
unsigned char)s[i];
61 m_Simulation2(simulation), m_CurrentTurn(0), m_ReadyTurn(1), m_TurnLength(defaultTurnLength), m_DeltaSimTime(0),
62 m_PlayerId(-1), m_ClientId(clientId), m_HasSyncError(false), m_Replay(replay),
128 maxTurns = std::max((
size_t)1, maxTurns);
130 for (
size_t i = 0; i < maxTurns; ++i)
152 PROFILE3(
"time warp serialization");
153 std::stringstream stream;
159 std::vector<SimulationCommand> commands;
162 commands.insert(commands.end(), it->second.begin(), it->second.end());
169 NETTURN_LOG((L
"Running %d cmds\n", commands.size()));
203 std::vector<SimulationCommand> commands;
206 commands.insert(commands.end(), it->second.begin(), it->second.end());
213 NETTURN_LOG((L
"Running %d cmds\n", commands.size()));
240 std::wstringstream msg;
241 msg << L
"Out of sync on turn " << turn << L
": expected hash " <<
Hexify(expectedHash) << L
"\n\n";
243 msg << L
"Dumping current state to " << path;
247 LOGERROR(L
"%ls", msg.str().c_str());
261 NETTURN_LOG((L
"AddCommand(client=%d player=%d turn=%d)\n", client, player, turn));
265 debug_warn(L
"Received command for invalid turn");
277 NETTURN_LOG((L
"FinishedAllCommands(%d, %d)\n", turn, turnLength));
326 std::stringstream stream;
330 LOGERROR(L
"Failed to quicksave game");
350 LOGERROR(L
"Cannot quickload game - no game was quicksaved");
358 LOGERROR(L
"Failed to quickload game");
393 NETTURN_LOG((L
"NotifyFinishedOwnCommands(%d)\n", turn));
396 CEndCommandBatchMessage msg;
417 CSyncCheckMessage msg;
449 #if 0 // this hurts performance and is only useful for verifying log replays
479 NETTURN_LOG((L
"NotifyFinishedClientCommands(client=%d, turn=%d)\n", client, turn));
508 CEndCommandBatchMessage msg;
527 u32 newest = std::numeric_limits<u32>::max();
530 if (it->second < newest)
537 if (it->first > newest)
541 std::string expected = it->second.begin()->second;
543 for (std::map<int, std::string>::iterator cit = it->second.begin(); cit != it->second.end(); ++cit)
545 NETTURN_LOG((L
"sync check %d: %d = %ls\n", it->first, cit->first,
Hexify(cit->second).c_str()));
546 if (cit->second != expected)
551 CSyncErrorMessage msg;
552 msg.m_Turn = it->first;
553 msg.m_HashExpected = expected;
567 NETTURN_LOG((L
"InitialiseClient(client=%d, turn=%d)\n", client, turn));
576 NETTURN_LOG((L
"UninitialiseClient(client=%d)\n", client));
std::map< u32, std::map< int, std::string > > m_ClientStateHashes
CNetTurnManager(CSimulation2 &simulation, u32 defaultTurnLength, int clientId, IReplayLogger &replay)
Construct for a given network session ID.
std::vector< u32 > m_SavedTurnLengths
CNetClientTurnManager(CSimulation2 &simulation, CNetClient &client, int clientId, IReplayLogger &replay)
void UninitialiseClient(int client)
Inform the turn manager that a previously-initialised client has left the game and will no longer be ...
#define UNUSED(param)
mark a function parameter as unused and avoid the corresponding compiler warning. ...
CNetLocalTurnManager(CSimulation2 &simulation, IReplayLogger &replay)
virtual void Turn(u32 n, u32 turnLength, const std::vector< SimulationCommand > &commands)=0
Run the given turn with the given collection of player commands.
const OsPath & psLogDir()
virtual void NotifyFinishedOwnCommands(u32 turn)
Called when this client has finished sending all its commands scheduled for the given turn...
bool DeserializeState(std::istream &stream)
std::list< std::string > m_TimeWarpStates
static void out(const wchar_t *fmt,...)
bool CallFunctionVoid(jsval val, const char *name)
Call the named property on the given object, with void return type and 0 arguments.
void EnableTimeWarpRecording(size_t numTurns)
Enables the recording of state snapshots every numTurns, which can be jumped back to via RewindTimeWa...
void Interpolate(float simFrameLength, float frameOffset, float realFrameLength)
const jsval & get() const
Returns the current value.
virtual void NotifyFinishedOwnCommands(u32 turn)
Called when this client has finished sending all its commands scheduled for the given turn...
float m_DeltaSimTime
Simulation time remaining until we ought to execute the next turn (as a negative value to add elapsed...
void NotifyFinishedClientUpdate(int client, u32 turn, const std::string &hash)
u32 m_ReadyTurn
The latest turn for which we have received all commands from all clients.
Replay log recorder interface.
std::string StringifyJSON(jsval obj, bool indent=true)
Stringify to a JSON string, UTF-8 encoded.
u32 GetSavedTurnLength(u32 turn)
Returns the turn length that was used for the given turn.
std::string m_QuickSaveState
virtual void NotifyFinishedUpdate(u32 turn)
Called when this client has finished a simulation update.
CScriptValRooted ParseJSON(const std::string &string_utf8)
Parse a UTF-8-encoded JSON string.
void Update(int turnLength)
Public API for simulation system.
CScriptVal GetSavedGameData()
Calls the current page's script function getSavedGameData() and returns the result.
bool WillUpdate(float simFrameLength)
Returns whether Update(simFrameLength, ...) will process at least one new turn.
bool SendMessage(const CNetMessage *message)
Send a message to the server.
virtual void NotifyFinishedUpdate(u32 turn)
Called when this client has finished a simulation update.
#define ENSURE(expr)
ensure the expression <expr> evaluates to non-zero.
void SetTurnLength(u32 msecs)
size_t m_TimeWarpNumTurns
u32 m_ReadyTurn
The latest turn for which we have received all commands from all clients.
#define NETTURN_LOG(args)
void InitialiseClient(int client, u32 turn)
Inform the turn manager of a new client who will be sending commands.
static const int DEFAULT_TURN_LENGTH_MP
Contains functions for managing saved game archives.
virtual void OnSyncError(u32 turn, const std::string &expectedHash)
Called when there has been an out-of-sync error.
void ResetState(u32 newCurrentTurn, u32 newReadyTurn)
Simulation command, typically received over the network in multiplayer games.
virtual void Hash(const std::string &hash, bool quick)=0
Optional hash of simulation state (for sync checking).
JSObject * GetScriptObject()
See CGUI::GetScriptObject; applies to the currently active page.
ScriptInterface & GetScriptInterface() const
static const int COMMAND_DELAY
Common network turn system (used by clients and offline games).
virtual void NotifyFinishedUpdate(u32 turn)=0
Called when this client has finished a simulation update.
void AddCommand(int client, int player, CScriptValRooted data, u32 turn)
Store a command to be executed at a given turn.
virtual void PostCommand(CScriptValRooted data)
Called by simulation code, to add a new command to be distributed to all clients and executed soon...
bool ComputeStateHash(std::string &outHash, bool quick)
virtual void PostCommand(CScriptValRooted data)
Called by simulation code, to add a new command to be distributed to all clients and executed soon...
void DisplayMessageBox(int width, int height, const CStrW &title, const CStrW &message)
Display a modal message box with an "OK" button.
std::deque< std::map< u32, std::vector< SimulationCommand > > > m_QueuedCommands
Commands queued at each turn (index 0 is for m_CurrentTurn+1)
bool SerializeState(std::ostream &stream)
bool Update(float simFrameLength, size_t maxTurns)
Advance the simulation by a certain time.
void FinishedAllCommands(u32 turn, u32 turnLength)
Called when all commands for a given turn have been received.
ScriptInterface & GetScriptInterface()
void NotifyFinishedClientCommands(int client, u32 turn)
#define TIMER(description)
Measures the time taken to execute code up until end of the current scope; displays it via debug_prin...
void SetPlayerID(int playerId)
Set the current user's player ID, which will be added into command messages.
void Interpolate(float simFrameLength, float realFrameLength)
Advance the graphics by a certain time.
static const int DEFAULT_TURN_LENGTH_SP
std::map< int, u32 > m_ClientsReady
CNetServerTurnManager(CNetServerWorker &server)
CNetServerWorker & m_NetServer
std::string m_QuickSaveMetadata
bool UpdateFastForward()
Advance the simulation by as much as possible.
void FlushDestroyedEntities()
Does the actual destruction of entities from DestroyEntity.
bool Broadcast(const CNetMessage *message)
Send a message to all clients who have completed the full connection process (i.e.
jsval get() const
Returns the current value (or JSVAL_VOID if uninitialised).
u32 m_CurrentTurn
The turn that we have most recently executed.
virtual void OnSimulationMessage(CSimulationMessage *msg)
Called by networking code when a simulation message is received.
virtual void NotifyFinishedOwnCommands(u32 turn)=0
Called when this client has finished sending all its commands scheduled for the given turn...
#define debug_warn(expr)
display the error dialog with the given text.
std::map< int, u32 > m_ClientsSimulated
virtual void OnSimulationMessage(CSimulationMessage *msg)
Called by networking code when a simulation message is received.
static std::wstring Hexify(const std::string &s)
void RewindTimeWarp()
Jumps back to the latest recorded state snapshot (if any).
bool DumpDebugState(std::ostream &stream)
Network server worker thread.
bool TurnNeedsFullHash(u32 turn)
Returns whether we should compute a complete state hash for the given turn, instead of a quick less-c...
T clamp(T value, T min, T max)
CSimulation2 & m_Simulation2
static std::string OsString(const OsPath &path)
Special message type for simulation commands.