1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-31 06:32:39 +00:00
OpenMW/apps/openmw/mwlua/luamanagerimp.hpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

233 lines
10 KiB
C++
Raw Normal View History

2020-12-18 23:21:10 +01:00
#ifndef MWLUA_LUAMANAGERIMP_H
#define MWLUA_LUAMANAGERIMP_H
#include <filesystem>
2020-12-18 23:21:10 +01:00
#include <map>
#include <osg/Stats>
2020-12-18 23:21:10 +01:00
#include <set>
2023-12-29 18:56:59 +00:00
#include <components/lua/inputactions.hpp>
2021-12-14 00:39:01 +01:00
#include <components/lua/luastate.hpp>
#include <components/lua/storage.hpp>
#include <components/lua_ui/resources.hpp>
2022-04-09 23:07:57 +02:00
#include <components/misc/color.hpp>
2020-12-18 23:21:10 +01:00
#include "../mwbase/luamanager.hpp"
#include "engineevents.hpp"
2020-12-18 23:21:10 +01:00
#include "globalscripts.hpp"
2022-08-17 19:09:38 +02:00
#include "localscripts.hpp"
#include "luaevents.hpp"
#include "menuscripts.hpp"
2020-12-18 23:21:10 +01:00
#include "object.hpp"
#include "objectlists.hpp"
2020-12-18 23:21:10 +01:00
namespace MWLua
{
// \brief LuaManager is the central interface through which the engine invokes lua scripts.
//
// This class implements the interface defined in MWBase::LuaManager.
// In addition to the interface, this class exposes lower level interaction between the engine
// and the lua world.
2020-12-18 23:21:10 +01:00
class LuaManager : public MWBase::LuaManager
{
public:
LuaManager(const VFS::Manager* vfs, const std::filesystem::path& libsDir);
LuaManager(const LuaManager&) = delete;
LuaManager(LuaManager&&) = delete;
2024-01-10 21:10:10 +01:00
~LuaManager();
2020-12-18 23:21:10 +01:00
// Called by engine.cpp when the environment is fully initialized.
2020-12-18 23:21:10 +01:00
void init();
void loadPermanentStorage(const std::filesystem::path& userConfigPath);
void savePermanentStorage(const std::filesystem::path& userConfigPath);
2021-12-14 00:39:01 +01:00
// \brief Executes lua handlers. Defaults to running in parallel with OSG Cull.
//
// The OSG Cull is expensive enough that we have "free" time to
// execute Lua by running it in parallel. The Cull also does
// not modify the game state, meaning we can safely read state from Lua
// despite the concurrency. Only modifying the parts of the game state
// that affect the scene graph is forbidden. Such modifications must
// be queued for execution in synchronizedUpdate().
// The parallelism can be turned off in the settings.
void update();
2020-12-18 23:21:10 +01:00
// \brief Executes latency-critical and scene graph related Lua logic.
//
// Called by engine.cpp from the main thread between InputManager and MechanicsManager updates.
// Can use the scene graph and applies the actions queued during update()
void synchronizedUpdate();
2020-12-18 23:21:10 +01:00
// Normally it is called by `synchronizedUpdate` every frame.
// Additionally must be called before making a save to ensure that there are no pending delayed
// actions and the world is in a consistent state.
void applyDelayedActions() override;
2020-12-18 23:21:10 +01:00
// Available everywhere through the MWBase::LuaManager interface.
// LuaManager queues these events and propagates to scripts on the next `update` call.
void newGameStarted() override;
void gameLoaded() override;
void gameEnded() override;
void noGame() override;
2020-12-18 23:21:10 +01:00
void objectAddedToScene(const MWWorld::Ptr& ptr) override;
void objectRemovedFromScene(const MWWorld::Ptr& ptr) override;
void inputEvent(const InputEvent& event) override;
void itemConsumed(const MWWorld::Ptr& consumable, const MWWorld::Ptr& actor) override
{
mEngineEvents.addToQueue(EngineEvents::OnConsume{ getId(actor), getId(consumable) });
}
void objectActivated(const MWWorld::Ptr& object, const MWWorld::Ptr& actor) override
{
mEngineEvents.addToQueue(EngineEvents::OnActivate{ getId(actor), getId(object) });
}
2023-11-05 21:32:18 +01:00
void useItem(const MWWorld::Ptr& object, const MWWorld::Ptr& actor, bool force) override;
2024-01-26 21:39:33 +00:00
void animationTextKey(const MWWorld::Ptr& actor, const std::string& key) override;
void playAnimation(const MWWorld::Ptr& actor, const std::string& groupname,
const MWRender::AnimPriority& priority, int blendMask, bool autodisable, float speedmult,
std::string_view start, std::string_view stop, float startpoint, uint32_t loops,
bool loopfallback) override;
void exteriorCreated(MWWorld::CellStore& cell) override
{
mEngineEvents.addToQueue(EngineEvents::OnNewExterior{ cell });
}
2023-06-18 21:19:34 +02:00
void objectTeleported(const MWWorld::Ptr& ptr) override;
2023-06-12 21:35:00 -05:00
void questUpdated(const ESM::RefId& questId, int stage) override;
2023-07-09 08:42:09 +02:00
void uiModeChanged(const MWWorld::Ptr& arg) override;
void actorDied(const MWWorld::Ptr& actor) override;
2020-12-18 23:21:10 +01:00
MWBase::LuaManager::ActorControls* getActorControls(const MWWorld::Ptr&) const override;
2020-12-18 23:21:10 +01:00
void clear() override; // should be called before loading game or starting a new game to reset internal state.
void setupPlayer(const MWWorld::Ptr& ptr) override; // Should be called once after each "clear".
// Used only in Lua bindings
void addCustomLocalScript(const MWWorld::Ptr&, int scriptId, std::string_view initData);
2021-01-29 01:54:54 +01:00
void addUIMessage(std::string_view message) { mUIMessages.emplace_back(message); }
2022-04-09 23:07:57 +02:00
void addInGameConsoleMessage(const std::string& msg, const Misc::Color& color)
{
mInGameConsoleMessages.push_back({ msg, color });
}
2022-09-22 21:26:05 +03:00
2022-04-11 01:04:55 +02:00
// Some changes to the game world can not be done from the scripting thread (because it runs in parallel with
2023-04-22 14:24:48 +02:00
// OSG Cull), so we need to queue it and apply from the main thread.
2022-04-11 01:04:55 +02:00
void addAction(std::function<void()> action, std::string_view name = "");
void addTeleportPlayerAction(std::function<void()> action);
2020-12-18 23:21:10 +01:00
// Saving
void write(ESM::ESMWriter& writer, Loading::Listener& progress) override;
void saveLocalScripts(const MWWorld::Ptr& ptr, ESM::LuaScripts& data) override;
// Loading from a save
void readRecord(ESM::ESMReader& reader, uint32_t type) override;
void loadLocalScripts(const MWWorld::Ptr& ptr, const ESM::LuaScripts& data) override;
void setContentFileMapping(const std::map<int, int>& mapping) override { mContentFileMapping = mapping; }
2023-09-09 11:42:55 +02:00
// At the end of the next `synchronizedUpdate` drops script cache and reloads all scripts.
// Calls `onSave` and `onLoad` for every script.
void reloadAllScripts() override { mReloadAllScriptsRequested = true; }
2021-04-12 03:15:17 +02:00
2022-04-09 23:07:57 +02:00
void handleConsoleCommand(
const std::string& consoleMode, const std::string& command, const MWWorld::Ptr& selectedPtr) override;
2021-08-27 09:26:38 +02:00
// Used to call Lua callbacks from C++
void queueCallback(LuaUtil::Callback callback, sol::main_object arg)
{
mQueuedCallbacks.push_back({ std::move(callback), std::move(arg) });
}
2021-08-27 09:26:38 +02:00
// Wraps Lua callback into an std::function.
// NOTE: Resulted function is not thread safe. Can not be used while LuaManager::update() or
// any other Lua-related function is running.
template <class Arg>
std::function<void(Arg)> wrapLuaCallback(const LuaUtil::Callback& c)
2021-08-27 09:26:38 +02:00
{
return
[this, c](Arg arg) { this->queueCallback(c, sol::main_object(this->mLua.sol(), sol::in_place, arg)); };
2021-08-27 09:26:38 +02:00
}
2022-02-26 12:10:55 +01:00
LuaUi::ResourceManager* uiResourceManager() { return &mUiResourceManager; }
2022-03-18 00:27:16 +01:00
bool isProcessingInputEvents() const { return mProcessingInputEvents; }
2022-11-26 21:25:18 +01:00
void reportStats(unsigned int frameNumber, osg::Stats& stats) const;
std::string formatResourceUsageStats() const override;
2022-09-30 01:46:43 +02:00
2023-12-29 18:56:59 +00:00
LuaUtil::InputAction::Registry& inputActions() { return mInputActions; }
LuaUtil::InputTrigger::Registry& inputTriggers() { return mInputTriggers; }
2020-12-18 23:21:10 +01:00
private:
void initConfiguration();
2022-05-20 21:47:13 +02:00
LocalScripts* createLocalScripts(const MWWorld::Ptr& ptr,
std::optional<LuaUtil::ScriptIdsWithInitializationData> autoStartConf = std::nullopt);
2023-09-09 11:42:55 +02:00
void reloadAllScriptsImpl();
bool mInitialized = false;
bool mGlobalScriptsStarted = false;
2022-03-18 00:27:16 +01:00
bool mProcessingInputEvents = false;
bool mApplyingDelayedActions = false;
bool mNewGameStarted = false;
2023-09-09 11:42:55 +02:00
bool mReloadAllScriptsRequested = false;
LuaUtil::ScriptsConfiguration mConfiguration;
2020-12-18 23:21:10 +01:00
LuaUtil::LuaState mLua;
2022-02-26 12:10:55 +01:00
LuaUi::ResourceManager mUiResourceManager;
std::map<std::string, sol::object> mLocalPackages;
std::map<std::string, sol::object> mPlayerPackages;
2020-12-18 23:21:10 +01:00
MenuScripts mMenuScripts{ &mLua };
2020-12-18 23:21:10 +01:00
GlobalScripts mGlobalScripts{ &mLua };
std::set<LocalScripts*> mActiveLocalScripts;
std::vector<LocalScripts*> mQueuedAutoStartedScripts;
ObjectLists mObjectLists;
2020-12-18 23:21:10 +01:00
MWWorld::Ptr mPlayer;
2023-10-31 10:28:52 +01:00
LuaEvents mLuaEvents{ mGlobalScripts, mMenuScripts };
2023-03-25 18:14:33 +01:00
EngineEvents mEngineEvents{ mGlobalScripts };
std::vector<MWBase::LuaManager::InputEvent> mInputEvents;
std::vector<MWBase::LuaManager::InputEvent> mMenuInputEvents;
2020-12-18 23:21:10 +01:00
std::unique_ptr<LuaUtil::UserdataSerializer> mGlobalSerializer;
std::unique_ptr<LuaUtil::UserdataSerializer> mLocalSerializer;
std::map<int, int> mContentFileMapping;
std::unique_ptr<LuaUtil::UserdataSerializer> mGlobalLoader;
std::unique_ptr<LuaUtil::UserdataSerializer> mLocalLoader;
2021-08-27 09:26:38 +02:00
struct CallbackWithData
{
LuaUtil::Callback mCallback;
sol::main_object mArg;
2021-08-27 09:26:38 +02:00
};
std::vector<CallbackWithData> mQueuedCallbacks;
2021-01-29 01:54:54 +01:00
// Queued actions that should be done in main thread. Processed by applyQueuedChanges().
2023-04-22 14:24:48 +02:00
class DelayedAction
{
public:
DelayedAction(LuaUtil::LuaState* state, std::function<void()> fn, std::string_view name);
void apply() const;
private:
std::string mCallerTraceback;
std::function<void()> mFn;
std::string mName;
};
std::vector<DelayedAction> mActionQueue;
std::optional<DelayedAction> mTeleportPlayerAction;
2021-01-29 01:54:54 +01:00
std::vector<std::string> mUIMessages;
2022-04-09 23:07:57 +02:00
std::vector<std::pair<std::string, Misc::Color>> mInGameConsoleMessages;
2023-10-21 13:04:02 +02:00
std::optional<ObjectId> mDelayedUiModeChangedArg;
2021-12-14 00:39:01 +01:00
LuaUtil::LuaStorage mGlobalStorage{ mLua.sol() };
LuaUtil::LuaStorage mPlayerStorage{ mLua.sol() };
2023-12-29 18:56:59 +00:00
LuaUtil::InputAction::Registry mInputActions;
LuaUtil::InputTrigger::Registry mInputTriggers;
2020-12-18 23:21:10 +01:00
};
}
#endif // MWLUA_LUAMANAGERIMP_H