From 37da3b008aff5360c463a0d33c9e5b8d9266b186 Mon Sep 17 00:00:00 2001 From: elexis Date: Mon, 1 May 2017 04:55:56 +0000 Subject: [PATCH] Translate the Out-Of-Sync error message and send it to the JS GUI for convenience and future extension. Add a hint that multiplayer games with AI are currently not supported. Differential Revision: https://code.wildfiregames.com/D105 Reviewed By: leper Refs #3858 This was SVN commit r19491. --- .../data/mods/public/gui/session/messages.js | 55 +++++++++++++++++++ .../data/mods/public/gui/session/session.xml | 4 ++ source/network/NetClientTurnManager.cpp | 31 +++++++---- .../simulation2/system/ReplayTurnManager.cpp | 19 ++----- source/simulation2/system/ReplayTurnManager.h | 2 - 5 files changed, 85 insertions(+), 26 deletions(-) diff --git a/binaries/data/mods/public/gui/session/messages.js b/binaries/data/mods/public/gui/session/messages.js index 4550b7f49e..7586e05eb8 100644 --- a/binaries/data/mods/public/gui/session/messages.js +++ b/binaries/data/mods/public/gui/session/messages.js @@ -44,6 +44,9 @@ var g_NetMessageTypes = { "netwarn": msg => { addNetworkWarning(msg); }, + "out-of-sync": msg => { + onNetworkOutOfSync(msg); + }, "players": msg => { handlePlayerAssignmentsMessage(msg); }, @@ -623,6 +626,58 @@ function handleClientsLoadingMessage(guids) loadingClientsText.caption = guids.map(guid => colorizePlayernameByGUID(guid)).join(translate(", ")); } +function onNetworkOutOfSync(msg) +{ + let txt = [ + sprintf(translate("Out-Of-Sync error on turn %(turn)s."), { + "turn": msg.turn + }), + + sprintf(translateWithContext("Out-Of-Sync", "Players: %(players)s"), { + "players": msg.players.join(translate(", ")) + }), + + msg.hash == msg.expectedHash ? + translateWithContext("Out-Of-Sync", "Your game state is identical to the hosts game state.") : + translateWithContext("Out-Of-Sync", "Your game state differs from the hosts game state."), + + "" + ]; + + if (msg.turn > 1 && g_GameAttributes.settings.PlayerData.some(pData => pData && pData.AI)) + txt.push(translateWithContext("Out-Of-Sync", "Rejoining Multiplayer games with AIs is not supported yet!")); + else + { + txt.push( + translateWithContext("Out-Of-Sync", "Ensure all players use the same mods."), + translateWithContext("Out-Of-Sync", 'Click on "Report Bugs" in the main menu to help fix this.'), + sprintf(translateWithContext("Out-Of-Sync", "Replay saved to %(filepath)s"), { + "filepath": escapeText(msg.path_replay) + }), + sprintf(translateWithContext("Out-Of-Sync", "Dumping current state to %(filepath)s"), { + "filepath": escapeText(msg.path_oos_dump) + }) + ); + } + + messageBox( + 600, 280, + txt.join("\n"), + translate("Out of Sync") + ); +} + +function onReplayOutOfSync() +{ + messageBox( + 500, 140, + translate("Out-Of-Sync error!") + "\n" + + // Translation: This is shown if replay is out of sync + translateWithContext("Out-Of-Sync", "The current game state is different from the original game state."), + translate("Out Of Sync") + ); +} + function handlePlayerAssignmentsMessage(message) { for (let guid in g_PlayerAssignments) diff --git a/binaries/data/mods/public/gui/session/session.xml b/binaries/data/mods/public/gui/session/session.xml index cf04976bd6..ff61c37d3e 100644 --- a/binaries/data/mods/public/gui/session/session.xml +++ b/binaries/data/mods/public/gui/session/session.xml @@ -30,6 +30,10 @@ onReplayFinished(); + + onReplayOutOfSync(); + + this.hidden = !this.hidden; diff --git a/source/network/NetClientTurnManager.cpp b/source/network/NetClientTurnManager.cpp index 7da290cc0e..ad79c31f57 100644 --- a/source/network/NetClientTurnManager.cpp +++ b/source/network/NetClientTurnManager.cpp @@ -122,18 +122,29 @@ void CNetClientTurnManager::OnSyncError(u32 turn, const CStr& expectedHash, cons hash = Hexify(hash); - std::stringstream msg; - msg << "Out of sync on turn " << turn; - + std::stringstream playerNamesString; + std::vector playerNamesStrings; + playerNamesStrings.reserve(playerNames.size()); for (size_t i = 0; i < playerNames.size(); ++i) - msg << (i == 0 ? "\nPlayers: " : ", ") << utf8_from_wstring(playerNames[i].m_Name); + { + CStr name = utf8_from_wstring(playerNames[i].m_Name); + playerNamesString << (i == 0 ? "" : ", ") << name; + playerNamesStrings.push_back(name); + } - msg << "\n\n" << "Your game state is " << (expectedHash == hash ? "identical to" : "different from") << " the hosts game state."; + LOGERROR("Out-Of-Sync on turn %d\nPlayers: %s\nDumping state to %s", turn, playerNamesString.str().c_str(), path.string8()); - msg << "\n\n" << "Dumping current state to " << CStr(path.string8()).EscapeToPrintableASCII(); + ScriptInterface& scriptInterface = m_NetClient.GetScriptInterface(); + JSContext* cx = scriptInterface.GetContext(); + JSAutoRequest rq(cx); - LOGERROR("%s", msg.str()); - - if (g_GUI) - g_GUI->DisplayMessageBox(600, 350, L"Sync error", wstring_from_utf8(msg.str())); + JS::RootedValue msg(cx); + scriptInterface.Eval("({ 'type':'out-of-sync' })", &msg); + scriptInterface.SetProperty(msg, "turn", turn); + scriptInterface.SetProperty(msg, "players", playerNamesStrings); + scriptInterface.SetProperty(msg, "expectedHash", expectedHash); + scriptInterface.SetProperty(msg, "hash", hash); + scriptInterface.SetProperty(msg, "path_oos_dump", path.string8()); + scriptInterface.SetProperty(msg, "path_replay", m_Replay.GetDirectory().string8()); + m_NetClient.PushGuiMessage(msg); } diff --git a/source/simulation2/system/ReplayTurnManager.cpp b/source/simulation2/system/ReplayTurnManager.cpp index b1ce296896..e525ee4847 100644 --- a/source/simulation2/system/ReplayTurnManager.cpp +++ b/source/simulation2/system/ReplayTurnManager.cpp @@ -77,7 +77,11 @@ void CReplayTurnManager::NotifyFinishedUpdate(u32 turn) hash = Hexify(hash); if (hash != expectedHash) - OnSyncError(turn); + { + m_HasSyncError = true; + LOGERROR("Replay out of sync on turn %d", turn); + g_GUI->SendEventToAll("ReplayOutOfSync"); + } } void CReplayTurnManager::DoTurn(u32 turn) @@ -100,16 +104,3 @@ void CReplayTurnManager::DoTurn(u32 turn) if (turn == m_FinalTurn) g_GUI->SendEventToAll("ReplayFinished"); } - -void CReplayTurnManager::OnSyncError(u32 turn) -{ - m_HasSyncError = true; - - std::stringstream msg; - msg << "Out of sync on turn " << turn << "\n\n" << "The current game state is different from the original game state."; - - LOGERROR("%s", msg.str()); - - if (g_GUI) - g_GUI->DisplayMessageBox(600, 350, L"Sync error", wstring_from_utf8(msg.str())); -} diff --git a/source/simulation2/system/ReplayTurnManager.h b/source/simulation2/system/ReplayTurnManager.h index 71ad11b7da..1c3fd74fef 100644 --- a/source/simulation2/system/ReplayTurnManager.h +++ b/source/simulation2/system/ReplayTurnManager.h @@ -41,8 +41,6 @@ private: void DoTurn(u32 turn); - void OnSyncError(u32 turn); - // Contains the commands of every player on each turn std::map>> m_ReplayCommands;