Index: binaries/data/mods/public/gui/loading/loading.js =================================================================== --- binaries/data/mods/public/gui/loading/loading.js +++ binaries/data/mods/public/gui/loading/loading.js @@ -55,25 +55,28 @@ } Engine.GetGUIObjectByName("progressText").caption = ""; - Engine.GetGUIObjectByName("progressbar").caption = 0; + + let progressbar = Engine.GetGUIObjectByName("progressbar"); + progressbar.caption = 0; + progressbar.onGameLoadProgress = displayProgress; Engine.GetGUIObjectByName("quoteText").caption = translate(pickRandom(Engine.ReadFileLines(g_QuotesFile).filter(line => line))); } -function displayProgress() +function displayProgress(data) { // Make the progessbar finish a little early so that the user can actually see it finish - if (g_Progress >= 100) + if (data.progress >= 100) return; // Show 100 when it is really 99 - let progress = g_Progress + 1; + let progress = data.progress + 1; Engine.GetGUIObjectByName("progressbar").caption = progress; // display current progress Engine.GetGUIObjectByName("progressText").caption = progress + "%"; // Displays detailed loading info rather than a percent - // Engine.GetGUIObjectByName("progressText").caption = g_LoadDescription; // display current progess details + // Engine.GetGUIObjectByName("progressText").caption = data.description; // display current progess details // Keep curved right edge of progress bar in sync with the rest of the progress bar let middle = Engine.GetGUIObjectByName("progressbar"); Index: binaries/data/mods/public/gui/loading/loading.xml =================================================================== --- binaries/data/mods/public/gui/loading/loading.xml +++ binaries/data/mods/public/gui/loading/loading.xml @@ -21,7 +21,6 @@ > - displayProgress(); Index: binaries/data/mods/public/gui/session/messages.js =================================================================== --- binaries/data/mods/public/gui/session/messages.js +++ binaries/data/mods/public/gui/session/messages.js @@ -729,11 +729,13 @@ ); } -function onReplayOutOfSync() +function onReplayOutOfSync(msg) { messageBox( 500, 140, - translate("Out-Of-Sync error!") + "\n" + + sprintf(translate("Out-Of-Sync error on turn %(turn)s."), { + "turn": msg.turn + }) + "\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") Index: binaries/data/mods/public/gui/session/session.xml =================================================================== --- binaries/data/mods/public/gui/session/session.xml +++ binaries/data/mods/public/gui/session/session.xml @@ -24,7 +24,7 @@ - onReplayOutOfSync(); + onReplayOutOfSync(arguments[0]); Index: source/gui/CGUI.h =================================================================== --- source/gui/CGUI.h +++ source/gui/CGUI.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 Wildfire Games. +/* Copyright (C) 2019 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -98,6 +98,13 @@ void SendEventToAll(const CStr& EventName); /** + * Sends a specified script event with a given argument to every object. + * + * @param argument A JS::Value that further describes event data. + */ + void SendEventToAll(const CStr& EventName, JS::HandleValue argument); + + /** * Displays the whole GUI */ void Draw(); Index: source/gui/CGUI.cpp =================================================================== --- source/gui/CGUI.cpp +++ source/gui/CGUI.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2018 Wildfire Games. +/* Copyright (C) 2019 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -274,8 +274,13 @@ // (sending events here) wasn't converting to lower case, // leading to a similar problem. // now fixed; case is irrelevant since all are converted to lower. - GUI::RecurseObject(0, m_BaseObject, - &IGUIObject::ScriptEvent, EventName.LowerCase()); + + GUI::RecurseObject(0, m_BaseObject, &IGUIObject::ScriptEvent, EventName.LowerCase()); +} + +void CGUI::SendEventToAll(const CStr& EventName, JS::HandleValue argument) +{ + GUI::RecurseObject(0, m_BaseObject, &IGUIObject::ScriptEvent, EventName.LowerCase(), argument); } CGUI::CGUI(const shared_ptr& runtime) Index: source/gui/GUIManager.h =================================================================== --- source/gui/GUIManager.h +++ source/gui/GUIManager.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2018 Wildfire Games. +/* Copyright (C) 2019 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -116,6 +116,7 @@ * See CGUI::SendEventToAll; applies to the currently active page. */ void SendEventToAll(const CStr& eventName) const; + void SendEventToAll(const CStr& eventName, JS::HandleValue argument) const; /** * See CGUI::TickObjects; applies to @em all loaded pages. Index: source/gui/GUIManager.cpp =================================================================== --- source/gui/GUIManager.cpp +++ source/gui/GUIManager.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2018 Wildfire Games. +/* Copyright (C) 2019 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -373,6 +373,11 @@ top()->SendEventToAll(eventName); } +void CGUIManager::SendEventToAll(const CStr& eventName, JS::HandleValue argument) const +{ + top()->SendEventToAll(eventName, argument); +} + void CGUIManager::TickObjects() { PROFILE3("gui tick"); Index: source/gui/GUIutil.h =================================================================== --- source/gui/GUIutil.h +++ source/gui/GUIutil.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015 Wildfire Games. +/* Copyright (C) 2019 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -222,6 +222,7 @@ typedef void (IGUIObject::*void_Object_pFunction_argT)(const T& arg); typedef void (IGUIObject::*void_Object_pFunction_argRefT)(T& arg); typedef void (IGUIObject::*void_Object_pFunction)(); + typedef void (IGUIObject::*void_Object_pFunction_argTJS)(const T& arg, JS::HandleValue arg2); /** * If you want to call a IGUIObject-function @@ -257,7 +258,6 @@ (pObject->*pFunc)(Argument); - // Iterate children for (IGUIObject* const& obj : *pObject) RecurseObject(RR, obj, pFunc, Argument); } @@ -274,11 +274,21 @@ (pObject->*pFunc)(Argument); - // Iterate children for (IGUIObject* const& obj : *pObject) RecurseObject(RR, obj, pFunc, Argument); } + static void RecurseObject(int RR, IGUIObject* pObject, void_Object_pFunction_argTJS pFunc, const T& Argument1, JS::HandleValue Argument2) + { + if (CheckIfRestricted(RR, pObject)) + return; + + (pObject->*pFunc)(Argument1, Argument2); + + for (IGUIObject* const& obj : *pObject) + RecurseObject(RR, obj, pFunc, Argument1, Argument2); + } + /** * With no argument. * Index: source/ps/GameSetup/GameSetup.cpp =================================================================== --- source/ps/GameSetup/GameSetup.cpp +++ source/ps/GameSetup/GameSetup.cpp @@ -183,12 +183,16 @@ // display progress / description in loading screen void GUI_DisplayLoadProgress(int percent, const wchar_t* pending_task) { - g_GUI->GetActiveGUI()->GetScriptInterface()->SetGlobal("g_Progress", percent, true, false, true); - g_GUI->GetActiveGUI()->GetScriptInterface()->SetGlobal("g_LoadDescription", pending_task, true, false, true); - g_GUI->GetActiveGUI()->SendEventToAll("progress"); -} + const ScriptInterface& scriptInterface = *(g_GUI->GetActiveGUI()->GetScriptInterface()); + JSContext* cx = scriptInterface.GetContext(); + JSAutoRequest rq(cx); + JS::RootedValue eventData(cx, JS::ObjectValue(*JS_NewPlainObject(cx))); + scriptInterface.SetProperty(eventData, "progress", percent); + scriptInterface.SetProperty(eventData, "description", pending_task); + g_GUI->GetActiveGUI()->SendEventToAll("GameLoadProgress", eventData); +} void Render() { Index: source/simulation2/system/ReplayTurnManager.cpp =================================================================== --- source/simulation2/system/ReplayTurnManager.cpp +++ source/simulation2/system/ReplayTurnManager.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 Wildfire Games. +/* Copyright (C) 2019 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -76,12 +76,21 @@ ENSURE(m_Simulation2.ComputeStateHash(hash, quickHash)); hash = Hexify(hash); - if (hash != expectedHash) - { - m_HasSyncError = true; - LOGERROR("Replay out of sync on turn %d", turn); - g_GUI->SendEventToAll("ReplayOutOfSync"); - } + if (hash == expectedHash) + return; + + m_HasSyncError = true; + LOGERROR("Replay out of sync on turn %d", turn); + + const ScriptInterface& scriptInterface = m_Simulation2.GetScriptInterface(); + JSContext* cx = scriptInterface.GetContext(); + JSAutoRequest rq(cx); + + JS::RootedValue replayData(cx, JS::ObjectValue(*JS_NewPlainObject(cx))); + scriptInterface.SetProperty(replayData, "turn", turn); + scriptInterface.SetProperty(replayData, "hash", hash); + scriptInterface.SetProperty(replayData, "expectedHash", expectedHash); + g_GUI->SendEventToAll("ReplayOutOfSync", replayData); } void CReplayTurnManager::DoTurn(u32 turn)