Index: ps/trunk/binaries/data/mods/public/gui/savegame/save.js =================================================================== --- ps/trunk/binaries/data/mods/public/gui/savegame/save.js +++ ps/trunk/binaries/data/mods/public/gui/savegame/save.js @@ -82,10 +82,3 @@ { Engine.PopGuiPage(); } - -// HACK: Engine.SaveGame* expects this function to be defined on the current page. -// That's why we have to pass the data to this page even if we don't need it. -function getSavedGameData() -{ - return g_SavedGameData; -} Index: ps/trunk/binaries/data/mods/public/gui/session/hotkeys/misc.xml =================================================================== --- ps/trunk/binaries/data/mods/public/gui/session/hotkeys/misc.xml +++ ps/trunk/binaries/data/mods/public/gui/session/hotkeys/misc.xml @@ -56,7 +56,7 @@ - Engine.QuickSave(); + Engine.QuickSave(getSavedGameData()); Index: ps/trunk/binaries/data/mods/public/gui/session/session.xml =================================================================== --- ps/trunk/binaries/data/mods/public/gui/session/session.xml +++ ps/trunk/binaries/data/mods/public/gui/session/session.xml @@ -15,6 +15,10 @@ onWindowResized(); + + restoreSavedGameData(arguments[0]); + + onSimulationUpdate(); Index: ps/trunk/source/gui/GUIManager.h =================================================================== --- ps/trunk/source/gui/GUIManager.h +++ ps/trunk/source/gui/GUIManager.h @@ -122,13 +122,6 @@ */ void UpdateResolution(); - /** - * Calls the current page's script function getSavedGameData() and returns the result. - */ - std::string GetSavedGameData(); - - void RestoreSavedGameData(const std::string& jsonData); - /** * Check if a template with this name exists */ Index: ps/trunk/source/gui/GUIManager.cpp =================================================================== --- ps/trunk/source/gui/GUIManager.cpp +++ ps/trunk/source/gui/GUIManager.cpp @@ -290,30 +290,6 @@ g_CursorName = g_DefaultCursor; } -std::string CGUIManager::GetSavedGameData() -{ - shared_ptr scriptInterface = top()->GetScriptInterface(); - JSContext* cx = scriptInterface->GetContext(); - JSAutoRequest rq(cx); - - JS::RootedValue data(cx); - JS::RootedValue global(cx, top()->GetGlobalObject()); - scriptInterface->CallFunction(global, "getSavedGameData", &data); - return scriptInterface->StringifyJSON(&data, false); -} - -void CGUIManager::RestoreSavedGameData(const std::string& jsonData) -{ - shared_ptr scriptInterface = top()->GetScriptInterface(); - JSContext* cx = scriptInterface->GetContext(); - JSAutoRequest rq(cx); - - JS::RootedValue global(cx, top()->GetGlobalObject()); - JS::RootedValue dataVal(cx); - scriptInterface->ParseJSON(jsonData, &dataVal); - scriptInterface->CallFunctionVoid(global, "restoreSavedGameData", dataVal); -} - InReaction CGUIManager::HandleEvent(const SDL_Event_* ev) { // We want scripts to have access to the raw input events, so they can do complex Index: ps/trunk/source/ps/scripting/JSInterface_SavedGame.h =================================================================== --- ps/trunk/source/ps/scripting/JSInterface_SavedGame.h +++ ps/trunk/source/ps/scripting/JSInterface_SavedGame.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 @@ -26,7 +26,7 @@ bool DeleteSavedGame(ScriptInterface::CxPrivate* pCxPrivate, const std::wstring& name); void SaveGame(ScriptInterface::CxPrivate* pCxPrivate, const std::wstring& filename, const std::wstring& description, JS::HandleValue GUIMetadata); void SaveGamePrefix(ScriptInterface::CxPrivate* pCxPrivate, const std::wstring& prefix, const std::wstring& description, JS::HandleValue GUIMetadata); - void QuickSave(ScriptInterface::CxPrivate* pCxPrivate); + void QuickSave(ScriptInterface::CxPrivate* pCxPrivate, JS::HandleValue GUIMetadata); void QuickLoad(ScriptInterface::CxPrivate* pCxPrivate); JS::Value StartSavedGame(ScriptInterface::CxPrivate* pCxPrivate, const std::wstring& name); Index: ps/trunk/source/ps/scripting/JSInterface_SavedGame.cpp =================================================================== --- ps/trunk/source/ps/scripting/JSInterface_SavedGame.cpp +++ ps/trunk/source/ps/scripting/JSInterface_SavedGame.cpp @@ -52,14 +52,20 @@ LOGERROR("Failed to save game"); } -void JSI_SavedGame::QuickSave(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) +void JSI_SavedGame::QuickSave(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), JS::HandleValue GUIMetadata) { - g_Game->GetTurnManager()->QuickSave(); + if (g_Game) + g_Game->GetTurnManager()->QuickSave(GUIMetadata); + else + LOGERROR("Can't store quicksave if game is not running!"); } void JSI_SavedGame::QuickLoad(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) { - g_Game->GetTurnManager()->QuickLoad(); + if (g_Game) + g_Game->GetTurnManager()->QuickLoad(); + else + LOGERROR("Can't load quicksave if game is not running!"); } JS::Value JSI_SavedGame::StartSavedGame(ScriptInterface::CxPrivate* pCxPrivate, const std::wstring& name) @@ -111,7 +117,7 @@ scriptInterface.RegisterFunction("DeleteSavedGame"); scriptInterface.RegisterFunction("SaveGame"); scriptInterface.RegisterFunction("SaveGamePrefix"); - scriptInterface.RegisterFunction("QuickSave"); + scriptInterface.RegisterFunction("QuickSave"); scriptInterface.RegisterFunction("QuickLoad"); scriptInterface.RegisterFunction("StartSavedGame"); } Index: ps/trunk/source/simulation2/system/TurnManager.h =================================================================== --- ps/trunk/source/simulation2/system/TurnManager.h +++ ps/trunk/source/simulation2/system/TurnManager.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 @@ -130,7 +130,7 @@ */ void RewindTimeWarp(); - void QuickSave(); + void QuickSave(JS::HandleValue GUIMetadata); void QuickLoad(); u32 GetCurrentTurn() { return m_CurrentTurn; } @@ -189,7 +189,7 @@ size_t m_TimeWarpNumTurns; // 0 if disabled std::list m_TimeWarpStates; std::string m_QuickSaveState; // TODO: should implement a proper disk-based quicksave system - std::string m_QuickSaveMetadata; + JS::PersistentRootedValue m_QuickSaveMetadata; }; #endif // INCLUDED_TURNMANAGER Index: ps/trunk/source/simulation2/system/TurnManager.cpp =================================================================== --- ps/trunk/source/simulation2/system/TurnManager.cpp +++ ps/trunk/source/simulation2/system/TurnManager.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 @@ -43,7 +43,8 @@ CTurnManager::CTurnManager(CSimulation2& simulation, u32 defaultTurnLength, int clientId, IReplayLogger& replay) : m_Simulation2(simulation), m_CurrentTurn(0), m_ReadyTurn(1), m_TurnLength(defaultTurnLength), m_PlayerId(-1), m_ClientId(clientId), m_DeltaSimTime(0), m_HasSyncError(false), m_Replay(replay), - m_FinalTurn(std::numeric_limits::max()), m_TimeWarpNumTurns(0) + m_FinalTurn(std::numeric_limits::max()), m_TimeWarpNumTurns(0), + m_QuickSaveMetadata(m_Simulation2.GetScriptInterface().GetContext()) { // When we are on turn n, we schedule new commands for n+2. // We know that all other clients have finished scheduling commands for n (else we couldn't have got here). @@ -290,7 +291,7 @@ ResetState(0, 1); } -void CTurnManager::QuickSave() +void CTurnManager::QuickSave(JS::HandleValue GUIMetadata) { TIMER(L"QuickSave"); @@ -302,13 +303,21 @@ } m_QuickSaveState = stream.str(); - if (g_GUI) - m_QuickSaveMetadata = g_GUI->GetSavedGameData(); + + JSContext* cx = m_Simulation2.GetScriptInterface().GetContext(); + JSAutoRequest rq(cx); + + if (JS_StructuredClone(cx, GUIMetadata, &m_QuickSaveMetadata, nullptr, nullptr)) + { + m_Simulation2.GetScriptInterface().FreezeObject(m_QuickSaveMetadata, true); + } else - m_QuickSaveMetadata = std::string(); + { + LOGERROR("Could not copy savegame GUI metadata"); + m_QuickSaveMetadata = JS::UndefinedValue(); + } LOGMESSAGERENDER("Quicksaved game"); - } void CTurnManager::QuickLoad() @@ -328,11 +337,18 @@ return; } - if (g_GUI && !m_QuickSaveMetadata.empty()) - g_GUI->RestoreSavedGameData(m_QuickSaveMetadata); - - LOGMESSAGERENDER("Quickloaded game"); - // See RewindTimeWarp ResetState(0, 1); + + if (!g_GUI) + return; + + JSContext* cx = m_Simulation2.GetScriptInterface().GetContext(); + JSAutoRequest rq(cx); + + JS::AutoValueArray<1> paramData(cx); + paramData[0].set(m_QuickSaveMetadata); + g_GUI->SendEventToAll("SavegameLoaded", paramData); + + LOGMESSAGERENDER("Quickloaded game"); }