From 44ec2e324e8e5e5dce3fb997d2983f0a5a01e9c2 Mon Sep 17 00:00:00 2001 From: elexis Date: Thu, 24 May 2018 18:08:56 +0000 Subject: [PATCH] Alpha 23 "lobby lag" release fix. Caches the loaded mod versions, so that GetEngineInfo doesn't read the zip and json files everytime and returns about 1000 times faster. Adds two missing includes. The lobby froze multiple times every few seconds on updateGameList(). The gamesetup page was slowed down with every stanza sent and the load savegame selection page was slowed down per savegame selection, proportional to the number of installed zipped mods. Introduced by: d5807cd59f and eca956a513 Differential Revision: https://code.wildfiregames.com/D1518 Reviewed By: wraitii Comments By: Imarok (in D1512, P121), leper (in the lobby) This was SVN commit r21823. --- source/ps/GameSetup/GameSetup.cpp | 3 +++ source/ps/GameSetup/GameSetup.h | 7 ++++++- source/ps/Mod.cpp | 30 +++++++++++++++++++++--------- source/ps/Mod.h | 10 ++++++++++ source/ps/Replay.cpp | 3 +++ 5 files changed, 43 insertions(+), 10 deletions(-) diff --git a/source/ps/GameSetup/GameSetup.cpp b/source/ps/GameSetup/GameSetup.cpp index 3712e98a59..255cac6f4a 100644 --- a/source/ps/GameSetup/GameSetup.cpp +++ b/source/ps/GameSetup/GameSetup.cpp @@ -80,6 +80,7 @@ #include "scriptinterface/ScriptInterface.h" #include "scriptinterface/ScriptStats.h" #include "scriptinterface/ScriptConversions.h" +#include "scriptinterface/ScriptRuntime.h" #include "simulation2/Simulation2.h" #include "lobby/IXmppClient.h" #include "soundmanager/scripting/JSInterface_Sound.h" @@ -922,6 +923,8 @@ bool Init(const CmdLineArgs& args, int flags) const int heapGrowthBytesGCTrigger = 20 * 1024 * 1024; g_ScriptRuntime = ScriptInterface::CreateRuntime(shared_ptr(), runtimeSize, heapGrowthBytesGCTrigger); + Mod::CacheEnabledModVersions(g_ScriptRuntime); + // Special command-line mode to dump the entity schemas instead of running the game. // (This must be done after loading VFS etc, but should be done before wasting time // on anything else.) diff --git a/source/ps/GameSetup/GameSetup.h b/source/ps/GameSetup/GameSetup.h index 54b9eca2d7..74debf2f23 100644 --- a/source/ps/GameSetup/GameSetup.h +++ b/source/ps/GameSetup/GameSetup.h @@ -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 @@ -79,6 +79,11 @@ extern void RenderCursor(bool RenderingState); class CmdLineArgs; class Paths; extern const std::vector& GetMods(const CmdLineArgs& args, int flags); + +/** + * Mounts all files of the given mods in the global VFS. + * Make sure to call CacheEnabledModVersions after every call to this. + */ extern void MountMods(const Paths& paths, const std::vector& mods); /** * Returns true if successful, false if mods changed and restart_engine was called. diff --git a/source/ps/Mod.cpp b/source/ps/Mod.cpp index 83e9eb7704..eea37a1d3e 100644 --- a/source/ps/Mod.cpp +++ b/source/ps/Mod.cpp @@ -28,9 +28,12 @@ #include "ps/GameSetup/GameSetup.h" #include "ps/GameSetup/Paths.h" #include "scriptinterface/ScriptInterface.h" +#include "scriptinterface/ScriptRuntime.h" std::vector g_modsLoaded; +std::vector> g_LoadedModVersions; + CmdLineArgs g_args; JS::Value Mod::GetAvailableMods(const ScriptInterface& scriptInterface) @@ -101,29 +104,38 @@ JS::Value Mod::GetAvailableMods(const ScriptInterface& scriptInterface) return JS::ObjectValue(*obj); } -JS::Value Mod::GetLoadedModsWithVersions(const ScriptInterface& scriptInterface) +void Mod::CacheEnabledModVersions(const shared_ptr& scriptRuntime) { + ScriptInterface scriptInterface("Engine", "CacheEnabledModVersions", scriptRuntime); JSContext* cx = scriptInterface.GetContext(); JSAutoRequest rq(cx); JS::RootedValue availableMods(cx, GetAvailableMods(scriptInterface)); - JS::RootedValue ret(cx, JS::ObjectValue(*JS_NewArrayObject(cx, 0))); + g_LoadedModVersions.clear(); - // Index of the created array - size_t j = 0; - for (size_t i = 0; i < g_modsLoaded.size(); ++i) + for (const CStr& mod : g_modsLoaded) { // Ignore user and mod mod as they are irrelevant for compatibility checks - if (g_modsLoaded[i] == "mod" || g_modsLoaded[i] == "user") + if (mod == "mod" || mod == "user") continue; + CStr version; JS::RootedValue modData(cx); - if (scriptInterface.GetProperty(availableMods, g_modsLoaded[i].c_str(), &modData)) + if (scriptInterface.GetProperty(availableMods, mod.c_str(), &modData)) scriptInterface.GetProperty(modData, "version", version); - scriptInterface.SetPropertyInt(ret, j++, std::vector{g_modsLoaded[i], version}); + + g_LoadedModVersions.push_back({mod, version}); } - return ret; +} + +JS::Value Mod::GetLoadedModsWithVersions(const ScriptInterface& scriptInterface) +{ + JSContext* cx = scriptInterface.GetContext(); + JSAutoRequest rq(cx); + JS::RootedValue returnValue(cx); + scriptInterface.ToJSVal(cx, &returnValue, g_LoadedModVersions); + return returnValue; } JS::Value Mod::GetEngineInfo(const ScriptInterface& scriptInterface) diff --git a/source/ps/Mod.h b/source/ps/Mod.h index 586edc7baf..8d41601fc0 100644 --- a/source/ps/Mod.h +++ b/source/ps/Mod.h @@ -22,6 +22,8 @@ #include "ps/GameSetup/CmdLineArgs.h" #include "scriptinterface/ScriptInterface.h" +class ScriptRuntime; + extern std::vector g_modsLoaded; extern CmdLineArgs g_args; @@ -29,6 +31,14 @@ namespace Mod { JS::Value GetAvailableMods(const ScriptInterface& scriptInterface); + /** + * This reads the version numbers from the launched mods. + * It caches the result, since the reading of zip files is slow and + * JS pages can request the version numbers too often easily. + * Make sure this is called after each MountMods call. + */ + void CacheEnabledModVersions(const shared_ptr& scriptRuntime); + /** * Get the loaded mods and their version. * "user" mod and "mod" mod are ignored as they are irrelevant for compatibility checks. diff --git a/source/ps/Replay.cpp b/source/ps/Replay.cpp index e4c8b9fd99..2f91cda777 100644 --- a/source/ps/Replay.cpp +++ b/source/ps/Replay.cpp @@ -35,6 +35,7 @@ #include "ps/Util.h" #include "ps/VisualReplay.h" #include "scriptinterface/ScriptInterface.h" +#include "scriptinterface/ScriptRuntime.h" #include "scriptinterface/ScriptStats.h" #include "simulation2/Simulation2.h" #include "simulation2/helpers/SimulationCommand.h" @@ -179,6 +180,8 @@ void CReplayPlayer::Replay(bool serializationtest, int rejointestturn, bool oosl const int heapGrowthBytesGCTrigger = 20 * 1024 * 1024; g_ScriptRuntime = ScriptInterface::CreateRuntime(shared_ptr(), runtimeSize, heapGrowthBytesGCTrigger); + Mod::CacheEnabledModVersions(g_ScriptRuntime); + g_Game = new CGame(true, false); if (serializationtest) g_Game->GetSimulation2()->EnableSerializationTest();