Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/source/ps/VisualReplay.cpp
/* Copyright (C) 2018 Wildfire Games. | /* Copyright (C) 2019 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 20 Lines • Show All 313 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
JS::Value VisualReplay::LoadReplayData(const ScriptInterface& scriptInterface, const OsPath& directory) | JS::Value VisualReplay::LoadReplayData(const ScriptInterface& scriptInterface, const OsPath& directory) | ||||
{ | { | ||||
// The directory argument must not be constant, otherwise concatenating will fail | // The directory argument must not be constant, otherwise concatenating will fail | ||||
const OsPath replayFile = GetDirectoryName() / directory / L"commands.txt"; | const OsPath replayFile = GetDirectoryName() / directory / L"commands.txt"; | ||||
if (!FileExists(replayFile)) | if (!FileExists(replayFile)) | ||||
return JSVAL_NULL; | return JS::NullValue(); | ||||
// Get file size and modification date | // Get file size and modification date | ||||
CFileInfo fileInfo; | CFileInfo fileInfo; | ||||
GetFileInfo(replayFile, &fileInfo); | GetFileInfo(replayFile, &fileInfo); | ||||
const off_t fileSize = fileInfo.Size(); | const off_t fileSize = fileInfo.Size(); | ||||
if (fileSize == 0) | if (fileSize == 0) | ||||
return JSVAL_NULL; | return JS::NullValue(); | ||||
std::ifstream* replayStream = new std::ifstream(OsString(replayFile).c_str()); | std::ifstream* replayStream = new std::ifstream(OsString(replayFile).c_str()); | ||||
CStr type; | CStr type; | ||||
if (!(*replayStream >> type).good()) | if (!(*replayStream >> type).good()) | ||||
{ | { | ||||
LOGERROR("Couldn't open %s.", replayFile.string8().c_str()); | LOGERROR("Couldn't open %s.", replayFile.string8().c_str()); | ||||
SAFE_DELETE(replayStream); | SAFE_DELETE(replayStream); | ||||
return JSVAL_NULL; | return JS::NullValue(); | ||||
} | } | ||||
if (type != "start") | if (type != "start") | ||||
{ | { | ||||
LOGWARNING("The replay %s doesn't begin with 'start'!", replayFile.string8().c_str()); | LOGWARNING("The replay %s doesn't begin with 'start'!", replayFile.string8().c_str()); | ||||
SAFE_DELETE(replayStream); | SAFE_DELETE(replayStream); | ||||
return JSVAL_NULL; | return JS::NullValue(); | ||||
} | } | ||||
// Parse header / first line | // Parse header / first line | ||||
CStr header; | CStr header; | ||||
std::getline(*replayStream, header); | std::getline(*replayStream, header); | ||||
JSContext* cx = scriptInterface.GetContext(); | JSContext* cx = scriptInterface.GetContext(); | ||||
JSAutoRequest rq(cx); | JSAutoRequest rq(cx); | ||||
JS::RootedValue attribs(cx); | JS::RootedValue attribs(cx); | ||||
if (!scriptInterface.ParseJSON(header, &attribs)) | if (!scriptInterface.ParseJSON(header, &attribs)) | ||||
{ | { | ||||
LOGERROR("Couldn't parse replay header of %s", replayFile.string8().c_str()); | LOGERROR("Couldn't parse replay header of %s", replayFile.string8().c_str()); | ||||
SAFE_DELETE(replayStream); | SAFE_DELETE(replayStream); | ||||
return JSVAL_NULL; | return JS::NullValue(); | ||||
} | } | ||||
// Ensure "turn" after header | // Ensure "turn" after header | ||||
if (!(*replayStream >> type).good() || type != "turn") | if (!(*replayStream >> type).good() || type != "turn") | ||||
{ | { | ||||
SAFE_DELETE(replayStream); | SAFE_DELETE(replayStream); | ||||
return JSVAL_NULL; // there are no turns at all | return JS::NullValue(); // there are no turns at all | ||||
} | } | ||||
// Don't process files of rejoined clients | // Don't process files of rejoined clients | ||||
u32 turn = 1; | u32 turn = 1; | ||||
*replayStream >> turn; | *replayStream >> turn; | ||||
if (turn != 0) | if (turn != 0) | ||||
{ | { | ||||
SAFE_DELETE(replayStream); | SAFE_DELETE(replayStream); | ||||
return JSVAL_NULL; | return JS::NullValue(); | ||||
} | } | ||||
int duration = getReplayDuration(replayStream, replayFile, fileSize); | int duration = getReplayDuration(replayStream, replayFile, fileSize); | ||||
SAFE_DELETE(replayStream); | SAFE_DELETE(replayStream); | ||||
// Ensure minimum duration | // Ensure minimum duration | ||||
if (duration < minimumReplayDuration) | if (duration < minimumReplayDuration) | ||||
return JSVAL_NULL; | return JS::NullValue(); | ||||
// Return the actual data | // Return the actual data | ||||
JS::RootedValue replayData(cx); | JS::RootedValue replayData(cx); | ||||
scriptInterface.Eval("({})", &replayData); | scriptInterface.Eval("({})", &replayData); | ||||
scriptInterface.SetProperty(replayData, "directory", directory.string()); | scriptInterface.SetProperty(replayData, "directory", directory.string()); | ||||
scriptInterface.SetProperty(replayData, "fileSize", (double)fileSize); | scriptInterface.SetProperty(replayData, "fileSize", (double)fileSize); | ||||
scriptInterface.SetProperty(replayData, "attribs", attribs); | scriptInterface.SetProperty(replayData, "attribs", attribs); | ||||
scriptInterface.SetProperty(replayData, "duration", duration); | scriptInterface.SetProperty(replayData, "duration", duration); | ||||
▲ Show 20 Lines • Show All 90 Lines • ▼ Show 20 Lines | bool VisualReplay::HasReplayMetadata(const OsPath& directoryName) | ||||
GetFileInfo(filePath, &fileInfo); | GetFileInfo(filePath, &fileInfo); | ||||
return fileInfo.Size() > 0; | return fileInfo.Size() > 0; | ||||
} | } | ||||
JS::Value VisualReplay::GetReplayMetadata(ScriptInterface::CxPrivate* pCxPrivate, const OsPath& directoryName) | JS::Value VisualReplay::GetReplayMetadata(ScriptInterface::CxPrivate* pCxPrivate, const OsPath& directoryName) | ||||
{ | { | ||||
if (!HasReplayMetadata(directoryName)) | if (!HasReplayMetadata(directoryName)) | ||||
return JSVAL_NULL; | return JS::NullValue(); | ||||
JSContext* cx = pCxPrivate->pScriptInterface->GetContext(); | JSContext* cx = pCxPrivate->pScriptInterface->GetContext(); | ||||
JSAutoRequest rq(cx); | JSAutoRequest rq(cx); | ||||
JS::RootedValue metadata(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(GetDirectoryName() / directoryName / L"metadata.json").c_str()); | ||||
ENSURE(stream->good()); | ENSURE(stream->good()); | ||||
CStr line; | CStr line; | ||||
std::getline(*stream, line); | std::getline(*stream, line); | ||||
stream->close(); | stream->close(); | ||||
SAFE_DELETE(stream); | SAFE_DELETE(stream); | ||||
pCxPrivate->pScriptInterface->ParseJSON(line, &metadata); | pCxPrivate->pScriptInterface->ParseJSON(line, &metadata); | ||||
return metadata; | return metadata; | ||||
} | } |
Wildfire Games · Phabricator