Ticket #9: t0009_visualreplay_v2_16707.patch
File t0009_visualreplay_v2_16707.patch, 21.8 KB (added by , 9 years ago) |
---|
-
binaries/data/mods/public/gui/session/session.js
555 555 if (battleState) 556 556 global.music.setState(global.music.states[battleState]); 557 557 } 558 558 } 559 559 560 function onReplayFinished() 561 { 562 closeMenu(); 563 closeOpenDialogs(); 564 pauseGame(); 565 var btCaptions = ["Yes", "No"]; 566 var btCode = [leaveGame, resumeGame]; 567 messageBox(400, 200, "The replay has finished. Do you want to quit?", "Confirmation", 0, btCaptions, btCode); 568 } 569 560 570 /** 561 571 * updates a status bar on the GUI 562 572 * nameOfBar: name of the bar 563 573 * points: points to show 564 574 * maxPoints: max points -
binaries/data/mods/public/gui/session/session.xml
20 20 21 21 <action on="SimulationUpdate"> 22 22 onSimulationUpdate(); 23 23 </action> 24 24 25 <action on="ReplayFinished"> 26 onReplayFinished(); 27 </action> 28 25 29 <action on="Press"> 26 30 this.hidden = !this.hidden; 27 31 </action> 28 32 29 33 <!-- ================================ ================================ --> -
source/main.cpp
440 440 return; 441 441 442 442 // run non-visual simulation replay if requested 443 443 if (args.Has("replay")) 444 444 { 445 std::string replayFile = args.Get("replay"); 446 if (!FileExists(OsPath(replayFile))) 447 { 448 debug_printf("ERROR: The requested replay file '%s' does not exist!\n", replayFile.c_str()); 449 return; 450 } 445 451 Paths paths(args); 446 452 g_VFS = CreateVfs(20 * MiB); 447 453 g_VFS->Mount(L"cache/", paths.Cache(), VFS_MOUNT_ARCHIVABLE); 448 454 MountMods(paths, GetMods(args, INIT_MODS)); 449 455 450 456 { 451 457 CReplayPlayer replay; 452 replay.Load( args.Get("replay"));458 replay.Load(replayFile); 453 459 replay.Replay(args.Has("serializationtest"), args.Has("ooslog")); 454 460 } 455 461 456 462 g_VFS.reset(); 457 463 458 464 CXeromyces::Terminate(); 459 465 return; 460 466 } 461 467 468 // If visual replay file does not exist, quit before starting the renderer 469 if (args.Has("replay-visual")) 470 { 471 std::string replayFile = args.Get("replay-visual"); 472 if (!FileExists(OsPath(replayFile))) 473 { 474 debug_printf("ERROR: The requested replay file '%s' does not exist!\n", replayFile.c_str()); 475 return; 476 } 477 } 478 479 462 480 // run in archive-building mode if requested 463 481 if (args.Has("archivebuild")) 464 482 { 465 483 Paths paths(args); 466 484 -
source/network/NetTurnManager.cpp
29 29 #include "ps/Profile.h" 30 30 #include "ps/Pyrogenesis.h" 31 31 #include "ps/Replay.h" 32 32 #include "ps/SavedGame.h" 33 33 #include "scriptinterface/ScriptInterface.h" 34 #include "simulation2/helpers/Player.h" 34 35 #include "simulation2/Simulation2.h" 35 36 36 37 #include <sstream> 37 38 #include <fstream> 38 39 #include <iomanip> … … 227 228 return; 228 229 m_HasSyncError = true; 229 230 230 231 bool quick = !TurnNeedsFullHash(turn); 231 232 std::string hash; 232 bool ok = m_Simulation2.ComputeStateHash(hash, quick); 233 ENSURE(ok); 233 ENSURE(m_Simulation2.ComputeStateHash(hash, quick)); 234 234 235 235 OsPath path = psLogDir()/"oos_dump.txt"; 236 236 std::ofstream file (OsString(path).c_str(), std::ofstream::out | std::ofstream::trunc); 237 237 m_Simulation2.DumpDebugState(file); 238 238 file.close(); 239 239 240 hash = Hexify(hash); 241 const std::string& expectedHashHex = Hexify(expectedHash); 242 243 DisplayOOSError(turn, hash, expectedHashHex, false, &path); 244 } 245 246 void CNetTurnManager::DisplayOOSError(u32 turn, std::string& hash, const std::string& expectedHash, const bool isReplay, OsPath* path = NULL) 247 { 240 248 std::stringstream msg; 241 msg << "Out of sync on turn " << turn << ": expected hash " << Hexify(expectedHash) << "\n\n"; 242 msg << "Current state: turn " << m_CurrentTurn << ", hash " << Hexify(hash) << "\n\n"; 243 msg << "Dumping current state to " << utf8_from_wstring(path.string()); 249 msg << "Out of sync on turn " << turn << ": expected hash " << expectedHash << "\n\n"; 250 251 if ((expectedHash != hash) || (m_CurrentTurn != turn)) 252 msg << "Current state: turn " << m_CurrentTurn << ", hash " << hash << "\n\n"; 253 254 if (isReplay) 255 msg << "The current game state is different from the original game state.\n\n"; 256 else 257 { 258 if (expectedHash == hash) 259 msg << "Your game state is identical to the hosts game state.\n\n"; 260 else 261 msg << "Your game state is different from the hosts game state.\n\n"; 262 } 263 264 if (path != NULL) 265 msg << "Dumping current state to " << utf8_from_wstring(OsPath(*path).string()); 266 244 267 if (g_GUI) 245 268 g_GUI->DisplayMessageBox(600, 350, L"Sync error", wstring_from_utf8(msg.str())); 246 269 else 247 270 LOGERROR("%s", msg.str()); 248 271 } … … 320 343 void CNetTurnManager::QuickSave() 321 344 { 322 345 TIMER(L"QuickSave"); 323 346 324 347 std::stringstream stream; 325 bool ok = m_Simulation2.SerializeState(stream); 326 if (!ok) 348 if (!m_Simulation2.SerializeState(stream)) 327 349 { 328 350 LOGERROR("Failed to quicksave game"); 329 351 return; 330 352 } 331 353 … … 348 370 LOGERROR("Cannot quickload game - no game was quicksaved"); 349 371 return; 350 372 } 351 373 352 374 std::stringstream stream(m_QuickSaveState); 353 bool ok = m_Simulation2.DeserializeState(stream); 354 if (!ok) 375 if (!m_Simulation2.DeserializeState(stream)) 355 376 { 356 377 LOGERROR("Failed to quickload game"); 357 378 return; 358 379 } 359 380 … … 400 421 { 401 422 bool quick = !TurnNeedsFullHash(turn); 402 423 std::string hash; 403 424 { 404 425 PROFILE3("state hash check"); 405 bool ok = m_Simulation2.ComputeStateHash(hash, quick); 406 ENSURE(ok); 426 ENSURE(m_Simulation2.ComputeStateHash(hash, quick)); 407 427 } 408 428 409 429 NETTURN_LOG((L"NotifyFinishedUpdate(%d, %hs)\n", turn, Hexify(hash).c_str())); 410 430 411 431 m_Replay.Hash(hash, quick); … … 450 470 { 451 471 #if 0 // this hurts performance and is only useful for verifying log replays 452 472 std::string hash; 453 473 { 454 474 PROFILE3("state hash check"); 455 bool ok = m_Simulation2.ComputeStateHash(hash); 456 ENSURE(ok); 475 ENSURE(m_Simulation2.ComputeStateHash(hash)); 457 476 } 458 477 m_Replay.Hash(hash); 459 478 #endif 460 479 } 461 480 462 481 void CNetLocalTurnManager::OnSimulationMessage(CSimulationMessage* UNUSED(msg)) 463 482 { 464 483 debug_warn(L"This should never be called"); 465 484 } 466 485 486 CNetReplayTurnManager::CNetReplayTurnManager(CSimulation2& simulation, IReplayLogger& replay) : 487 CNetLocalTurnManager(simulation, replay) 488 { 489 } 490 491 void CNetReplayTurnManager::StoreReplayCommand(u32 turn, int player, const std::string& command) 492 { 493 m_ReplayCommands[turn][player].push_back(command); 494 } 495 496 void CNetReplayTurnManager::StoreReplayHash(u32 turn, const std::string& hash, bool quick) 497 { 498 m_ReplayHash[turn] = std::make_pair(hash, quick); 499 } 500 501 void CNetReplayTurnManager::StoreReplayTurnLength(u32 turn, u32 turnLength) 502 { 503 m_ReplayTurnLengths[turn] = turnLength; 504 505 // Initialize turn length 506 if (turn == 0) 507 m_TurnLength = m_ReplayTurnLengths[0]; 508 } 509 510 void CNetReplayTurnManager::StoreFinalReplayTurn(u32 turn) 511 { 512 m_FinalReplayTurn = turn; 513 } 514 void CNetReplayTurnManager::NotifyFinishedUpdate(u32 turn) 515 { 516 if (turn > m_FinalReplayTurn) 517 return; 518 519 debug_printf("Executing turn %d of %d\n", turn, m_FinalReplayTurn); 520 DoTurn(turn); 521 522 // Compare hash, if it exists in the replay 523 if (m_ReplayHash.count(turn) == 0) 524 return; 467 525 526 std::string expectedHash = m_ReplayHash[turn].first; 527 bool quickHash = m_ReplayHash[turn].second; 528 529 // Compute hash 530 std::string hash; 531 ENSURE(m_Simulation2.ComputeStateHash(hash, quickHash)); 532 hash = Hexify(hash); 468 533 534 if (hash != expectedHash) 535 DisplayOOSError(turn, hash, expectedHash, true); 536 } 537 538 void CNetReplayTurnManager::DoTurn(u32 turn) 539 { 540 // Save turn length 541 m_TurnLength = m_ReplayTurnLengths[turn]; 542 543 // Simulate commands for that turn 544 for (auto& command : m_ReplayCommands[turn]) 545 for (size_t i = 0; i < command.second.size(); ++i) 546 { 547 JS::RootedValue data(m_Simulation2.GetScriptInterface().GetContext()); 548 m_Simulation2.GetScriptInterface().ParseJSON(command.second[i], &data); 549 AddCommand(m_ClientId, command.first, data, m_CurrentTurn + 1); 550 } 551 } 469 552 470 553 CNetServerTurnManager::CNetServerTurnManager(CNetServerWorker& server) : 471 554 m_NetServer(server), m_ReadyTurn(1), m_TurnLength(DEFAULT_TURN_LENGTH_MP) 472 555 { 473 556 // The first turn we will actually execute is number 2, -
source/network/NetTurnManager.h
17 17 18 18 #ifndef INCLUDED_NETTURNMANAGER 19 19 #define INCLUDED_NETTURNMANAGER 20 20 21 21 #include "simulation2/helpers/SimulationCommand.h" 22 #include "lib/os_path.h" 22 23 23 24 #include <list> 24 25 #include <map> 26 #include <vector> 25 27 26 28 class CNetServerWorker; 27 29 class CNetClient; 28 30 class CSimulationMessage; 29 31 class CSimulation2; … … 106 108 * Called when there has been an out-of-sync error. 107 109 */ 108 110 virtual void OnSyncError(u32 turn, const std::string& expectedHash); 109 111 110 112 /** 113 * Shows a message box when an out of sync error has been detected in the session or visual replay. 114 */ 115 virtual void DisplayOOSError(u32 turn, std::string& hash, const std::string& expectedHash, const bool isReplay, OsPath* path); 116 117 /** 111 118 * Called by simulation code, to add a new command to be distributed to all clients and executed soon. 112 119 */ 113 120 virtual void PostCommand(JS::HandleValue data) = 0; 114 121 115 122 /** … … 187 194 std::list<std::string> m_TimeWarpStates; 188 195 std::string m_QuickSaveState; // TODO: should implement a proper disk-based quicksave system 189 196 std::string m_QuickSaveMetadata; 190 197 }; 191 198 199 192 200 /** 193 201 * Implementation of CNetTurnManager for network clients. 194 202 */ 195 203 class CNetClientTurnManager : public CNetTurnManager 196 204 { … … 231 239 232 240 virtual void NotifyFinishedUpdate(u32 turn); 233 241 }; 234 242 235 243 244 245 /** 246 * Implementation of CNetTurnManager for replay games. 247 */ 248 class CNetReplayTurnManager : public CNetLocalTurnManager 249 { 250 public: 251 CNetReplayTurnManager(CSimulation2& simulation, IReplayLogger& replay); 252 253 void StoreReplayCommand(u32 turn, int player, const std::string& command); 254 255 void StoreReplayTurnLength(u32 turn, u32 turnLength); 256 257 void StoreReplayHash(u32 turn, const std::string& hash, bool quick); 258 259 void StoreFinalReplayTurn(u32 turn); 260 261 262 protected: 263 virtual void NotifyFinishedUpdate(u32 turn); 264 265 void DoTurn(u32 turn); 266 267 // Contains the commands of every player on each turn 268 std::map<u32, std::map<int, std::vector<std::string> > > m_ReplayCommands; 269 270 // Contains the length of every turn 271 std::map<u32, u32> m_ReplayTurnLengths; 272 273 // Contains all replay hash values and weather or not the quick hash method was used 274 std::map<u32, std::pair<std::string, bool> > m_ReplayHash; 275 276 // The number of the last turn in the replay 277 u32 m_FinalReplayTurn; 278 279 }; 236 280 /** 237 281 * The server-side counterpart to CNetClientTurnManager. 238 282 * Records the turn state of each client, and sends turn advancement messages 239 283 * when all clients are ready. 240 284 * -
source/ps/Game.cpp
45 45 #include "renderer/WaterManager.h" 46 46 #include "scriptinterface/ScriptInterface.h" 47 47 #include "simulation2/Simulation2.h" 48 48 #include "simulation2/components/ICmpPlayer.h" 49 49 #include "simulation2/components/ICmpPlayerManager.h" 50 #include "simulation2/helpers/Player.h" 50 51 #include "soundmanager/ISoundManager.h" 51 52 52 53 #include "tools/atlas/GameInterface/GameLoop.h" 53 54 54 55 extern bool g_GameRestarted; 55 56 extern GameLoopState* g_AtlasGameLoop; 57 extern void kill_mainloop(); // from main.cpp 56 58 57 59 /** 58 60 * Globally accessible pointer to the CGame object. 59 61 **/ 60 62 CGame *g_Game=NULL; 61 63 62 64 /** 63 65 * Constructor 64 66 * 65 67 **/ 66 CGame::CGame(bool disableGraphics ):68 CGame::CGame(bool disableGraphics, bool replayLog): 67 69 m_World(new CWorld(this)), 68 70 m_Simulation2(new CSimulation2(&m_World->GetUnitManager(), g_ScriptRuntime, m_World->GetTerrain())), 69 71 m_GameView(disableGraphics ? NULL : new CGameView(this)), 70 72 m_GameStarted(false), 71 73 m_Paused(false), 72 74 m_SimRate(1.0f), 73 75 m_PlayerID(-1), 74 m_IsSavedGame(false) 76 m_IsSavedGame(false), 77 m_IsReplay(false), 78 m_ReplayStream(NULL) 75 79 { 76 m_ReplayLogger = new CReplayLogger(m_Simulation2->GetScriptInterface());77 80 // TODO: should use CDummyReplayLogger unless activated by cmd-line arg, perhaps? 81 if (replayLog) 82 m_ReplayLogger = new CReplayLogger(m_Simulation2->GetScriptInterface()); 83 else 84 m_ReplayLogger = new CDummyReplayLogger(); 78 85 79 86 // Need to set the CObjectManager references after various objects have 80 87 // been initialised, so do it here rather than via the initialisers above. 81 88 if (m_GameView) 82 89 m_World->GetUnitManager().SetObjectManager(m_GameView->GetObjectManager()); 83 90 84 91 m_TurnManager = new CNetLocalTurnManager(*m_Simulation2, GetReplayLogger()); // this will get replaced if we're a net server/client 85 92 86 93 m_Simulation2->LoadDefaultScripts(); 87 94 } 95 int CGame::LoadReplayData() 96 { 97 ENSURE(m_IsReplay); 98 ENSURE(!m_ReplayPath.empty()); 99 100 CNetReplayTurnManager* replayTurnMgr = static_cast<CNetReplayTurnManager*>(GetTurnManager()); 101 102 u32 currentTurn = 0; 103 std::string type; 104 while ((*m_ReplayStream >> type).good()) 105 { 106 if (type == "turn") 107 { 108 u32 turn = 0; 109 u32 turnLength = 0; 110 *m_ReplayStream >> turn >> turnLength; 111 ENSURE(turn == currentTurn); 112 replayTurnMgr->StoreReplayTurnLength(currentTurn, turnLength); 113 } 114 else if (type == "cmd") 115 { 116 player_id_t player; 117 *m_ReplayStream >> player; 118 119 std::string line; 120 std::getline(*m_ReplayStream, line); 121 replayTurnMgr->StoreReplayCommand(currentTurn, player, line); 122 } 123 else if (type == "hash" || type == "hash-quick") 124 { 125 bool quick = (type == "hash-quick"); 126 std::string replayHash; 127 *m_ReplayStream >> replayHash; 128 replayTurnMgr->StoreReplayHash(currentTurn, replayHash, quick); 129 } 130 else if (type == "end") 131 { 132 currentTurn++; 133 } 134 else 135 { 136 CancelLoad(L"Failed to load replay data (unrecognized content)"); 137 } 138 } 139 m_FinalReplayTurn = currentTurn; 140 replayTurnMgr->StoreFinalReplayTurn(currentTurn); 141 return 0; 142 } 143 bool CGame::StartReplay(const std::string& replayPath) 144 { 145 m_IsReplay = true; 146 ScriptInterface& scriptInterface = m_Simulation2->GetScriptInterface(); 88 147 148 SetTurnManager(new CNetReplayTurnManager(*m_Simulation2, GetReplayLogger())); 149 150 m_ReplayPath = replayPath; 151 m_ReplayStream = new std::ifstream(m_ReplayPath.c_str()); 152 153 std::string type; 154 ENSURE((*m_ReplayStream >> type).good() && type == "start"); 155 156 std::string line; 157 std::getline(*m_ReplayStream, line); 158 JS::RootedValue attribs(scriptInterface.GetContext()); 159 scriptInterface.ParseJSON(line, &attribs); 160 StartGame(&attribs, ""); 161 162 return true; 163 } 89 164 /** 90 165 * Destructor 91 166 * 92 167 **/ 93 168 CGame::~CGame() … … 99 174 delete m_TurnManager; 100 175 delete m_GameView; 101 176 delete m_Simulation2; 102 177 delete m_World; 103 178 delete m_ReplayLogger; 179 delete m_ReplayStream; 104 180 } 105 181 106 182 void CGame::SetTurnManager(CNetTurnManager* turnManager) 107 183 { 108 184 if (m_TurnManager) … … 174 250 RegMemFun(g_Renderer.GetSingletonPtr()->GetWaterManager(), &WaterManager::LoadWaterTextures, L"LoadWaterTextures", 80); 175 251 176 252 if (m_IsSavedGame) 177 253 RegMemFun(this, &CGame::LoadInitialState, L"Loading game", 1000); 178 254 255 if (m_IsReplay) 256 RegMemFun(this, &CGame::LoadReplayData, L"Loading replay data", 1000); 257 179 258 LDR_EndRegistering(); 180 259 } 181 260 182 261 int CGame::LoadInitialState() 183 262 { … … 261 340 int CGame::GetPlayerID() 262 341 { 263 342 return m_PlayerID; 264 343 } 265 344 266 void CGame::SetPlayerID( int playerID)345 void CGame::SetPlayerID(player_id_t playerID) 267 346 { 268 347 m_PlayerID = playerID; 269 348 if (m_TurnManager) 270 349 m_TurnManager->SetPlayerID(m_PlayerID); 271 350 } 272 351 273 352 void CGame::StartGame(JS::MutableHandleValue attribs, const std::string& savedState) 274 353 { 275 m_ReplayLogger->StartGame(attribs); 354 if (m_ReplayLogger != false) 355 m_ReplayLogger->StartGame(attribs); 356 276 357 RegisterInit(attribs, savedState); 277 358 } 278 359 279 360 // TODO: doInterpolate is optional because Atlas interpolates explicitly, 280 361 // so that it has more control over the update rate. The game might want to … … 308 389 { 309 390 { 310 391 PROFILE3("gui sim update"); 311 392 g_GUI->SendEventToAll("SimulationUpdate"); 312 393 } 394 if (m_IsReplay && m_TurnManager->GetCurrentTurn() == m_FinalReplayTurn - 1) 395 g_GUI->SendEventToAll("ReplayFinished"); 313 396 314 397 GetView()->GetLOSTexture().MakeDirty(); 315 398 } 316 399 317 400 if (CRenderer::IsInitialised()) … … 360 443 m_PlayerColors[i] = cmpPlayer->GetColor(); 361 444 } 362 445 } 363 446 364 447 365 CColor CGame::GetPlayerColor( int player) const448 CColor CGame::GetPlayerColor(player_id_t player) const 366 449 { 367 450 if (player < 0 || player >= (int)m_PlayerColors.size()) 368 451 return BrokenColor; 369 452 370 453 return m_PlayerColors[player]; -
source/ps/Game.h
19 19 #define INCLUDED_GAME 20 20 21 21 #include "ps/Errors.h" 22 22 #include <vector> 23 23 24 #include <map> 24 25 #include "scriptinterface/ScriptVal.h" 26 #include "simulation2/helpers/Player.h" 25 27 26 28 class CWorld; 27 29 class CSimulation2; 28 30 class CGameView; 29 31 class CNetTurnManager; … … 58 60 /** 59 61 * Timescale multiplier for simulation rate. 60 62 **/ 61 63 float m_SimRate; 62 64 63 int m_PlayerID;65 player_id_t m_PlayerID; 64 66 65 67 CNetTurnManager* m_TurnManager; 66 68 67 69 public: 68 CGame(bool disableGraphics = false );70 CGame(bool disableGraphics = false, bool replayLog = true); 69 71 ~CGame(); 70 72 71 73 /** 72 74 * the game is paused and no updates will be performed if true. 73 75 **/ 74 76 bool m_Paused; 75 77 76 78 void StartGame(JS::MutableHandleValue attribs, const std::string& savedState); 77 79 PSRETURN ReallyStartGame(); 78 80 81 bool StartReplay(const std::string& replayPath); 82 79 83 /** 80 84 * Periodic heartbeat that controls the process. performs all per-frame updates. 81 85 * Simulation update is called and game status update is called. 82 86 * 83 87 * @param deltaRealTime Elapsed real time since last beat/frame, in seconds. … … 88 92 bool Update(const double deltaRealTime, bool doInterpolate = true); 89 93 90 94 void Interpolate(float simFrameLength, float realFrameLength); 91 95 92 96 int GetPlayerID(); 93 void SetPlayerID( int playerID);97 void SetPlayerID(player_id_t playerID); 94 98 95 99 /** 96 100 * Retrieving player colors from scripts is slow, so this updates an 97 101 * internal cache of all players' colors. 98 102 * Call this just before rendering, so it will always have the latest 99 103 * colors. 100 104 */ 101 105 void CachePlayerColors(); 102 106 103 CColor GetPlayerColor( int player) const;107 CColor GetPlayerColor(player_id_t player) const; 104 108 105 109 /** 106 110 * Get m_GameStarted. 107 111 * 108 112 * @return bool the value of m_GameStarted. … … 169 173 std::vector<CColor> m_PlayerColors; 170 174 171 175 int LoadInitialState(); 172 176 std::string m_InitialSavedState; // valid between RegisterInit and LoadInitialState 173 177 bool m_IsSavedGame; // true if loading a saved game; false for a new game 178 179 int LoadReplayData(); 180 std::string m_ReplayPath; 181 bool m_IsReplay; 182 std::istream* m_ReplayStream; 183 u32 m_FinalReplayTurn; 174 184 }; 175 185 176 186 extern CGame *g_Game; 177 187 178 188 #endif -
source/ps/GameSetup/GameSetup.cpp
879 879 srand(time(NULL)); // NOTE: this rand should *not* be used for simulation! 880 880 } 881 881 882 882 bool Autostart(const CmdLineArgs& args); 883 883 884 // Returns true if and only if the user has intended to replay a file 885 bool VisualReplay(const std::string replayFile); 886 884 887 bool Init(const CmdLineArgs& args, int flags) 885 888 { 886 889 h_mgr_init(); 887 890 888 891 // Do this as soon as possible, because it chdirs … … 1071 1074 1072 1075 ogl_WarnIfError(); 1073 1076 1074 1077 try 1075 1078 { 1076 if (! Autostart(args))1079 if (!VisualReplay(args.Get("replay-visual")) && !Autostart(args)) 1077 1080 { 1078 1081 const bool setup_gui = ((flags & INIT_NO_GUI) == 0); 1079 1082 // We only want to display the splash screen at startup 1080 1083 shared_ptr<ScriptInterface> scriptInterface = g_GUI->GetScriptInterface(); 1081 1084 JSContext* cx = scriptInterface->GetContext(); … … 1468 1471 } 1469 1472 1470 1473 return true; 1471 1474 } 1472 1475 1476 bool VisualReplay(const std::string replayFile) 1477 { 1478 if (!FileExists(OsPath(replayFile))) 1479 return false; 1480 1481 g_Game = new CGame(false, false); 1482 g_Game->SetPlayerID(-1); 1483 g_Game->StartReplay(replayFile); 1484 1485 // TODO: Non progressive load can fail - need a decent way to handle this 1486 LDR_NonprogressiveLoad(); 1487 1488 PSRETURN ret = g_Game->ReallyStartGame(); 1489 ENSURE(ret == PSRETURN_OK); 1490 1491 ScriptInterface& scriptInterface = g_Game->GetSimulation2()->GetScriptInterface(); 1492 1493 InitPs(true, L"page_session.xml", &scriptInterface, JS::UndefinedHandleValue); 1494 return true; 1495 } 1496 1473 1497 void CancelLoad(const CStrW& message) 1474 1498 { 1475 1499 shared_ptr<ScriptInterface> pScriptInterface = g_GUI->GetActiveGUI()->GetScriptInterface(); 1476 1500 JSContext* cx = pScriptInterface->GetContext(); 1477 1501 JSAutoRequest rq(cx); -
source/ps/Replay.h
54 54 */ 55 55 class CDummyReplayLogger : public IReplayLogger 56 56 { 57 57 public: 58 58 virtual void StartGame(JS::MutableHandleValue UNUSED(attribs)) { } 59 virtual void Turn(u32 UNUSED(n), u32 UNUSED(turnLength), conststd::vector<SimulationCommand>& UNUSED(commands)) { }59 virtual void Turn(u32 UNUSED(n), u32 UNUSED(turnLength), std::vector<SimulationCommand>& UNUSED(commands)) { } 60 60 virtual void Hash(const std::string& UNUSED(hash), bool UNUSED(quick)) { } 61 61 }; 62 62 63 63 /** 64 64 * Implementation of IReplayLogger that saves data to a file in the logs directory.