From 47c89567fbfe95ebba2f2c501d29baa37be71772 Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Sun, 26 Sep 2021 15:21:46 +0200 Subject: [PATCH] Load LuaScriptsCfg from both *.omwscripts and *.omwaddon files. --- apps/openmw/engine.cpp | 7 +--- apps/openmw/engine.hpp | 2 - apps/openmw/main.cpp | 8 ++-- apps/openmw/mwlua/luamanagerimp.cpp | 22 ++-------- apps/openmw/mwlua/luamanagerimp.hpp | 5 +-- apps/openmw/mwworld/esmstore.cpp | 42 ++++++++++++++++++- apps/openmw/mwworld/esmstore.hpp | 10 +++++ apps/openmw/mwworld/worldimp.cpp | 14 +++++++ apps/openmw/options.cpp | 5 +-- apps/openmw_test_suite/mwworld/test_store.cpp | 6 ++- components/esm/defs.hpp | 1 + 11 files changed, 81 insertions(+), 41 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index bbe4f25f69..bc31243ffc 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -495,11 +495,6 @@ void OMW::Engine::addGroundcoverFile(const std::string& file) mGroundcoverFiles.emplace_back(file); } -void OMW::Engine::addLuaScriptListFile(const std::string& file) -{ - mLuaScriptListFiles.push_back(file); -} - void OMW::Engine::setSkipMenu (bool skipMenu, bool newGame) { mSkipMenu = skipMenu; @@ -714,7 +709,7 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings) mViewer->addEventHandler(mScreenCaptureHandler); - mLuaManager = new MWLua::LuaManager(mVFS.get(), mLuaScriptListFiles); + mLuaManager = new MWLua::LuaManager(mVFS.get()); mEnvironment.setLuaManager(mLuaManager); // Create input and UI first to set up a bootstrapping environment for diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index 290fd890a6..5fe032d27e 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -72,7 +72,6 @@ namespace OMW std::string mCellName; std::vector mContentFiles; std::vector mGroundcoverFiles; - std::vector mLuaScriptListFiles; bool mSkipMenu; bool mUseSound; bool mCompileAll; @@ -146,7 +145,6 @@ namespace OMW */ void addContentFile(const std::string& file); void addGroundcoverFile(const std::string& file); - void addLuaScriptListFile(const std::string& file); /// Disable or enable all sounds void setSoundUsage(bool soundUsage); diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index d1f9fd1787..1cf7abe2f2 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -124,9 +124,11 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat engine.addGroundcoverFile(file); } - StringsVector luaScriptLists = variables["lua-scripts"].as().toStdStringVector(); - for (const auto& file : luaScriptLists) - engine.addLuaScriptListFile(file); + if (variables.count("lua-scripts")) + { + Log(Debug::Warning) << "Lua scripts have been specified via the old lua-scripts option and will not be loaded. " + "Please update them to a version which uses the new omwscripts format."; + } // startup-settings engine.setCell(variables["start"].as().toStdString()); diff --git a/apps/openmw/mwlua/luamanagerimp.cpp b/apps/openmw/mwlua/luamanagerimp.cpp index 7a4b319f27..30866faf56 100644 --- a/apps/openmw/mwlua/luamanagerimp.cpp +++ b/apps/openmw/mwlua/luamanagerimp.cpp @@ -11,6 +11,7 @@ #include "../mwbase/windowmanager.hpp" #include "../mwworld/class.hpp" +#include "../mwworld/esmstore.hpp" #include "../mwworld/ptr.hpp" #include "luabindings.hpp" @@ -19,8 +20,7 @@ namespace MWLua { - LuaManager::LuaManager(const VFS::Manager* vfs, std::vector OMWScriptsFiles) : - mVFS(vfs), mOMWScriptsFiles(std::move(OMWScriptsFiles)), mLua(vfs, &mConfiguration) + LuaManager::LuaManager(const VFS::Manager* vfs) : mLua(vfs, &mConfiguration) { Log(Debug::Info) << "Lua version: " << LuaUtil::getLuaVersion(); @@ -34,23 +34,7 @@ namespace MWLua void LuaManager::initConfiguration() { - ESM::LuaScriptsCfg cfg; - for (const std::string& file : mOMWScriptsFiles) - { - if (!Misc::StringUtils::endsWith(file, ".omwscripts")) - { - Log(Debug::Error) << "Script list should have suffix '.omwscripts', got: '" << file << "'"; - continue; - } - try - { - std::string content(std::istreambuf_iterator(*mVFS->get(file)), {}); - LuaUtil::parseOMWScripts(cfg, content); - } - catch (std::exception& e) { Log(Debug::Error) << e.what(); } - } - // TODO: Add data from content files - mConfiguration.init(cfg); + mConfiguration.init(MWBase::Environment::get().getWorld()->getStore().getLuaScriptsCfg()); Log(Debug::Verbose) << "Lua scripts configuration (" << mConfiguration.size() << " scripts):"; for (size_t i = 0; i < mConfiguration.size(); ++i) Log(Debug::Verbose) << "#" << i << " " << LuaUtil::scriptCfgToString(mConfiguration[i]); diff --git a/apps/openmw/mwlua/luamanagerimp.hpp b/apps/openmw/mwlua/luamanagerimp.hpp index be80cfe2e7..b9151de685 100644 --- a/apps/openmw/mwlua/luamanagerimp.hpp +++ b/apps/openmw/mwlua/luamanagerimp.hpp @@ -35,7 +35,7 @@ namespace MWLua class LuaManager : public MWBase::LuaManager { public: - LuaManager(const VFS::Manager* vfs, std::vector OMWScriptsFiles); + LuaManager(const VFS::Manager* vfs); // Called by engine.cpp when the environment is fully initialized. void init(); @@ -97,9 +97,6 @@ namespace MWLua void initConfiguration(); LocalScripts* createLocalScripts(const MWWorld::Ptr& ptr, ESM::LuaScriptCfg::Flags); - const VFS::Manager* mVFS; - const std::vector mOMWScriptsFiles; - bool mInitialized = false; bool mGlobalScriptsStarted = false; LuaUtil::ScriptsConfiguration mConfiguration; diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index c5b0fff00f..66aba9139e 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -1,14 +1,16 @@ #include "esmstore.hpp" #include +#include #include #include #include -#include #include #include +#include +#include #include #include "../mwmechanics/spelllist.hpp" @@ -166,7 +168,10 @@ void ESMStore::load(ESM::ESMReader &esm, Loading::Listener* listener) std::string fname = mast.name; int index = ~0; for (int i = 0; i < esm.getIndex(); i++) { - const std::string candidate = allPlugins->at(i).getContext().filename; + ESM::ESMReader& reader = allPlugins->at(i); + if (reader.getFileSize() == 0) + continue; // Content file in non-ESM format + const std::string candidate = reader.getContext().filename; std::string fnamecandidate = boost::filesystem::path(candidate).filename().string(); if (Misc::StringUtils::ciEqual(fname, fnamecandidate)) { index = i; @@ -213,6 +218,13 @@ void ESMStore::load(ESM::ESMReader &esm, Loading::Listener* listener) // ignore project file only records esm.skipRecord(); } + else if (n.toInt() == ESM::REC_LUAL) + { + ESM::LuaScriptsCfg cfg; + cfg.load(esm); + // TODO: update refnums in cfg.mScripts[].mInitializationData according to load order + mLuaContent.push_back(std::move(cfg)); + } else { throw std::runtime_error("Unknown record: " + n.toString()); } @@ -234,6 +246,32 @@ void ESMStore::load(ESM::ESMReader &esm, Loading::Listener* listener) } } +ESM::LuaScriptsCfg ESMStore::getLuaScriptsCfg() const +{ + ESM::LuaScriptsCfg cfg; + for (const LuaContent& c : mLuaContent) + { + if (std::holds_alternative(c)) + { + // *.omwscripts are intentionally reloaded every time when `getLuaScriptsCfg` is called. + // It is important for the `reloadlua` console command. + try + { + auto file = std::ifstream(std::get(c)); + std::string fileContent(std::istreambuf_iterator(file), {}); + LuaUtil::parseOMWScripts(cfg, fileContent); + } + catch (std::exception& e) { Log(Debug::Error) << e.what(); } + } + else + { + const ESM::LuaScriptsCfg& addition = std::get(c); + cfg.mScripts.insert(cfg.mScripts.end(), addition.mScripts.begin(), addition.mScripts.end()); + } + } + return cfg; +} + void ESMStore::setUp(bool validateRecords) { mIds.clear(); diff --git a/apps/openmw/mwworld/esmstore.hpp b/apps/openmw/mwworld/esmstore.hpp index 6ad479f8bf..22b58f77dd 100644 --- a/apps/openmw/mwworld/esmstore.hpp +++ b/apps/openmw/mwworld/esmstore.hpp @@ -6,6 +6,7 @@ #include #include +#include #include #include "store.hpp" @@ -92,7 +93,16 @@ namespace MWWorld template void removeMissingObjects(Store& store); + + using LuaContent = std::variant< + ESM::LuaScriptsCfg, // data from an omwaddon + std::string>; // path to an omwscripts file + std::vector mLuaContent; + public: + void addOMWScripts(std::string filePath) { mLuaContent.push_back(std::move(filePath)); } + ESM::LuaScriptsCfg getLuaScriptsCfg() const; + /// \todo replace with SharedIterator typedef std::map::const_iterator iterator; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index ccd78170bb..21e2d8380a 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -111,6 +111,17 @@ namespace MWWorld LoadersContainer mLoaders; }; + struct OMWScriptsLoader : public ContentLoader + { + ESMStore& mStore; + OMWScriptsLoader(Loading::Listener& listener, ESMStore& store) : ContentLoader(listener), mStore(store) {} + void load(const boost::filesystem::path& filepath, int& index) override + { + ContentLoader::load(filepath.filename(), index); + mStore.addOMWScripts(filepath.string()); + } + }; + void World::adjustSky() { if (mSky && (isCellExterior() || isCellQuasiExterior())) @@ -156,6 +167,9 @@ namespace MWWorld gameContentLoader.addLoader(".omwaddon", &esmLoader); gameContentLoader.addLoader(".project", &esmLoader); + OMWScriptsLoader omwScriptsLoader(*listener, mStore); + gameContentLoader.addLoader(".omwscripts", &omwScriptsLoader); + loadContentFiles(fileCollections, contentFiles, groundcoverFiles, gameContentLoader); listener->loadingOff(); diff --git a/apps/openmw/options.cpp b/apps/openmw/options.cpp index 62ea0910dd..d68809468c 100644 --- a/apps/openmw/options.cpp +++ b/apps/openmw/options.cpp @@ -40,14 +40,11 @@ namespace OpenMW "set initial cell") ("content", bpo::value()->default_value(Files::EscapeStringVector(), "") - ->multitoken()->composing(), "content file(s): esm/esp, or omwgame/omwaddon") + ->multitoken()->composing(), "content file(s): esm/esp, or omwgame/omwaddon/omwscripts") ("groundcover", bpo::value()->default_value(Files::EscapeStringVector(), "") ->multitoken()->composing(), "groundcover content file(s): esm/esp, or omwgame/omwaddon") - ("lua-scripts", bpo::value()->default_value(Files::EscapeStringVector(), "") - ->multitoken()->composing(), "file(s) with a list of global Lua scripts: omwscripts") - ("no-sound", bpo::value()->implicit_value(true) ->default_value(false), "disable all sounds") diff --git a/apps/openmw_test_suite/mwworld/test_store.cpp b/apps/openmw_test_suite/mwworld/test_store.cpp index f3b2bb3dcb..3fe479587c 100644 --- a/apps/openmw_test_suite/mwworld/test_store.cpp +++ b/apps/openmw_test_suite/mwworld/test_store.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include "apps/openmw/mwworld/esmstore.hpp" #include "apps/openmw/mwmechanics/spelllist.hpp" @@ -88,7 +89,10 @@ struct ContentFileTest : public ::testing::Test std::vector contentFiles = variables["content"].as().toStdStringVector(); for (auto & contentFile : contentFiles) - mContentFiles.push_back(collections.getPath(contentFile)); + { + if (!Misc::StringUtils::ciEndsWith(contentFile, ".omwscripts")) + mContentFiles.push_back(collections.getPath(contentFile)); + } } protected: diff --git a/components/esm/defs.hpp b/components/esm/defs.hpp index 7f2fe19cc5..254e66ec3a 100644 --- a/components/esm/defs.hpp +++ b/components/esm/defs.hpp @@ -165,6 +165,7 @@ enum RecNameInts // format 1 REC_FILT = FourCC<'F','I','L','T'>::value, REC_DBGP = FourCC<'D','B','G','P'>::value, ///< only used in project files + REC_LUAL = FourCC<'L','U','A','L'>::value, // LuaScriptsCfg // format 16 - Lua scripts in saved games REC_LUAM = FourCC<'L','U','A','M'>::value, // LuaManager data