mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-20 06:40:09 +00:00
Extract engine handlers processing from LuaManager to a new class EngineEvents
This commit is contained in:
parent
7ef759c78b
commit
8d1e52ed51
@ -59,8 +59,8 @@ add_openmw_dir (mwscript
|
||||
)
|
||||
|
||||
add_openmw_dir (mwlua
|
||||
luamanagerimp object worldview userdataserializer luaevents objectvariant
|
||||
luabindings localscripts playerscripts objectbindings cellbindings
|
||||
luamanagerimp object worldview userdataserializer luaevents engineevents objectvariant
|
||||
context globalscripts localscripts playerscripts luabindings objectbindings cellbindings
|
||||
camerabindings uibindings inputbindings nearbybindings postprocessingbindings stats debugbindings
|
||||
types/types types/door types/actor types/container types/weapon types/npc types/creature types/activator types/book types/lockpick types/probe types/apparatus types/potion types/ingredient types/misc types/repair types/armor types/light types/static types/clothing
|
||||
worker
|
||||
|
105
apps/openmw/mwlua/engineevents.cpp
Normal file
105
apps/openmw/mwlua/engineevents.cpp
Normal file
@ -0,0 +1,105 @@
|
||||
#include "engineevents.hpp"
|
||||
|
||||
#include <components/debug/debuglog.hpp>
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/worldmodel.hpp"
|
||||
|
||||
#include "globalscripts.hpp"
|
||||
#include "localscripts.hpp"
|
||||
#include "object.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
|
||||
class EngineEvents::Visitor
|
||||
{
|
||||
public:
|
||||
explicit Visitor(GlobalScripts* globalScripts)
|
||||
: mGlobalScripts(globalScripts)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(const OnNewGame&) const { mGlobalScripts->newGameStarted(); }
|
||||
|
||||
void operator()(const OnActive& event) const
|
||||
{
|
||||
MWWorld::Ptr ptr = getPtr(event.mObject);
|
||||
if (ptr.isEmpty())
|
||||
return;
|
||||
if (ptr.getCellRef().getRefId() == "player")
|
||||
mGlobalScripts->playerAdded(GObject(ptr));
|
||||
else
|
||||
{
|
||||
mGlobalScripts->objectActive(GObject(ptr));
|
||||
const MWWorld::Class& objClass = ptr.getClass();
|
||||
if (objClass.isActor())
|
||||
mGlobalScripts->actorActive(GObject(ptr));
|
||||
if (objClass.isItem(ptr))
|
||||
mGlobalScripts->itemActive(GObject(ptr));
|
||||
}
|
||||
if (auto* scripts = getLocalScripts(ptr))
|
||||
scripts->setActive(true);
|
||||
}
|
||||
|
||||
void operator()(const OnInactive& event) const
|
||||
{
|
||||
if (auto* scripts = getLocalScripts(event.mObject))
|
||||
scripts->setActive(false);
|
||||
}
|
||||
|
||||
void operator()(const OnActivate& event) const
|
||||
{
|
||||
MWWorld::Ptr obj = getPtr(event.mObject);
|
||||
MWWorld::Ptr actor = getPtr(event.mActor);
|
||||
if (actor.isEmpty() || obj.isEmpty())
|
||||
return;
|
||||
if (auto* scripts = getLocalScripts(obj))
|
||||
scripts->onActivated(LObject(actor));
|
||||
}
|
||||
|
||||
void operator()(const OnConsume& event) const
|
||||
{
|
||||
MWWorld::Ptr actor = getPtr(event.mActor);
|
||||
MWWorld::Ptr consumable = getPtr(event.mConsumable);
|
||||
if (actor.isEmpty() || consumable.isEmpty())
|
||||
return;
|
||||
if (auto* scripts = getLocalScripts(actor))
|
||||
scripts->onConsume(LObject(consumable));
|
||||
}
|
||||
|
||||
private:
|
||||
MWWorld::Ptr getPtr(const ESM::RefNum& id) const
|
||||
{
|
||||
MWWorld::Ptr res = mWorldModel->getPtr(id);
|
||||
if (res.isEmpty() && mLuaDebug)
|
||||
Log(Debug::Verbose) << "Can not find object" << id.toString() << " when calling engine hanglers";
|
||||
return res;
|
||||
}
|
||||
|
||||
LocalScripts* getLocalScripts(const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
if (ptr.isEmpty())
|
||||
return nullptr;
|
||||
else
|
||||
return ptr.getRefData().getLuaScripts();
|
||||
}
|
||||
|
||||
LocalScripts* getLocalScripts(const ESM::RefNum& id) const { return getLocalScripts(getPtr(id)); }
|
||||
|
||||
GlobalScripts* mGlobalScripts;
|
||||
bool mLuaDebug = Settings::Manager::getBool("lua debug", "Lua");
|
||||
MWWorld::WorldModel* mWorldModel = MWBase::Environment::get().getWorldModel();
|
||||
};
|
||||
|
||||
void EngineEvents::callEngineHandlers()
|
||||
{
|
||||
Visitor vis(mGlobalScripts);
|
||||
for (const Event& event : mQueue)
|
||||
std::visit(vis, event);
|
||||
mQueue.clear();
|
||||
}
|
||||
|
||||
}
|
56
apps/openmw/mwlua/engineevents.hpp
Normal file
56
apps/openmw/mwlua/engineevents.hpp
Normal file
@ -0,0 +1,56 @@
|
||||
#ifndef MWLUA_ENGINEEVENTS_H
|
||||
#define MWLUA_ENGINEEVENTS_H
|
||||
|
||||
#include <variant>
|
||||
|
||||
#include <components/esm3/cellref.hpp> // defines RefNum that is used as a unique id
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
class GlobalScripts;
|
||||
|
||||
class EngineEvents
|
||||
{
|
||||
public:
|
||||
explicit EngineEvents(GlobalScripts* globalScripts)
|
||||
: mGlobalScripts(globalScripts)
|
||||
{
|
||||
}
|
||||
|
||||
struct OnNewGame
|
||||
{
|
||||
};
|
||||
struct OnActive
|
||||
{
|
||||
ESM::RefNum mObject;
|
||||
};
|
||||
struct OnInactive
|
||||
{
|
||||
ESM::RefNum mObject;
|
||||
};
|
||||
struct OnActivate
|
||||
{
|
||||
ESM::RefNum mActor;
|
||||
ESM::RefNum mObject;
|
||||
};
|
||||
struct OnConsume
|
||||
{
|
||||
ESM::RefNum mActor;
|
||||
ESM::RefNum mConsumable;
|
||||
};
|
||||
using Event = std::variant<OnNewGame, OnActive, OnInactive, OnConsume, OnActivate>;
|
||||
|
||||
void clear() { mQueue.clear(); }
|
||||
void addToQueue(Event e) { mQueue.push_back(std::move(e)); }
|
||||
void callEngineHandlers();
|
||||
|
||||
private:
|
||||
class Visitor;
|
||||
|
||||
GlobalScripts* mGlobalScripts;
|
||||
std::vector<Event> mQueue;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // MWLUA_ENGINEEVENTS_H
|
@ -206,32 +206,13 @@ namespace MWLua
|
||||
{ &mOnActiveHandlers, &mOnInactiveHandlers, &mOnConsumeHandlers, &mOnActivatedHandlers });
|
||||
}
|
||||
|
||||
void LocalScripts::receiveEngineEvent(const EngineEvent& event)
|
||||
void LocalScripts::setActive(bool active)
|
||||
{
|
||||
std::visit(
|
||||
[this](auto&& arg) {
|
||||
using EventT = std::decay_t<decltype(arg)>;
|
||||
if constexpr (std::is_same_v<EventT, OnActive>)
|
||||
{
|
||||
mData.mIsActive = true;
|
||||
callEngineHandlers(mOnActiveHandlers);
|
||||
}
|
||||
else if constexpr (std::is_same_v<EventT, OnInactive>)
|
||||
{
|
||||
mData.mIsActive = false;
|
||||
callEngineHandlers(mOnInactiveHandlers);
|
||||
}
|
||||
else if constexpr (std::is_same_v<EventT, OnActivated>)
|
||||
{
|
||||
callEngineHandlers(mOnActivatedHandlers, arg.mActivatingActor);
|
||||
}
|
||||
else
|
||||
{
|
||||
static_assert(std::is_same_v<EventT, OnConsume>);
|
||||
callEngineHandlers(mOnConsumeHandlers, arg.mConsumable);
|
||||
}
|
||||
},
|
||||
event);
|
||||
mData.mIsActive = active;
|
||||
if (active)
|
||||
callEngineHandlers(mOnActiveHandlers);
|
||||
else
|
||||
callEngineHandlers(mOnInactiveHandlers);
|
||||
}
|
||||
|
||||
void LocalScripts::applyStatsCache()
|
||||
|
@ -23,11 +23,6 @@ namespace MWLua
|
||||
public:
|
||||
using Setter = void (*)(int, std::string_view, const MWWorld::Ptr&, const sol::object&);
|
||||
|
||||
private:
|
||||
Setter mSetter; // Function that updates a stat's property
|
||||
int mIndex; // Optional index to disambiguate the stat
|
||||
std::string_view mProp; // Name of the stat's property
|
||||
public:
|
||||
CachedStat(Setter setter, int index, std::string_view prop)
|
||||
: mSetter(setter)
|
||||
, mIndex(index)
|
||||
@ -44,6 +39,11 @@ namespace MWLua
|
||||
{
|
||||
return std::tie(mSetter, mIndex, mProp) < std::tie(other.mSetter, other.mIndex, other.mProp);
|
||||
}
|
||||
|
||||
private:
|
||||
Setter mSetter; // Function that updates a stat's property
|
||||
int mIndex; // Optional index to disambiguate the stat
|
||||
std::string_view mProp; // Name of the stat's property
|
||||
};
|
||||
|
||||
SelfObject(const LObject& obj)
|
||||
@ -65,23 +65,9 @@ namespace MWLua
|
||||
MWBase::LuaManager::ActorControls* getActorControls() { return &mData.mControls; }
|
||||
const MWWorld::Ptr& getPtr() const { return mData.ptr(); }
|
||||
|
||||
struct OnActive
|
||||
{
|
||||
};
|
||||
struct OnInactive
|
||||
{
|
||||
};
|
||||
struct OnActivated
|
||||
{
|
||||
LObject mActivatingActor;
|
||||
};
|
||||
struct OnConsume
|
||||
{
|
||||
LObject mConsumable;
|
||||
};
|
||||
using EngineEvent = std::variant<OnActive, OnInactive, OnConsume, OnActivated>;
|
||||
|
||||
void receiveEngineEvent(const EngineEvent&);
|
||||
void setActive(bool active);
|
||||
void onConsume(const LObject& consumable) { callEngineHandlers(mOnConsumeHandlers, consumable); }
|
||||
void onActivated(const LObject& actor) { callEngineHandlers(mOnActivatedHandlers, actor); }
|
||||
|
||||
void applyStatsCache();
|
||||
|
||||
|
@ -136,7 +136,6 @@ namespace MWLua
|
||||
|
||||
void LuaManager::update()
|
||||
{
|
||||
static const bool luaDebug = Settings::Manager::getBool("lua debug", "Lua");
|
||||
static const int gcStepCount = Settings::Manager::getInt("gc steps per frame", "Lua");
|
||||
if (gcStepCount > 0)
|
||||
lua_gc(mLua.sol(), LUA_GCSTEP, gcStepCount);
|
||||
@ -177,6 +176,7 @@ namespace MWLua
|
||||
scripts->processTimers(simulationTime, gameTime);
|
||||
}
|
||||
|
||||
// Run event handlers for events that were sent before `finalizeEventBatch`.
|
||||
mLuaEvents.callEventHandlers();
|
||||
|
||||
// Run queued callbacks
|
||||
@ -184,63 +184,14 @@ namespace MWLua
|
||||
c.mCallback.tryCall(c.mArg);
|
||||
mQueuedCallbacks.clear();
|
||||
|
||||
// Engine handlers in local scripts
|
||||
for (const LocalEngineEvent& e : mLocalEngineEvents)
|
||||
{
|
||||
LObject obj(e.mDest);
|
||||
const MWWorld::Ptr& ptr = obj.ptrOrNull();
|
||||
if (ptr.isEmpty())
|
||||
{
|
||||
if (luaDebug)
|
||||
Log(Debug::Verbose) << "Can not call engine handlers: object" << e.mDest.toString()
|
||||
<< " is not found";
|
||||
continue;
|
||||
}
|
||||
LocalScripts* scripts = ptr.getRefData().getLuaScripts();
|
||||
if (scripts)
|
||||
scripts->receiveEngineEvent(e.mEvent);
|
||||
}
|
||||
mLocalEngineEvents.clear();
|
||||
|
||||
// Run engine handlers
|
||||
mEngineEvents.callEngineHandlers();
|
||||
if (!mWorldView.isPaused())
|
||||
{
|
||||
for (LocalScripts* scripts : mActiveLocalScripts)
|
||||
scripts->update(frameDuration);
|
||||
}
|
||||
|
||||
// Engine handlers in global scripts
|
||||
if (mPlayerChanged)
|
||||
{
|
||||
mPlayerChanged = false;
|
||||
mGlobalScripts.playerAdded(GObject(getId(mPlayer)));
|
||||
}
|
||||
if (mNewGameStarted)
|
||||
{
|
||||
mNewGameStarted = false;
|
||||
mGlobalScripts.newGameStarted();
|
||||
}
|
||||
|
||||
for (ObjectId id : mObjectAddedEvents)
|
||||
{
|
||||
GObject obj(id);
|
||||
const MWWorld::Ptr& ptr = obj.ptrOrNull();
|
||||
if (!ptr.isEmpty())
|
||||
{
|
||||
mGlobalScripts.objectActive(obj);
|
||||
const MWWorld::Class& objClass = ptr.getClass();
|
||||
if (objClass.isActor())
|
||||
mGlobalScripts.actorActive(obj);
|
||||
if (objClass.isItem(ptr))
|
||||
mGlobalScripts.itemActive(obj);
|
||||
}
|
||||
else if (luaDebug)
|
||||
Log(Debug::Verbose) << "Could not resolve a Lua object added event: object" << id.toString()
|
||||
<< " is already removed";
|
||||
}
|
||||
mObjectAddedEvents.clear();
|
||||
|
||||
if (!mWorldView.isPaused())
|
||||
mGlobalScripts.update(frameDuration);
|
||||
}
|
||||
}
|
||||
|
||||
void LuaManager::synchronizedUpdate()
|
||||
@ -286,11 +237,8 @@ namespace MWLua
|
||||
MWBase::Environment::get().getWorld()->getPostProcessor()->disableDynamicShaders();
|
||||
mActiveLocalScripts.clear();
|
||||
mLuaEvents.clear();
|
||||
mEngineEvents.clear();
|
||||
mInputEvents.clear();
|
||||
mObjectAddedEvents.clear();
|
||||
mLocalEngineEvents.clear();
|
||||
mNewGameStarted = false;
|
||||
mPlayerChanged = false;
|
||||
mWorldView.clear();
|
||||
mGlobalScripts.removeAllScripts();
|
||||
mGlobalScriptsStarted = false;
|
||||
@ -321,16 +269,15 @@ namespace MWLua
|
||||
localScripts->addAutoStartedScripts();
|
||||
}
|
||||
mActiveLocalScripts.insert(localScripts);
|
||||
mLocalEngineEvents.push_back({ getId(ptr), LocalScripts::OnActive{} });
|
||||
mPlayerChanged = true;
|
||||
mEngineEvents.addToQueue(EngineEvents::OnActive{ getId(ptr) });
|
||||
}
|
||||
|
||||
void LuaManager::newGameStarted()
|
||||
{
|
||||
mNewGameStarted = true;
|
||||
mInputEvents.clear();
|
||||
mGlobalScripts.addAutoStartedScripts();
|
||||
mGlobalScriptsStarted = true;
|
||||
mEngineEvents.addToQueue(EngineEvents::OnNewGame{});
|
||||
}
|
||||
|
||||
void LuaManager::gameLoaded()
|
||||
@ -343,26 +290,16 @@ namespace MWLua
|
||||
void LuaManager::objectAddedToScene(const MWWorld::Ptr& ptr)
|
||||
{
|
||||
mWorldView.objectAddedToScene(ptr); // assigns generated RefNum if it is not set yet.
|
||||
mEngineEvents.addToQueue(EngineEvents::OnActive{ getId(ptr) });
|
||||
|
||||
LocalScripts* localScripts = ptr.getRefData().getLuaScripts();
|
||||
if (!localScripts)
|
||||
if (!ptr.getRefData().getLuaScripts())
|
||||
{
|
||||
LuaUtil::ScriptIdsWithInitializationData autoStartConf
|
||||
= mConfiguration.getLocalConf(getLiveCellRefType(ptr.mRef), ptr.getCellRef().getRefId(), getId(ptr));
|
||||
// TODO: put to a queue and apply `addAutoStartedScripts` on next `update()`
|
||||
if (!autoStartConf.empty())
|
||||
{
|
||||
localScripts = createLocalScripts(ptr, std::move(autoStartConf));
|
||||
localScripts->addAutoStartedScripts(); // TODO: put to a queue and apply on next `update()`
|
||||
}
|
||||
createLocalScripts(ptr, std::move(autoStartConf))->addAutoStartedScripts();
|
||||
}
|
||||
if (localScripts)
|
||||
{
|
||||
mActiveLocalScripts.insert(localScripts);
|
||||
mLocalEngineEvents.push_back({ getId(ptr), LocalScripts::OnActive{} });
|
||||
}
|
||||
|
||||
if (ptr != mPlayer)
|
||||
mObjectAddedEvents.push_back(getId(ptr));
|
||||
}
|
||||
|
||||
void LuaManager::objectRemovedFromScene(const MWWorld::Ptr& ptr)
|
||||
@ -373,21 +310,10 @@ namespace MWLua
|
||||
{
|
||||
mActiveLocalScripts.erase(localScripts);
|
||||
if (!MWBase::Environment::get().getWorldModel()->getPtr(getId(ptr)).isEmpty())
|
||||
mLocalEngineEvents.push_back({ getId(ptr), LocalScripts::OnInactive{} });
|
||||
mEngineEvents.addToQueue(EngineEvents::OnInactive{ getId(ptr) });
|
||||
}
|
||||
}
|
||||
|
||||
void LuaManager::itemConsumed(const MWWorld::Ptr& consumable, const MWWorld::Ptr& actor)
|
||||
{
|
||||
MWBase::Environment::get().getWorldModel()->registerPtr(consumable);
|
||||
mLocalEngineEvents.push_back({ getId(actor), LocalScripts::OnConsume{ LObject(getId(consumable)) } });
|
||||
}
|
||||
|
||||
void LuaManager::objectActivated(const MWWorld::Ptr& object, const MWWorld::Ptr& actor)
|
||||
{
|
||||
mLocalEngineEvents.push_back({ getId(object), LocalScripts::OnActivated{ LObject(getId(actor)) } });
|
||||
}
|
||||
|
||||
MWBase::LuaManager::ActorControls* LuaManager::getActorControls(const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
LocalScripts* localScripts = ptr.getRefData().getLuaScripts();
|
||||
@ -529,7 +455,7 @@ namespace MWLua
|
||||
scripts->load(data);
|
||||
}
|
||||
for (LocalScripts* scripts : mActiveLocalScripts)
|
||||
scripts->receiveEngineEvent(LocalScripts::OnActive());
|
||||
scripts->setActive(true);
|
||||
}
|
||||
|
||||
void LuaManager::handleConsoleCommand(
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include "../mwbase/luamanager.hpp"
|
||||
|
||||
#include "engineevents.hpp"
|
||||
#include "globalscripts.hpp"
|
||||
#include "localscripts.hpp"
|
||||
#include "luaevents.hpp"
|
||||
@ -64,8 +65,14 @@ namespace MWLua
|
||||
void objectAddedToScene(const MWWorld::Ptr& ptr) override;
|
||||
void objectRemovedFromScene(const MWWorld::Ptr& ptr) override;
|
||||
void inputEvent(const InputEvent& event) override { mInputEvents.push_back(event); }
|
||||
void itemConsumed(const MWWorld::Ptr& consumable, const MWWorld::Ptr& actor) override;
|
||||
void objectActivated(const MWWorld::Ptr& object, const MWWorld::Ptr& actor) 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) });
|
||||
}
|
||||
|
||||
MWBase::LuaManager::ActorControls* getActorControls(const MWWorld::Ptr&) const override;
|
||||
|
||||
@ -163,11 +170,11 @@ namespace MWLua
|
||||
std::set<LocalScripts*> mActiveLocalScripts;
|
||||
WorldView mWorldView;
|
||||
|
||||
bool mPlayerChanged = false;
|
||||
bool mNewGameStarted = false;
|
||||
MWWorld::Ptr mPlayer;
|
||||
|
||||
LuaEvents mLuaEvents{ &mGlobalScripts };
|
||||
EngineEvents mEngineEvents{ &mGlobalScripts };
|
||||
std::vector<MWBase::LuaManager::InputEvent> mInputEvents;
|
||||
|
||||
std::unique_ptr<LuaUtil::UserdataSerializer> mGlobalSerializer;
|
||||
std::unique_ptr<LuaUtil::UserdataSerializer> mLocalSerializer;
|
||||
@ -176,9 +183,6 @@ namespace MWLua
|
||||
std::unique_ptr<LuaUtil::UserdataSerializer> mGlobalLoader;
|
||||
std::unique_ptr<LuaUtil::UserdataSerializer> mLocalLoader;
|
||||
|
||||
std::vector<MWBase::LuaManager::InputEvent> mInputEvents;
|
||||
std::vector<ObjectId> mObjectAddedEvents;
|
||||
|
||||
struct CallbackWithData
|
||||
{
|
||||
LuaUtil::Callback mCallback;
|
||||
@ -186,13 +190,6 @@ namespace MWLua
|
||||
};
|
||||
std::vector<CallbackWithData> mQueuedCallbacks;
|
||||
|
||||
struct LocalEngineEvent
|
||||
{
|
||||
ObjectId mDest;
|
||||
LocalScripts::EngineEvent mEvent;
|
||||
};
|
||||
std::vector<LocalEngineEvent> mLocalEngineEvents;
|
||||
|
||||
// Queued actions that should be done in main thread. Processed by applyQueuedChanges().
|
||||
std::vector<std::unique_ptr<Action>> mActionQueue;
|
||||
std::unique_ptr<Action> mTeleportPlayerAction;
|
||||
|
@ -21,6 +21,13 @@ namespace MWWorld
|
||||
return res;
|
||||
}
|
||||
|
||||
SafePtr::SafePtr(const Ptr& ptr)
|
||||
: mId(ptr.getCellRef().getRefNum())
|
||||
, mPtr(ptr)
|
||||
, mLastUpdate(MWBase::Environment::get().getWorldModel()->getPtrIndexUpdateCounter())
|
||||
{
|
||||
}
|
||||
|
||||
std::string SafePtr::toString() const
|
||||
{
|
||||
update();
|
||||
|
@ -159,10 +159,7 @@ namespace MWWorld
|
||||
: mId(id)
|
||||
{
|
||||
}
|
||||
explicit SafePtr(const Ptr& ptr)
|
||||
: SafePtr(ptr.getCellRef().getRefNum())
|
||||
{
|
||||
}
|
||||
explicit SafePtr(const Ptr& ptr);
|
||||
virtual ~SafePtr() = default;
|
||||
Id id() const { return mId; }
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user