Index: source/ps/Replay.cpp =================================================================== --- source/ps/Replay.cpp +++ source/ps/Replay.cpp @@ -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 @@ -72,7 +72,7 @@ JS::RootedValue mods(cx, Mod::GetLoadedModsWithVersions(m_ScriptInterface)); m_ScriptInterface.SetProperty(attribs, "mods", mods); - m_Directory = createDateIndexSubdirectory(VisualReplay::GetDirectoryName()); + m_Directory = createDateIndexSubdirectory(VisualReplay::GetDirectoryPath()); debug_printf("Writing replay to %s\n", m_Directory.string8().c_str()); m_Stream = new std::ofstream(OsString(m_Directory / L"commands.txt").c_str(), std::ofstream::out | std::ofstream::trunc); Index: source/ps/VisualReplay.h =================================================================== --- source/ps/VisualReplay.h +++ source/ps/VisualReplay.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 @@ -34,7 +34,22 @@ * @param scriptInterface - the ScriptInterface in which to create the return data. * @return OsPath the absolute file path */ -OsPath GetDirectoryName(); +OsPath GetDirectoryPath(); + +/** + * Returns the path to the replay cache file. + * + * @return OsPath the absolute file path + */ +OsPath GetCacheFilePath(); + +/** + * Returns the path to the temporary replay cache file used to + * always have a valid cache file in place even if bad things happen. + * + * @return OsPath the absolute file path + */ +OsPath GetTempCacheFilePath(); /** * Replays the commands.txt file in the given subdirectory visually. Index: source/ps/VisualReplay.cpp =================================================================== --- source/ps/VisualReplay.cpp +++ source/ps/VisualReplay.cpp @@ -40,22 +40,32 @@ */ const u8 minimumReplayDuration = 3; -static const OsPath tempCacheFileName = VisualReplay::GetDirectoryName() / L"replayCache_temp.json"; -static const OsPath cacheFileName = VisualReplay::GetDirectoryName() / L"replayCache.json"; - -OsPath VisualReplay::GetDirectoryName() +OsPath VisualReplay::GetDirectoryPath() { const Paths paths(g_args); return OsPath(paths.UserData() / "replays" / engine_version); } +OsPath VisualReplay::GetCacheFilePath() +{ + static const OsPath cacheFilePath = VisualReplay::GetDirectoryPath() / L"replayCache.json"; + return cacheFilePath; +} + +OsPath VisualReplay::GetTempCacheFilePath() +{ + static const OsPath tempCacheFilePath = VisualReplay::GetDirectoryPath() / L"replayCache_temp.json"; + return tempCacheFilePath; +} + + bool VisualReplay::StartVisualReplay(const OsPath& directory) { ENSURE(!g_NetServer); ENSURE(!g_NetClient); ENSURE(!g_Game); - const OsPath replayFile = VisualReplay::GetDirectoryName() / directory / L"commands.txt"; + const OsPath replayFile = VisualReplay::GetDirectoryPath() / directory / L"commands.txt"; if (!FileExists(replayFile)) return false; @@ -69,10 +79,10 @@ JSContext* cx = scriptInterface.GetContext(); JSAutoRequest rq(cx); - if (!FileExists(cacheFileName)) + if (!FileExists(GetCacheFilePath())) return false; - std::ifstream cacheStream(OsString(cacheFileName).c_str()); + std::ifstream cacheStream(OsString(GetCacheFilePath()).c_str()); CStr cacheStr((std::istreambuf_iterator(cacheStream)), std::istreambuf_iterator()); cacheStream.close(); @@ -85,7 +95,7 @@ } LOGWARNING("The replay cache file is corrupted, it will be deleted"); - wunlink(cacheFileName); + wunlink(GetCacheFilePath()); return false; } @@ -95,12 +105,12 @@ JSAutoRequest rq(cx); JS::RootedValue replaysRooted(cx, JS::ObjectValue(*replays)); - std::ofstream cacheStream(OsString(tempCacheFileName).c_str(), std::ofstream::out | std::ofstream::trunc); + std::ofstream cacheStream(OsString(GetTempCacheFilePath()).c_str(), std::ofstream::out | std::ofstream::trunc); cacheStream << scriptInterface.StringifyJSON(&replaysRooted); cacheStream.close(); - wunlink(cacheFileName); - if (wrename(tempCacheFileName, cacheFileName)) + wunlink(GetCacheFilePath()); + if (wrename(GetTempCacheFilePath(), GetCacheFilePath())) LOGERROR("Could not store the replay cache"); } @@ -139,7 +149,7 @@ JS::RootedObject replays(cx, JS_NewArrayObject(cx, 0)); DirectoryNames directories; - if (GetDirectoryEntries(GetDirectoryName(), nullptr, &directories) != INFO::OK) + if (GetDirectoryEntries(GetDirectoryPath(), nullptr, &directories) != INFO::OK) return replays; bool newReplays = false; @@ -155,7 +165,7 @@ // Don't return, because we want to save our progress break; - const OsPath replayFile = GetDirectoryName() / directory / L"commands.txt"; + const OsPath replayFile = GetDirectoryPath() / directory / L"commands.txt"; bool isNew = true; replayCacheMap::iterator it = fileList.find(directory); @@ -325,7 +335,7 @@ JS::Value VisualReplay::LoadReplayData(const ScriptInterface& scriptInterface, const OsPath& directory) { // The directory argument must not be constant, otherwise concatenating will fail - const OsPath replayFile = GetDirectoryName() / directory / L"commands.txt"; + const OsPath replayFile = GetDirectoryPath() / directory / L"commands.txt"; if (!FileExists(replayFile)) return JS::NullValue(); @@ -407,7 +417,7 @@ if (replayDirectory.empty()) return false; - const OsPath directory = GetDirectoryName() / replayDirectory; + const OsPath directory = GetDirectoryPath() / replayDirectory; return DirectoryExists(directory) && DeleteDirectory(directory) == INFO::OK; } @@ -420,7 +430,7 @@ pCxPrivate->pScriptInterface->Eval("({})", &attribs); // Return empty object if file doesn't exist - const OsPath replayFile = GetDirectoryName() / directoryName / L"commands.txt"; + const OsPath replayFile = GetDirectoryPath() / directoryName / L"commands.txt"; if (!FileExists(replayFile)) return attribs; @@ -483,7 +493,7 @@ bool VisualReplay::HasReplayMetadata(const OsPath& directoryName) { - const OsPath filePath(GetDirectoryName() / directoryName / L"metadata.json"); + const OsPath filePath(GetDirectoryPath() / directoryName / L"metadata.json"); if (!FileExists(filePath)) return false; @@ -503,7 +513,7 @@ JSAutoRequest rq(cx); JS::RootedValue metadata(cx); - std::ifstream* stream = new std::ifstream(OsString(GetDirectoryName() / directoryName / L"metadata.json").c_str()); + std::ifstream* stream = new std::ifstream(OsString(GetDirectoryPath() / directoryName / L"metadata.json").c_str()); ENSURE(stream->good()); CStr line; std::getline(*stream, line); Index: source/ps/scripting/JSInterface_VisualReplay.cpp =================================================================== --- source/ps/scripting/JSInterface_VisualReplay.cpp +++ source/ps/scripting/JSInterface_VisualReplay.cpp @@ -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 @@ -61,7 +61,7 @@ CStrW JSI_VisualReplay::GetReplayDirectoryName(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), const CStrW& directoryName) { - return wstring_from_utf8(OsPath(VisualReplay::GetDirectoryName() / directoryName).string8()); + return wstring_from_utf8(OsPath(VisualReplay::GetDirectoryPath() / directoryName).string8()); } void JSI_VisualReplay::RegisterScriptFunctions(const ScriptInterface& scriptInterface)