1
0
forked from 0ad/0ad

Fix mod check of non-visual replays and allow conversion of a vector of vectors of strings via ScriptConversions

Reviewed by: elexis
Fixes #5044
Differential Revision: https://code.wildfiregames.com/D1316
This was SVN commit r21603.
This commit is contained in:
Imarok 2018-03-22 15:26:27 +00:00
parent ee9e677084
commit d6ae354158
3 changed files with 50 additions and 11 deletions

View File

@ -125,6 +125,47 @@ void CReplayPlayer::Load(const OsPath& path)
ENSURE(m_Stream->good());
}
CStr CReplayPlayer::ModListToString(const std::vector<std::vector<CStr>>& list) const
{
CStr text;
for (const std::vector<CStr>& mod : list)
text += mod[0] + " (" + mod[1] + ")\n";
return text;
}
void CReplayPlayer::CheckReplayMods(const ScriptInterface& scriptInterface, JS::HandleValue attribs) const
{
JSContext* cx = scriptInterface.GetContext();
JSAutoRequest rq(cx);
std::vector<std::vector<CStr>> replayMods;
scriptInterface.GetProperty(attribs, "mods", replayMods);
std::vector<std::vector<CStr>> enabledMods;
JS::RootedValue enabledModsJS(cx, Mod::GetLoadedModsWithVersions(scriptInterface));
scriptInterface.FromJSVal(cx, enabledModsJS, enabledMods);
CStr warn;
if (replayMods.size() != enabledMods.size())
warn = "The number of enabled mods does not match the mods of the replay.";
else
for (size_t i = 0; i < replayMods.size(); ++i)
{
if (replayMods[i][0] != enabledMods[i][0])
{
warn = "The enabled mods don't match the mods of the replay.";
break;
}
else if (replayMods[i][1] != enabledMods[i][1])
{
warn = "The mod '" + replayMods[i][0] + "' with version '" + replayMods[i][1] + "' is required by the replay file, but version '" + enabledMods[i][1] + "' is present!";
break;
}
}
if (!warn.empty())
LOGWARNING("%s\nThe mods of the replay are:\n%s\nThese mods are enabled:\n%s", warn, ModListToString(replayMods), ModListToString(enabledMods));
}
void CReplayPlayer::Replay(bool serializationtest, int rejointestturn, bool ooslog)
{
ENSURE(m_Stream);
@ -162,6 +203,7 @@ void CReplayPlayer::Replay(bool serializationtest, int rejointestturn, bool oosl
JSContext* cx = g_Game->GetSimulation2()->GetScriptInterface().GetContext();
JSAutoRequest rq(cx);
std::string type;
while ((*m_Stream >> type).good())
{
if (type == "start")
@ -171,16 +213,7 @@ void CReplayPlayer::Replay(bool serializationtest, int rejointestturn, bool oosl
JS::RootedValue attribs(cx);
ENSURE(g_Game->GetSimulation2()->GetScriptInterface().ParseJSON(line, &attribs));
std::vector<CStr> replayModList;
g_Game->GetSimulation2()->GetScriptInterface().GetProperty(attribs, "mods", replayModList);
for (const CStr& mod : replayModList)
if (mod != "user" && std::find(g_modsLoaded.begin(), g_modsLoaded.end(), mod) == g_modsLoaded.end())
LOGWARNING("The mod '%s' is required by the replay file, but wasn't passed as an argument!", mod);
for (const CStr& mod : g_modsLoaded)
if (mod != "user" && std::find(replayModList.begin(), replayModList.end(), mod) == replayModList.end())
LOGWARNING("The mod '%s' wasn't used when creating this replay file, but was passed as an argument!", mod);
CheckReplayMods(g_Game->GetSimulation2()->GetScriptInterface(), attribs);
g_Game->StartGame(&attribs, "");

View File

@ -18,6 +18,7 @@
#ifndef INCLUDED_REPLAY
#define INCLUDED_REPLAY
#include "ps/CStr.h"
#include "scriptinterface/ScriptTypes.h"
struct SimulationCommand;
@ -101,6 +102,8 @@ public:
private:
std::istream* m_Stream;
CStr ModListToString(const std::vector<std::vector<CStr>>& list) const;
void CheckReplayMods(const ScriptInterface& scriptInterface, JS::HandleValue attribs) const;
};
#endif // INCLUDED_REPLAY

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2017 Wildfire Games.
/* Copyright (C) 2018 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -307,7 +307,10 @@ JSVAL_VECTOR(u32)
JSVAL_VECTOR(u16)
JSVAL_VECTOR(std::string)
JSVAL_VECTOR(std::wstring)
JSVAL_VECTOR(std::vector<std::wstring>)
JSVAL_VECTOR(CStr8)
JSVAL_VECTOR(std::vector<CStr8>)
JSVAL_VECTOR(std::vector<std::string>)
class IComponent;