Line data Source code
1 : /* Copyright (C) 2021 Wildfire Games.
2 : * This file is part of 0 A.D.
3 : *
4 : * 0 A.D. is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 2 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * 0 A.D. is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 : */
17 :
18 : #include "precompiled.h"
19 :
20 : #include "JSInterface_SavedGame.h"
21 :
22 : #include "network/NetClient.h"
23 : #include "network/NetServer.h"
24 : #include "ps/CLogger.h"
25 : #include "ps/Game.h"
26 : #include "ps/SavedGame.h"
27 : #include "scriptinterface/FunctionWrapper.h"
28 : #include "scriptinterface/StructuredClone.h"
29 : #include "simulation2/Simulation2.h"
30 : #include "simulation2/system/TurnManager.h"
31 :
32 : namespace JSI_SavedGame
33 : {
34 0 : JS::Value GetSavedGames(const ScriptInterface& scriptInterface)
35 : {
36 0 : return SavedGames::GetSavedGames(scriptInterface);
37 : }
38 :
39 0 : bool DeleteSavedGame(const std::wstring& name)
40 : {
41 0 : return SavedGames::DeleteSavedGame(name);
42 : }
43 :
44 0 : void SaveGame(const ScriptRequest& rq, const std::wstring& filename, const std::wstring& description, JS::HandleValue GUIMetadata)
45 : {
46 0 : Script::StructuredClone GUIMetadataClone = Script::WriteStructuredClone(rq, GUIMetadata);
47 0 : if (SavedGames::Save(filename, description, *g_Game->GetSimulation2(), GUIMetadataClone) < 0)
48 0 : LOGERROR("Failed to save game");
49 0 : }
50 :
51 0 : void SaveGamePrefix(const ScriptRequest& rq, const std::wstring& prefix, const std::wstring& description, JS::HandleValue GUIMetadata)
52 : {
53 0 : Script::StructuredClone GUIMetadataClone = Script::WriteStructuredClone(rq, GUIMetadata);
54 0 : if (SavedGames::SavePrefix(prefix, description, *g_Game->GetSimulation2(), GUIMetadataClone) < 0)
55 0 : LOGERROR("Failed to save game");
56 0 : }
57 :
58 0 : void QuickSave(JS::HandleValue GUIMetadata)
59 : {
60 0 : if (g_NetServer || g_NetClient)
61 0 : LOGERROR("Can't store quicksave during multiplayer!");
62 0 : else if (g_Game)
63 0 : g_Game->GetTurnManager()->QuickSave(GUIMetadata);
64 : else
65 0 : LOGERROR("Can't store quicksave if game is not running!");
66 0 : }
67 :
68 0 : void QuickLoad()
69 : {
70 0 : if (g_NetServer || g_NetClient)
71 0 : LOGERROR("Can't load quicksave during multiplayer!");
72 0 : else if (g_Game)
73 0 : g_Game->GetTurnManager()->QuickLoad();
74 : else
75 0 : LOGERROR("Can't load quicksave if game is not running!");
76 0 : }
77 :
78 0 : JS::Value StartSavedGame(const ScriptInterface& scriptInterface, const std::wstring& name)
79 : {
80 : // We need to be careful with different compartments and contexts.
81 : // The GUI calls this function from the GUI context and expects the return value in the same context.
82 : // The game we start from here creates another context and expects data in this context.
83 :
84 0 : ScriptRequest rqGui(scriptInterface);
85 :
86 0 : ENSURE(!g_NetServer);
87 0 : ENSURE(!g_NetClient);
88 :
89 0 : ENSURE(!g_Game);
90 :
91 : // Load the saved game data from disk
92 0 : JS::RootedValue guiContextMetadata(rqGui.cx);
93 0 : std::string savedState;
94 0 : Status err = SavedGames::Load(name, scriptInterface, &guiContextMetadata, savedState);
95 0 : if (err < 0)
96 0 : return JS::UndefinedValue();
97 :
98 0 : g_Game = new CGame(true);
99 :
100 : {
101 0 : CSimulation2* sim = g_Game->GetSimulation2();
102 0 : ScriptRequest rqGame(sim->GetScriptInterface());
103 :
104 0 : JS::RootedValue gameContextMetadata(rqGame.cx, Script::CloneValueFromOtherCompartment(sim->GetScriptInterface(), scriptInterface, guiContextMetadata));
105 0 : JS::RootedValue gameInitAttributes(rqGame.cx);
106 0 : Script::GetProperty(rqGame, gameContextMetadata, "initAttributes", &gameInitAttributes);
107 :
108 : int playerID;
109 0 : Script::GetProperty(rqGame, gameContextMetadata, "playerID", playerID);
110 :
111 0 : g_Game->SetPlayerID(playerID);
112 0 : g_Game->StartGame(&gameInitAttributes, savedState);
113 : }
114 :
115 0 : return guiContextMetadata;
116 : }
117 :
118 0 : void ActivateRejoinTest()
119 : {
120 0 : if (!g_Game || !g_Game->GetSimulation2() || !g_Game->GetTurnManager())
121 0 : return;
122 0 : g_Game->GetSimulation2()->ActivateRejoinTest(g_Game->GetTurnManager()->GetCurrentTurn() + 1);
123 : }
124 :
125 12 : void RegisterScriptFunctions(const ScriptRequest& rq)
126 : {
127 12 : ScriptFunction::Register<&GetSavedGames>(rq, "GetSavedGames");
128 12 : ScriptFunction::Register<&DeleteSavedGame>(rq, "DeleteSavedGame");
129 12 : ScriptFunction::Register<&SaveGame>(rq, "SaveGame");
130 12 : ScriptFunction::Register<&SaveGamePrefix>(rq, "SaveGamePrefix");
131 12 : ScriptFunction::Register<&QuickSave>(rq, "QuickSave");
132 12 : ScriptFunction::Register<&QuickLoad>(rq, "QuickLoad");
133 12 : ScriptFunction::Register<&ActivateRejoinTest>(rq, "ActivateRejoinTest");
134 12 : ScriptFunction::Register<&StartSavedGame>(rq, "StartSavedGame");
135 12 : }
136 3 : }
|