|
|
|
@ -12,13 +12,10 @@
|
|
|
|
|
#include <components/esm3/esmreader.hpp>
|
|
|
|
|
#include <components/esm3/esmwriter.hpp>
|
|
|
|
|
|
|
|
|
|
#include <components/settings/settings.hpp>
|
|
|
|
|
#include <components/settings/values.hpp>
|
|
|
|
|
|
|
|
|
|
#include <components/l10n/manager.hpp>
|
|
|
|
|
|
|
|
|
|
#include <components/lua/asyncpackage.hpp>
|
|
|
|
|
#include <components/lua/utilpackage.hpp>
|
|
|
|
|
|
|
|
|
|
#include <components/lua_ui/content.hpp>
|
|
|
|
|
#include <components/lua_ui/util.hpp>
|
|
|
|
|
|
|
|
|
@ -31,7 +28,6 @@
|
|
|
|
|
#include "../mwworld/ptr.hpp"
|
|
|
|
|
#include "../mwworld/scene.hpp"
|
|
|
|
|
|
|
|
|
|
#include "debugbindings.hpp"
|
|
|
|
|
#include "luabindings.hpp"
|
|
|
|
|
#include "playerscripts.hpp"
|
|
|
|
|
#include "types/types.hpp"
|
|
|
|
@ -42,12 +38,12 @@ namespace MWLua
|
|
|
|
|
|
|
|
|
|
static LuaUtil::LuaStateSettings createLuaStateSettings()
|
|
|
|
|
{
|
|
|
|
|
if (!Settings::Manager::getBool("lua profiler", "Lua"))
|
|
|
|
|
if (!Settings::lua().mLuaProfiler)
|
|
|
|
|
LuaUtil::LuaState::disableProfiler();
|
|
|
|
|
return { .mInstructionLimit = Settings::Manager::getUInt64("instruction limit per call", "Lua"),
|
|
|
|
|
.mMemoryLimit = Settings::Manager::getUInt64("memory limit", "Lua"),
|
|
|
|
|
.mSmallAllocMaxSize = Settings::Manager::getUInt64("small alloc max size", "Lua"),
|
|
|
|
|
.mLogMemoryUsage = Settings::Manager::getBool("log memory usage", "Lua") };
|
|
|
|
|
return { .mInstructionLimit = Settings::lua().mInstructionLimitPerCall,
|
|
|
|
|
.mMemoryLimit = Settings::lua().mMemoryLimit,
|
|
|
|
|
.mSmallAllocMaxSize = Settings::lua().mSmallAllocMaxSize,
|
|
|
|
|
.mLogMemoryUsage = Settings::lua().mLogMemoryUsage };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LuaManager::LuaManager(const VFS::Manager* vfs, const std::filesystem::path& libsDir)
|
|
|
|
@ -88,31 +84,21 @@ namespace MWLua
|
|
|
|
|
localContext.mIsGlobal = false;
|
|
|
|
|
localContext.mSerializer = mLocalSerializer.get();
|
|
|
|
|
|
|
|
|
|
initObjectBindingsForGlobalScripts(context);
|
|
|
|
|
initCellBindingsForGlobalScripts(context);
|
|
|
|
|
initObjectBindingsForLocalScripts(localContext);
|
|
|
|
|
initCellBindingsForLocalScripts(localContext);
|
|
|
|
|
LocalScripts::initializeSelfPackage(localContext);
|
|
|
|
|
LuaUtil::LuaStorage::initLuaBindings(mLua.sol());
|
|
|
|
|
for (const auto& [name, package] : initCommonPackages(context))
|
|
|
|
|
mLua.addCommonPackage(name, package);
|
|
|
|
|
for (const auto& [name, package] : initGlobalPackages(context))
|
|
|
|
|
mGlobalScripts.addPackage(name, package);
|
|
|
|
|
|
|
|
|
|
mLua.addCommonPackage("openmw.async",
|
|
|
|
|
LuaUtil::getAsyncPackageInitializer(
|
|
|
|
|
mLua.sol(), [this] { return mWorldView.getSimulationTime(); },
|
|
|
|
|
[this] { return mWorldView.getGameTime(); }));
|
|
|
|
|
mLua.addCommonPackage("openmw.util", LuaUtil::initUtilPackage(mLua.sol()));
|
|
|
|
|
mLua.addCommonPackage("openmw.core", initCorePackage(context));
|
|
|
|
|
mLua.addCommonPackage("openmw.types", initTypesPackage(context));
|
|
|
|
|
mGlobalScripts.addPackage("openmw.world", initWorldPackage(context));
|
|
|
|
|
mGlobalScripts.addPackage("openmw.storage", initGlobalStoragePackage(context, &mGlobalStorage));
|
|
|
|
|
|
|
|
|
|
mCameraPackage = initCameraPackage(localContext);
|
|
|
|
|
mUserInterfacePackage = initUserInterfacePackage(localContext);
|
|
|
|
|
mInputPackage = initInputPackage(localContext);
|
|
|
|
|
mNearbyPackage = initNearbyPackage(localContext);
|
|
|
|
|
mLocalStoragePackage = initLocalStoragePackage(localContext, &mGlobalStorage);
|
|
|
|
|
mPlayerStoragePackage = initPlayerStoragePackage(localContext, &mGlobalStorage, &mPlayerStorage);
|
|
|
|
|
mPostprocessingPackage = initPostprocessingPackage(localContext);
|
|
|
|
|
mDebugPackage = initDebugPackage(localContext);
|
|
|
|
|
mLocalPackages = initLocalPackages(localContext);
|
|
|
|
|
mPlayerPackages = initPlayerPackages(localContext);
|
|
|
|
|
mPlayerPackages.insert(mLocalPackages.begin(), mLocalPackages.end());
|
|
|
|
|
|
|
|
|
|
LuaUtil::LuaStorage::initLuaBindings(mLua.sol());
|
|
|
|
|
mGlobalScripts.addPackage(
|
|
|
|
|
"openmw.storage", LuaUtil::LuaStorage::initGlobalPackage(mLua.sol(), &mGlobalStorage));
|
|
|
|
|
mLocalPackages["openmw.storage"] = LuaUtil::LuaStorage::initLocalPackage(mLua.sol(), &mGlobalStorage);
|
|
|
|
|
mPlayerPackages["openmw.storage"]
|
|
|
|
|
= LuaUtil::LuaStorage::initPlayerPackage(mLua.sol(), &mGlobalStorage, &mPlayerStorage);
|
|
|
|
|
|
|
|
|
|
initConfiguration();
|
|
|
|
|
mInitialized = true;
|
|
|
|
@ -136,9 +122,8 @@ namespace MWLua
|
|
|
|
|
|
|
|
|
|
void LuaManager::update()
|
|
|
|
|
{
|
|
|
|
|
static const int gcStepCount = Settings::Manager::getInt("gc steps per frame", "Lua");
|
|
|
|
|
if (gcStepCount > 0)
|
|
|
|
|
lua_gc(mLua.sol(), LUA_GCSTEP, gcStepCount);
|
|
|
|
|
if (Settings::lua().mGcStepsPerFrame > 0)
|
|
|
|
|
lua_gc(mLua.sol(), LUA_GCSTEP, Settings::lua().mGcStepsPerFrame);
|
|
|
|
|
|
|
|
|
|
if (mPlayer.isEmpty())
|
|
|
|
|
return; // The game is not started yet.
|
|
|
|
@ -147,7 +132,7 @@ namespace MWLua
|
|
|
|
|
|
|
|
|
|
MWWorld::Ptr newPlayerPtr = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
|
|
|
|
if (!(getId(mPlayer) == getId(newPlayerPtr)))
|
|
|
|
|
throw std::logic_error("Player Refnum was changed unexpectedly");
|
|
|
|
|
throw std::logic_error("Player RefNum was changed unexpectedly");
|
|
|
|
|
if (!mPlayer.isInCell() || !newPlayerPtr.isInCell() || mPlayer.getCell() != newPlayerPtr.getCell())
|
|
|
|
|
{
|
|
|
|
|
mPlayer = newPlayerPtr; // player was moved to another cell, update ptr in registry
|
|
|
|
@ -220,12 +205,12 @@ namespace MWLua
|
|
|
|
|
windowManager->printToConsole(msg, "#" + color.toHex());
|
|
|
|
|
mInGameConsoleMessages.clear();
|
|
|
|
|
|
|
|
|
|
for (std::unique_ptr<Action>& action : mActionQueue)
|
|
|
|
|
action->safeApply();
|
|
|
|
|
for (DelayedAction& action : mActionQueue)
|
|
|
|
|
action.apply();
|
|
|
|
|
mActionQueue.clear();
|
|
|
|
|
|
|
|
|
|
if (mTeleportPlayerAction)
|
|
|
|
|
mTeleportPlayerAction->safeApply();
|
|
|
|
|
mTeleportPlayerAction->apply();
|
|
|
|
|
mTeleportPlayerAction.reset();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -352,12 +337,8 @@ namespace MWLua
|
|
|
|
|
{
|
|
|
|
|
scripts = std::make_shared<PlayerScripts>(&mLua, LObject(getId(ptr)));
|
|
|
|
|
scripts->setAutoStartConf(mConfiguration.getPlayerConf());
|
|
|
|
|
scripts->addPackage("openmw.ui", mUserInterfacePackage);
|
|
|
|
|
scripts->addPackage("openmw.camera", mCameraPackage);
|
|
|
|
|
scripts->addPackage("openmw.input", mInputPackage);
|
|
|
|
|
scripts->addPackage("openmw.storage", mPlayerStoragePackage);
|
|
|
|
|
scripts->addPackage("openmw.postprocessing", mPostprocessingPackage);
|
|
|
|
|
scripts->addPackage("openmw.debug", mDebugPackage);
|
|
|
|
|
for (const auto& [name, package] : mPlayerPackages)
|
|
|
|
|
scripts->addPackage(name, package);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
@ -365,9 +346,9 @@ namespace MWLua
|
|
|
|
|
if (!autoStartConf.has_value())
|
|
|
|
|
autoStartConf = mConfiguration.getLocalConf(type, ptr.getCellRef().getRefId(), getId(ptr));
|
|
|
|
|
scripts->setAutoStartConf(std::move(*autoStartConf));
|
|
|
|
|
scripts->addPackage("openmw.storage", mLocalStoragePackage);
|
|
|
|
|
for (const auto& [name, package] : mLocalPackages)
|
|
|
|
|
scripts->addPackage(name, package);
|
|
|
|
|
}
|
|
|
|
|
scripts->addPackage("openmw.nearby", mNearbyPackage);
|
|
|
|
|
scripts->setSerializer(mLocalSerializer.get());
|
|
|
|
|
|
|
|
|
|
MWWorld::RefData& refData = ptr.getRefData();
|
|
|
|
@ -483,22 +464,23 @@ namespace MWLua
|
|
|
|
|
"No Lua handlers for console\n", MWBase::WindowManager::sConsoleColor_Error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LuaManager::Action::Action(LuaUtil::LuaState* state)
|
|
|
|
|
LuaManager::DelayedAction::DelayedAction(LuaUtil::LuaState* state, std::function<void()> fn, std::string_view name)
|
|
|
|
|
: mFn(std::move(fn))
|
|
|
|
|
, mName(name)
|
|
|
|
|
{
|
|
|
|
|
static const bool luaDebug = Settings::Manager::getBool("lua debug", "Lua");
|
|
|
|
|
if (luaDebug)
|
|
|
|
|
if (Settings::lua().mLuaDebug)
|
|
|
|
|
mCallerTraceback = state->debugTraceback();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LuaManager::Action::safeApply() const
|
|
|
|
|
void LuaManager::DelayedAction::apply() const
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
apply();
|
|
|
|
|
mFn();
|
|
|
|
|
}
|
|
|
|
|
catch (const std::exception& e)
|
|
|
|
|
{
|
|
|
|
|
Log(Debug::Error) << "Error in " << this->toString() << ": " << e.what();
|
|
|
|
|
Log(Debug::Error) << "Error in DelayedAction " << mName << ": " << e.what();
|
|
|
|
|
|
|
|
|
|
if (mCallerTraceback.empty())
|
|
|
|
|
Log(Debug::Error) << "Set 'lua_debug=true' in settings.cfg to enable action tracebacks";
|
|
|
|
@ -507,35 +489,14 @@ namespace MWLua
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace
|
|
|
|
|
{
|
|
|
|
|
class FunctionAction final : public LuaManager::Action
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
FunctionAction(LuaUtil::LuaState* state, std::function<void()> fn, std::string_view name)
|
|
|
|
|
: Action(state)
|
|
|
|
|
, mFn(std::move(fn))
|
|
|
|
|
, mName(name)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void apply() const override { mFn(); }
|
|
|
|
|
std::string toString() const override { return "FunctionAction " + mName; }
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
std::function<void()> mFn;
|
|
|
|
|
std::string mName;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LuaManager::addAction(std::function<void()> action, std::string_view name)
|
|
|
|
|
{
|
|
|
|
|
mActionQueue.push_back(std::make_unique<FunctionAction>(&mLua, std::move(action), name));
|
|
|
|
|
mActionQueue.emplace_back(&mLua, std::move(action), name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LuaManager::addTeleportPlayerAction(std::function<void()> action)
|
|
|
|
|
{
|
|
|
|
|
mTeleportPlayerAction = std::make_unique<FunctionAction>(&mLua, std::move(action), "TeleportPlayer");
|
|
|
|
|
mTeleportPlayerAction = DelayedAction(&mLua, std::move(action), "TeleportPlayer");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LuaManager::reportStats(unsigned int frameNumber, osg::Stats& stats) const
|
|
|
|
@ -566,7 +527,7 @@ namespace MWLua
|
|
|
|
|
out << (bytes / (1024 * 1024 * 1024)) << " GB";
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const uint64_t smallAllocSize = Settings::Manager::getUInt64("small alloc max size", "Lua");
|
|
|
|
|
const uint64_t smallAllocSize = Settings::lua().mSmallAllocMaxSize;
|
|
|
|
|
out << "Total memory usage:";
|
|
|
|
|
outMemSize(mLua.getTotalMemoryUsage());
|
|
|
|
|
out << "\n";
|
|
|
|
|