1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-30 12:32:36 +00:00

Load LuaScriptsCfg from both *.omwscripts and *.omwaddon files.

This commit is contained in:
Petr Mikheev 2021-09-26 15:21:46 +02:00
parent 4ec7f0625e
commit 47c89567fb
11 changed files with 81 additions and 41 deletions

View File

@ -495,11 +495,6 @@ void OMW::Engine::addGroundcoverFile(const std::string& file)
mGroundcoverFiles.emplace_back(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) void OMW::Engine::setSkipMenu (bool skipMenu, bool newGame)
{ {
mSkipMenu = skipMenu; mSkipMenu = skipMenu;
@ -714,7 +709,7 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
mViewer->addEventHandler(mScreenCaptureHandler); mViewer->addEventHandler(mScreenCaptureHandler);
mLuaManager = new MWLua::LuaManager(mVFS.get(), mLuaScriptListFiles); mLuaManager = new MWLua::LuaManager(mVFS.get());
mEnvironment.setLuaManager(mLuaManager); mEnvironment.setLuaManager(mLuaManager);
// Create input and UI first to set up a bootstrapping environment for // Create input and UI first to set up a bootstrapping environment for

View File

@ -72,7 +72,6 @@ namespace OMW
std::string mCellName; std::string mCellName;
std::vector<std::string> mContentFiles; std::vector<std::string> mContentFiles;
std::vector<std::string> mGroundcoverFiles; std::vector<std::string> mGroundcoverFiles;
std::vector<std::string> mLuaScriptListFiles;
bool mSkipMenu; bool mSkipMenu;
bool mUseSound; bool mUseSound;
bool mCompileAll; bool mCompileAll;
@ -146,7 +145,6 @@ namespace OMW
*/ */
void addContentFile(const std::string& file); void addContentFile(const std::string& file);
void addGroundcoverFile(const std::string& file); void addGroundcoverFile(const std::string& file);
void addLuaScriptListFile(const std::string& file);
/// Disable or enable all sounds /// Disable or enable all sounds
void setSoundUsage(bool soundUsage); void setSoundUsage(bool soundUsage);

View File

@ -124,9 +124,11 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
engine.addGroundcoverFile(file); engine.addGroundcoverFile(file);
} }
StringsVector luaScriptLists = variables["lua-scripts"].as<Files::EscapeStringVector>().toStdStringVector(); if (variables.count("lua-scripts"))
for (const auto& file : luaScriptLists) {
engine.addLuaScriptListFile(file); 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 // startup-settings
engine.setCell(variables["start"].as<Files::EscapeHashString>().toStdString()); engine.setCell(variables["start"].as<Files::EscapeHashString>().toStdString());

View File

@ -11,6 +11,7 @@
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwworld/esmstore.hpp"
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "luabindings.hpp" #include "luabindings.hpp"
@ -19,8 +20,7 @@
namespace MWLua namespace MWLua
{ {
LuaManager::LuaManager(const VFS::Manager* vfs, std::vector<std::string> OMWScriptsFiles) : LuaManager::LuaManager(const VFS::Manager* vfs) : mLua(vfs, &mConfiguration)
mVFS(vfs), mOMWScriptsFiles(std::move(OMWScriptsFiles)), mLua(vfs, &mConfiguration)
{ {
Log(Debug::Info) << "Lua version: " << LuaUtil::getLuaVersion(); Log(Debug::Info) << "Lua version: " << LuaUtil::getLuaVersion();
@ -34,23 +34,7 @@ namespace MWLua
void LuaManager::initConfiguration() void LuaManager::initConfiguration()
{ {
ESM::LuaScriptsCfg cfg; mConfiguration.init(MWBase::Environment::get().getWorld()->getStore().getLuaScriptsCfg());
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<char>(*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);
Log(Debug::Verbose) << "Lua scripts configuration (" << mConfiguration.size() << " scripts):"; Log(Debug::Verbose) << "Lua scripts configuration (" << mConfiguration.size() << " scripts):";
for (size_t i = 0; i < mConfiguration.size(); ++i) for (size_t i = 0; i < mConfiguration.size(); ++i)
Log(Debug::Verbose) << "#" << i << " " << LuaUtil::scriptCfgToString(mConfiguration[i]); Log(Debug::Verbose) << "#" << i << " " << LuaUtil::scriptCfgToString(mConfiguration[i]);

View File

@ -35,7 +35,7 @@ namespace MWLua
class LuaManager : public MWBase::LuaManager class LuaManager : public MWBase::LuaManager
{ {
public: public:
LuaManager(const VFS::Manager* vfs, std::vector<std::string> OMWScriptsFiles); LuaManager(const VFS::Manager* vfs);
// Called by engine.cpp when the environment is fully initialized. // Called by engine.cpp when the environment is fully initialized.
void init(); void init();
@ -97,9 +97,6 @@ namespace MWLua
void initConfiguration(); void initConfiguration();
LocalScripts* createLocalScripts(const MWWorld::Ptr& ptr, ESM::LuaScriptCfg::Flags); LocalScripts* createLocalScripts(const MWWorld::Ptr& ptr, ESM::LuaScriptCfg::Flags);
const VFS::Manager* mVFS;
const std::vector<std::string> mOMWScriptsFiles;
bool mInitialized = false; bool mInitialized = false;
bool mGlobalScriptsStarted = false; bool mGlobalScriptsStarted = false;
LuaUtil::ScriptsConfiguration mConfiguration; LuaUtil::ScriptsConfiguration mConfiguration;

View File

@ -1,14 +1,16 @@
#include "esmstore.hpp" #include "esmstore.hpp"
#include <algorithm> #include <algorithm>
#include <fstream>
#include <set> #include <set>
#include <boost/filesystem/operations.hpp> #include <boost/filesystem/operations.hpp>
#include <components/debug/debuglog.hpp> #include <components/debug/debuglog.hpp>
#include <components/loadinglistener/loadinglistener.hpp>
#include <components/esm/esmreader.hpp> #include <components/esm/esmreader.hpp>
#include <components/esm/esmwriter.hpp> #include <components/esm/esmwriter.hpp>
#include <components/loadinglistener/loadinglistener.hpp>
#include <components/lua/configuration.hpp>
#include <components/misc/algorithm.hpp> #include <components/misc/algorithm.hpp>
#include "../mwmechanics/spelllist.hpp" #include "../mwmechanics/spelllist.hpp"
@ -166,7 +168,10 @@ void ESMStore::load(ESM::ESMReader &esm, Loading::Listener* listener)
std::string fname = mast.name; std::string fname = mast.name;
int index = ~0; int index = ~0;
for (int i = 0; i < esm.getIndex(); i++) { 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(); std::string fnamecandidate = boost::filesystem::path(candidate).filename().string();
if (Misc::StringUtils::ciEqual(fname, fnamecandidate)) { if (Misc::StringUtils::ciEqual(fname, fnamecandidate)) {
index = i; index = i;
@ -213,6 +218,13 @@ void ESMStore::load(ESM::ESMReader &esm, Loading::Listener* listener)
// ignore project file only records // ignore project file only records
esm.skipRecord(); 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 { else {
throw std::runtime_error("Unknown record: " + n.toString()); 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<std::string>(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<std::string>(c));
std::string fileContent(std::istreambuf_iterator<char>(file), {});
LuaUtil::parseOMWScripts(cfg, fileContent);
}
catch (std::exception& e) { Log(Debug::Error) << e.what(); }
}
else
{
const ESM::LuaScriptsCfg& addition = std::get<ESM::LuaScriptsCfg>(c);
cfg.mScripts.insert(cfg.mScripts.end(), addition.mScripts.begin(), addition.mScripts.end());
}
}
return cfg;
}
void ESMStore::setUp(bool validateRecords) void ESMStore::setUp(bool validateRecords)
{ {
mIds.clear(); mIds.clear();

View File

@ -6,6 +6,7 @@
#include <stdexcept> #include <stdexcept>
#include <unordered_map> #include <unordered_map>
#include <components/esm/luascripts.hpp>
#include <components/esm/records.hpp> #include <components/esm/records.hpp>
#include "store.hpp" #include "store.hpp"
@ -92,7 +93,16 @@ namespace MWWorld
template<class T> template<class T>
void removeMissingObjects(Store<T>& store); void removeMissingObjects(Store<T>& store);
using LuaContent = std::variant<
ESM::LuaScriptsCfg, // data from an omwaddon
std::string>; // path to an omwscripts file
std::vector<LuaContent> mLuaContent;
public: public:
void addOMWScripts(std::string filePath) { mLuaContent.push_back(std::move(filePath)); }
ESM::LuaScriptsCfg getLuaScriptsCfg() const;
/// \todo replace with SharedIterator<StoreBase> /// \todo replace with SharedIterator<StoreBase>
typedef std::map<int, StoreBase *>::const_iterator iterator; typedef std::map<int, StoreBase *>::const_iterator iterator;

View File

@ -111,6 +111,17 @@ namespace MWWorld
LoadersContainer mLoaders; 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() void World::adjustSky()
{ {
if (mSky && (isCellExterior() || isCellQuasiExterior())) if (mSky && (isCellExterior() || isCellQuasiExterior()))
@ -156,6 +167,9 @@ namespace MWWorld
gameContentLoader.addLoader(".omwaddon", &esmLoader); gameContentLoader.addLoader(".omwaddon", &esmLoader);
gameContentLoader.addLoader(".project", &esmLoader); gameContentLoader.addLoader(".project", &esmLoader);
OMWScriptsLoader omwScriptsLoader(*listener, mStore);
gameContentLoader.addLoader(".omwscripts", &omwScriptsLoader);
loadContentFiles(fileCollections, contentFiles, groundcoverFiles, gameContentLoader); loadContentFiles(fileCollections, contentFiles, groundcoverFiles, gameContentLoader);
listener->loadingOff(); listener->loadingOff();

View File

@ -40,14 +40,11 @@ namespace OpenMW
"set initial cell") "set initial cell")
("content", bpo::value<Files::EscapeStringVector>()->default_value(Files::EscapeStringVector(), "") ("content", bpo::value<Files::EscapeStringVector>()->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<Files::EscapeStringVector>()->default_value(Files::EscapeStringVector(), "") ("groundcover", bpo::value<Files::EscapeStringVector>()->default_value(Files::EscapeStringVector(), "")
->multitoken()->composing(), "groundcover content file(s): esm/esp, or omwgame/omwaddon") ->multitoken()->composing(), "groundcover content file(s): esm/esp, or omwgame/omwaddon")
("lua-scripts", bpo::value<Files::EscapeStringVector>()->default_value(Files::EscapeStringVector(), "")
->multitoken()->composing(), "file(s) with a list of global Lua scripts: omwscripts")
("no-sound", bpo::value<bool>()->implicit_value(true) ("no-sound", bpo::value<bool>()->implicit_value(true)
->default_value(false), "disable all sounds") ->default_value(false), "disable all sounds")

View File

@ -7,6 +7,7 @@
#include <components/esm/esmreader.hpp> #include <components/esm/esmreader.hpp>
#include <components/esm/esmwriter.hpp> #include <components/esm/esmwriter.hpp>
#include <components/loadinglistener/loadinglistener.hpp> #include <components/loadinglistener/loadinglistener.hpp>
#include <components/misc/stringops.hpp>
#include "apps/openmw/mwworld/esmstore.hpp" #include "apps/openmw/mwworld/esmstore.hpp"
#include "apps/openmw/mwmechanics/spelllist.hpp" #include "apps/openmw/mwmechanics/spelllist.hpp"
@ -88,8 +89,11 @@ struct ContentFileTest : public ::testing::Test
std::vector<std::string> contentFiles = variables["content"].as<Files::EscapeStringVector>().toStdStringVector(); std::vector<std::string> contentFiles = variables["content"].as<Files::EscapeStringVector>().toStdStringVector();
for (auto & contentFile : contentFiles) for (auto & contentFile : contentFiles)
{
if (!Misc::StringUtils::ciEndsWith(contentFile, ".omwscripts"))
mContentFiles.push_back(collections.getPath(contentFile)); mContentFiles.push_back(collections.getPath(contentFile));
} }
}
protected: protected:
Files::ConfigurationManager mConfigurationManager; Files::ConfigurationManager mConfigurationManager;

View File

@ -165,6 +165,7 @@ enum RecNameInts
// format 1 // format 1
REC_FILT = FourCC<'F','I','L','T'>::value, REC_FILT = FourCC<'F','I','L','T'>::value,
REC_DBGP = FourCC<'D','B','G','P'>::value, ///< only used in project files 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 // format 16 - Lua scripts in saved games
REC_LUAM = FourCC<'L','U','A','M'>::value, // LuaManager data REC_LUAM = FourCC<'L','U','A','M'>::value, // LuaManager data