Changeset View
Changeset View
Standalone View
Standalone View
source/simulation2/system/TurnManager.cpp
/* Copyright (C) 2021 Wildfire Games. | /* Copyright (C) 2022 Wildfire Games. | ||||
* This file is part of 0 A.D. | * This file is part of 0 A.D. | ||||
* | * | ||||
* 0 A.D. is free software: you can redistribute it and/or modify | * 0 A.D. is free software: you can redistribute it and/or modify | ||||
* it under the terms of the GNU General Public License as published by | * it under the terms of the GNU General Public License as published by | ||||
* the Free Software Foundation, either version 2 of the License, or | * the Free Software Foundation, either version 2 of the License, or | ||||
* (at your option) any later version. | * (at your option) any later version. | ||||
* | * | ||||
* 0 A.D. is distributed in the hope that it will be useful, | * 0 A.D. is distributed in the hope that it will be useful, | ||||
Show All 11 Lines | |||||
#include "gui/GUIManager.h" | #include "gui/GUIManager.h" | ||||
#include "maths/MathUtil.h" | #include "maths/MathUtil.h" | ||||
#include "ps/Pyrogenesis.h" | #include "ps/Pyrogenesis.h" | ||||
#include "ps/Profile.h" | #include "ps/Profile.h" | ||||
#include "ps/CLogger.h" | #include "ps/CLogger.h" | ||||
#include "ps/Replay.h" | #include "ps/Replay.h" | ||||
#include "ps/Util.h" | #include "ps/Util.h" | ||||
#include "ps/SavedGame.h" | |||||
#include "scriptinterface/Object.h" | #include "scriptinterface/Object.h" | ||||
#include "simulation2/Simulation2.h" | #include "simulation2/Simulation2.h" | ||||
#if 0 | #if 0 | ||||
#define NETTURN_LOG(...) debug_printf(__VA_ARGS__) | #define NETTURN_LOG(...) debug_printf(__VA_ARGS__) | ||||
#else | #else | ||||
#define NETTURN_LOG(...) | #define NETTURN_LOG(...) | ||||
#endif | #endif | ||||
const CStr CTurnManager::EventNameSavegameLoaded = "SavegameLoaded"; | const CStr CTurnManager::EventNameSavegameLoaded = "SavegameLoaded"; | ||||
CTurnManager::CTurnManager(CSimulation2& simulation, u32 defaultTurnLength, u32 commandDelay, int clientId, IReplayLogger& replay) | CTurnManager::CTurnManager(CSimulation2& simulation, u32 defaultTurnLength, u32 commandDelay, int clientId, IReplayLogger& replay) | ||||
: m_Simulation2(simulation), m_CurrentTurn(0), m_CommandDelay(commandDelay), m_ReadyTurn(commandDelay - 1), m_TurnLength(defaultTurnLength), | : m_Simulation2(simulation), m_CurrentTurn(0), m_CommandDelay(commandDelay), m_ReadyTurn(commandDelay - 1), m_TurnLength(defaultTurnLength), | ||||
m_PlayerId(-1), m_ClientId(clientId), m_DeltaSimTime(0), m_Replay(replay), | m_PlayerId(-1), m_ClientId(clientId), m_DeltaSimTime(0), m_Replay(replay), | ||||
m_FinalTurn(std::numeric_limits<u32>::max()), m_TimeWarpNumTurns(0) | m_FinalTurn(std::numeric_limits<u32>::max()), m_TimeWarpNumTurns(0) | ||||
{ | { | ||||
ScriptRequest rq(m_Simulation2.GetScriptInterface()); | |||||
m_QuickSaveMetadata.init(rq.cx); | |||||
m_QueuedCommands.resize(1); | m_QueuedCommands.resize(1); | ||||
} | } | ||||
void CTurnManager::ResetState(u32 newCurrentTurn, u32 newReadyTurn) | void CTurnManager::ResetState(u32 newCurrentTurn, u32 newReadyTurn) | ||||
{ | { | ||||
m_CurrentTurn = newCurrentTurn; | m_CurrentTurn = newCurrentTurn; | ||||
m_ReadyTurn = newReadyTurn; | m_ReadyTurn = newReadyTurn; | ||||
m_DeltaSimTime = 0; | m_DeltaSimTime = 0; | ||||
▲ Show 20 Lines • Show All 222 Lines • ▼ Show 20 Lines | void CTurnManager::RewindTimeWarp() | ||||
// here, but this is simpler for now.) | // here, but this is simpler for now.) | ||||
ResetState(1, m_CommandDelay); | ResetState(1, m_CommandDelay); | ||||
} | } | ||||
void CTurnManager::QuickSave(JS::HandleValue GUIMetadata) | void CTurnManager::QuickSave(JS::HandleValue GUIMetadata) | ||||
{ | { | ||||
TIMER(L"QuickSave"); | TIMER(L"QuickSave"); | ||||
std::stringstream stream; | ScriptRequest rq(m_Simulation2.GetScriptInterface()); | ||||
if (!m_Simulation2.SerializeState(stream)) | Script::StructuredClone GUIMetadataClone = Script::WriteStructuredClone(rq, GUIMetadata); | ||||
{ | if (SavedGames::Save(L"quicksave", L"quicksave", m_Simulation2, GUIMetadataClone) < 0) | ||||
LOGERROR("Failed to quicksave game"); | LOGERROR("Failed to quicksave game"); | ||||
return; | |||||
} | } | ||||
m_QuickSaveState = stream.str(); | void CTurnManager::QuickLoad() | ||||
{ | |||||
TIMER(L"QuickLoad"); | |||||
ScriptRequest rq(m_Simulation2.GetScriptInterface()); | ScriptRequest rq(m_Simulation2.GetScriptInterface()); | ||||
m_QuickSaveMetadata.set(Script::DeepCopy(rq, GUIMetadata)); | // Load quicksave archive | ||||
// Freeze state to ensure that consectuvie loads don't modify the state | JS::RootedValue quickSaveMetadata(rq.cx); | ||||
Script::FreezeObject(rq, m_QuickSaveMetadata, true); | std::string savedState; | ||||
if (SavedGames::Load(L"quicksave", m_Simulation2.GetScriptInterface(), &quickSaveMetadata, savedState) < 0) | |||||
LOGMESSAGERENDER("Quicksaved game"); | { | ||||
LOGERROR("Failed to load save file"); | |||||
Stan: quicksave?
Bonus question, should those messages be translated since they are not technical… | |||||
Done Inline ActionsGood remark. I'm not familiar with the internationalization system though. Other than calling g_L10n.Translate(...), is there anything else I should add you reckon? sotirangelo: Good remark. I'm not familiar with the internationalization system though. Other than calling… | |||||
return; | |||||
} | } | ||||
void CTurnManager::QuickLoad() | // Get matchID of quicksave | ||||
{ | JS::RootedValue gameInitAttributes(rq.cx); | ||||
TIMER(L"QuickLoad"); | Script::GetProperty(rq, quickSaveMetadata, "initAttributes", &gameInitAttributes); | ||||
std::wstring savedMatchID; | |||||
Script::GetProperty(rq, gameInitAttributes, "matchID", savedMatchID); | |||||
// Get matchID of current game | |||||
std::wstring matchID; | |||||
JS::RootedValue gameMetadata(rq.cx, m_Simulation2.GetInitAttributes()); | |||||
Script::GetProperty(rq, gameMetadata, "matchID", matchID); | |||||
if (m_QuickSaveState.empty()) | // Compare IDs | ||||
if (matchID.compare(savedMatchID) != 0) | |||||
{ | { | ||||
LOGERROR("Cannot quickload game - no game was quicksaved"); | LOGERROR("Cannot quickload game - match not quicksaved"); | ||||
return; | return; | ||||
} | } | ||||
std::stringstream stream(m_QuickSaveState); | std::stringstream stream(savedState); | ||||
if (!m_Simulation2.DeserializeState(stream)) | if (!m_Simulation2.DeserializeState(stream)) | ||||
{ | { | ||||
LOGERROR("Failed to quickload game"); | LOGERROR("Failed to quickload game"); | ||||
return; | return; | ||||
} | } | ||||
// See RewindTimeWarp | // See RewindTimeWarp | ||||
ResetState(1, m_CommandDelay); | ResetState(1, m_CommandDelay); | ||||
if (!g_GUI) | if (!g_GUI) | ||||
return; | return; | ||||
ScriptRequest rq(m_Simulation2.GetScriptInterface()); | |||||
// Provide a copy, so that GUI components don't have to clone to get mutable objects | // Provide a copy, so that GUI components don't have to clone to get mutable objects | ||||
JS::RootedValue quickSaveMetadataClone(rq.cx, Script::DeepCopy(rq, m_QuickSaveMetadata)); | JS::RootedValue quickSaveMetadataClone(rq.cx, Script::DeepCopy(rq, quickSaveMetadata)); | ||||
JS::RootedValueArray<1> paramData(rq.cx); | JS::RootedValueArray<1> paramData(rq.cx); | ||||
paramData[0].set(quickSaveMetadataClone); | paramData[0].set(quickSaveMetadataClone); | ||||
g_GUI->SendEventToAll(EventNameSavegameLoaded, paramData); | g_GUI->SendEventToAll(EventNameSavegameLoaded, paramData); | ||||
LOGMESSAGERENDER("Quickloaded game"); | LOGMESSAGERENDER("Quickloaded game"); | ||||
} | } |
Wildfire Games · Phabricator
quicksave?
Bonus question, should those messages be translated since they are not technical errors but user facing ones