Changeset View
Changeset View
Standalone View
Standalone View
source/ps/Replay.cpp
Show First 20 Lines • Show All 177 Lines • ▼ Show 20 Lines | void CReplayPlayer::Replay(const bool serializationtest, const int rejointestturn, const bool ooslog, const bool testHashFull, const bool testHashQuick) | ||||
g_ProfileViewer.AddRootTable(g_ScriptStatsTable); | g_ProfileViewer.AddRootTable(g_ScriptStatsTable); | ||||
const int runtimeSize = 384 * 1024 * 1024; | const int runtimeSize = 384 * 1024 * 1024; | ||||
const int heapGrowthBytesGCTrigger = 20 * 1024 * 1024; | const int heapGrowthBytesGCTrigger = 20 * 1024 * 1024; | ||||
g_ScriptRuntime = ScriptInterface::CreateRuntime(shared_ptr<ScriptRuntime>(), runtimeSize, heapGrowthBytesGCTrigger); | g_ScriptRuntime = ScriptInterface::CreateRuntime(shared_ptr<ScriptRuntime>(), runtimeSize, heapGrowthBytesGCTrigger); | ||||
Mod::CacheEnabledModVersions(g_ScriptRuntime); | Mod::CacheEnabledModVersions(g_ScriptRuntime); | ||||
g_Game = new CGame(true, false); | CGame::InitGame(true, false); | ||||
if (serializationtest) | if (serializationtest) | ||||
g_Game->GetSimulation2()->EnableSerializationTest(); | CGame::GetGame()->GetSimulation2()->EnableSerializationTest(); | ||||
if (rejointestturn > 0) | if (rejointestturn > 0) | ||||
g_Game->GetSimulation2()->EnableRejoinTest(rejointestturn); | CGame::GetGame()->GetSimulation2()->EnableRejoinTest(rejointestturn); | ||||
if (ooslog) | if (ooslog) | ||||
g_Game->GetSimulation2()->EnableOOSLog(); | CGame::GetGame()->GetSimulation2()->EnableOOSLog(); | ||||
// Need some stuff for terrain movement costs: | // Need some stuff for terrain movement costs: | ||||
// (TODO: this ought to be independent of any graphics code) | // (TODO: this ought to be independent of any graphics code) | ||||
new CTerrainTextureManager; | new CTerrainTextureManager; | ||||
g_TexMan.LoadTerrainTextures(); | g_TexMan.LoadTerrainTextures(); | ||||
// Initialise h_mgr so it doesn't crash when emitting sounds | // Initialise h_mgr so it doesn't crash when emitting sounds | ||||
h_mgr_init(); | h_mgr_init(); | ||||
std::vector<SimulationCommand> commands; | std::vector<SimulationCommand> commands; | ||||
u32 turn = 0; | u32 turn = 0; | ||||
u32 turnLength = 0; | u32 turnLength = 0; | ||||
{ | { | ||||
JSContext* cx = g_Game->GetSimulation2()->GetScriptInterface().GetContext(); | JSContext* cx = CGame::GetGame()->GetSimulation2()->GetScriptInterface().GetContext(); | ||||
JSAutoRequest rq(cx); | JSAutoRequest rq(cx); | ||||
std::string type; | std::string type; | ||||
while ((*m_Stream >> type).good()) | while ((*m_Stream >> type).good()) | ||||
{ | { | ||||
if (type == "start") | if (type == "start") | ||||
{ | { | ||||
std::string line; | std::string line; | ||||
std::getline(*m_Stream, line); | std::getline(*m_Stream, line); | ||||
JS::RootedValue attribs(cx); | JS::RootedValue attribs(cx); | ||||
ENSURE(g_Game->GetSimulation2()->GetScriptInterface().ParseJSON(line, &attribs)); | ENSURE(CGame::GetGame()->GetSimulation2()->GetScriptInterface().ParseJSON(line, &attribs)); | ||||
CheckReplayMods(g_Game->GetSimulation2()->GetScriptInterface(), attribs); | CheckReplayMods(CGame::GetGame()->GetSimulation2()->GetScriptInterface(), attribs); | ||||
g_Game->StartGame(&attribs, ""); | CGame::GetGame()->StartGame(&attribs, ""); | ||||
// TODO: Non progressive load can fail - need a decent way to handle this | // TODO: Non progressive load can fail - need a decent way to handle this | ||||
LDR_NonprogressiveLoad(); | LDR_NonprogressiveLoad(); | ||||
PSRETURN ret = g_Game->ReallyStartGame(); | PSRETURN ret = CGame::GetGame()->ReallyStartGame(); | ||||
ENSURE(ret == PSRETURN_OK); | ENSURE(ret == PSRETURN_OK); | ||||
} | } | ||||
else if (type == "turn") | else if (type == "turn") | ||||
{ | { | ||||
*m_Stream >> turn >> turnLength; | *m_Stream >> turn >> turnLength; | ||||
debug_printf("Turn %u (%u)...\n", turn, turnLength); | debug_printf("Turn %u (%u)...\n", turn, turnLength); | ||||
} | } | ||||
else if (type == "cmd") | else if (type == "cmd") | ||||
{ | { | ||||
player_id_t player; | player_id_t player; | ||||
*m_Stream >> player; | *m_Stream >> player; | ||||
std::string line; | std::string line; | ||||
std::getline(*m_Stream, line); | std::getline(*m_Stream, line); | ||||
JS::RootedValue data(cx); | JS::RootedValue data(cx); | ||||
g_Game->GetSimulation2()->GetScriptInterface().ParseJSON(line, &data); | CGame::GetGame()->GetSimulation2()->GetScriptInterface().ParseJSON(line, &data); | ||||
g_Game->GetSimulation2()->GetScriptInterface().FreezeObject(data, true); | CGame::GetGame()->GetSimulation2()->GetScriptInterface().FreezeObject(data, true); | ||||
commands.emplace_back(SimulationCommand(player, cx, data)); | commands.emplace_back(SimulationCommand(player, cx, data)); | ||||
} | } | ||||
else if (type == "hash" || type == "hash-quick") | else if (type == "hash" || type == "hash-quick") | ||||
{ | { | ||||
std::string replayHash; | std::string replayHash; | ||||
*m_Stream >> replayHash; | *m_Stream >> replayHash; | ||||
TestHash(type, replayHash, testHashFull, testHashQuick); | TestHash(type, replayHash, testHashFull, testHashQuick); | ||||
} | } | ||||
else if (type == "end") | else if (type == "end") | ||||
{ | { | ||||
{ | { | ||||
g_Profiler2.RecordFrameStart(); | g_Profiler2.RecordFrameStart(); | ||||
PROFILE2("frame"); | PROFILE2("frame"); | ||||
g_Profiler2.IncrementFrameNumber(); | g_Profiler2.IncrementFrameNumber(); | ||||
PROFILE2_ATTR("%d", g_Profiler2.GetFrameNumber()); | PROFILE2_ATTR("%d", g_Profiler2.GetFrameNumber()); | ||||
g_Game->GetSimulation2()->Update(turnLength, commands); | CGame::GetGame()->GetSimulation2()->Update(turnLength, commands); | ||||
commands.clear(); | commands.clear(); | ||||
} | } | ||||
g_Profiler.Frame(); | g_Profiler.Frame(); | ||||
if (turn % PROFILE_TURN_INTERVAL == 0) | if (turn % PROFILE_TURN_INTERVAL == 0) | ||||
g_ProfileViewer.SaveToFile(); | g_ProfileViewer.SaveToFile(); | ||||
} | } | ||||
else | else | ||||
debug_printf("Unrecognised replay token %s\n", type.c_str()); | debug_printf("Unrecognised replay token %s\n", type.c_str()); | ||||
} | } | ||||
} | } | ||||
SAFE_DELETE(m_Stream); | SAFE_DELETE(m_Stream); | ||||
g_Profiler2.SaveToFile(); | g_Profiler2.SaveToFile(); | ||||
std::string hash; | std::string hash; | ||||
bool ok = g_Game->GetSimulation2()->ComputeStateHash(hash, false); | bool ok = CGame::GetGame()->GetSimulation2()->ComputeStateHash(hash, false); | ||||
ENSURE(ok); | ENSURE(ok); | ||||
debug_printf("# Final state: %s\n", Hexify(hash).c_str()); | debug_printf("# Final state: %s\n", Hexify(hash).c_str()); | ||||
timer_DisplayClientTotals(); | timer_DisplayClientTotals(); | ||||
SAFE_DELETE(g_Game); | CGame::DeInitGame(); | ||||
// Must be explicitly destructed here to avoid callbacks from the JSAPI trying to use g_Profiler2 when | // Must be explicitly destructed here to avoid callbacks from the JSAPI trying to use g_Profiler2 when | ||||
// it's already destructed. | // it's already destructed. | ||||
g_ScriptRuntime.reset(); | g_ScriptRuntime.reset(); | ||||
// Clean up | // Clean up | ||||
delete &g_TexMan; | delete &g_TexMan; | ||||
delete &g_Profiler; | delete &g_Profiler; | ||||
delete &g_ProfileViewer; | delete &g_ProfileViewer; | ||||
SAFE_DELETE(g_ScriptStatsTable); | SAFE_DELETE(g_ScriptStatsTable); | ||||
} | } | ||||
void CReplayPlayer::TestHash(const std::string& hashType, const std::string& replayHash, const bool testHashFull, const bool testHashQuick) | void CReplayPlayer::TestHash(const std::string& hashType, const std::string& replayHash, const bool testHashFull, const bool testHashQuick) | ||||
{ | { | ||||
bool quick = (hashType == "hash-quick"); | bool quick = (hashType == "hash-quick"); | ||||
if ((quick && !testHashQuick) || (!quick && !testHashFull)) | if ((quick && !testHashQuick) || (!quick && !testHashFull)) | ||||
return; | return; | ||||
std::string hash; | std::string hash; | ||||
ENSURE(g_Game->GetSimulation2()->ComputeStateHash(hash, quick)); | ENSURE(CGame::GetGame()->GetSimulation2()->ComputeStateHash(hash, quick)); | ||||
std::string hexHash = Hexify(hash); | std::string hexHash = Hexify(hash); | ||||
if (hexHash == replayHash) | if (hexHash == replayHash) | ||||
debug_printf("%s ok (%s)\n", hashType.c_str(), hexHash.c_str()); | debug_printf("%s ok (%s)\n", hashType.c_str(), hexHash.c_str()); | ||||
else | else | ||||
debug_printf("%s MISMATCH (%s != %s)\n", hashType.c_str(), hexHash.c_str(), replayHash.c_str()); | debug_printf("%s MISMATCH (%s != %s)\n", hashType.c_str(), hexHash.c_str(), replayHash.c_str()); | ||||
} | } |
Wildfire Games · Phabricator