mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-31 15:45:35 +00:00
Refactor mwlua/eventqueue and extract some code out of LuaManager
This commit is contained in:
parent
4fd07cb58d
commit
7ef759c78b
11 changed files with 194 additions and 143 deletions
|
@ -59,7 +59,7 @@ add_openmw_dir (mwscript
|
|||
)
|
||||
|
||||
add_openmw_dir (mwlua
|
||||
luamanagerimp object worldview userdataserializer eventqueue objectvariant
|
||||
luamanagerimp object worldview userdataserializer luaevents objectvariant
|
||||
luabindings localscripts playerscripts 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
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#ifndef MWLUA_CONTEXT_H
|
||||
#define MWLUA_CONTEXT_H
|
||||
|
||||
#include "eventqueue.hpp"
|
||||
|
||||
namespace LuaUtil
|
||||
{
|
||||
class LuaState;
|
||||
|
@ -11,6 +9,7 @@ namespace LuaUtil
|
|||
|
||||
namespace MWLua
|
||||
{
|
||||
class LuaEvents;
|
||||
class LuaManager;
|
||||
class WorldView;
|
||||
|
||||
|
@ -21,8 +20,7 @@ namespace MWLua
|
|||
LuaUtil::LuaState* mLua;
|
||||
LuaUtil::UserdataSerializer* mSerializer;
|
||||
WorldView* mWorldView;
|
||||
LocalEventQueue* mLocalEventQueue;
|
||||
GlobalEventQueue* mGlobalEventQueue;
|
||||
LuaEvents* mLuaEvents;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
#include "eventqueue.hpp"
|
||||
|
||||
#include <components/debug/debuglog.hpp>
|
||||
|
||||
#include <components/esm/luascripts.hpp>
|
||||
#include <components/esm3/esmreader.hpp>
|
||||
#include <components/esm3/esmwriter.hpp>
|
||||
|
||||
#include <components/lua/serialization.hpp>
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
|
||||
template <typename Event>
|
||||
void saveEvent(ESM::ESMWriter& esm, const ObjectId& dest, const Event& event)
|
||||
{
|
||||
esm.writeHNString("LUAE", event.mEventName);
|
||||
dest.save(esm, true);
|
||||
if (!event.mEventData.empty())
|
||||
saveLuaBinaryData(esm, event.mEventData);
|
||||
}
|
||||
|
||||
void loadEvents(sol::state_view& lua, ESM::ESMReader& esm, GlobalEventQueue& globalEvents,
|
||||
LocalEventQueue& localEvents, const std::map<int, int>& contentFileMapping,
|
||||
const LuaUtil::UserdataSerializer* serializer)
|
||||
{
|
||||
while (esm.isNextSub("LUAE"))
|
||||
{
|
||||
std::string name = esm.getHString();
|
||||
ObjectId dest;
|
||||
dest.load(esm, true);
|
||||
std::string data = loadLuaBinaryData(esm);
|
||||
try
|
||||
{
|
||||
data = LuaUtil::serialize(LuaUtil::deserialize(lua, data, serializer), serializer);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
Log(Debug::Error) << "loadEvent: invalid event data: " << e.what();
|
||||
}
|
||||
if (dest.isSet())
|
||||
{
|
||||
auto it = contentFileMapping.find(dest.mContentFile);
|
||||
if (it != contentFileMapping.end())
|
||||
dest.mContentFile = it->second;
|
||||
localEvents.push_back({ dest, std::move(name), std::move(data) });
|
||||
}
|
||||
else
|
||||
globalEvents.push_back({ std::move(name), std::move(data) });
|
||||
}
|
||||
}
|
||||
|
||||
void saveEvents(ESM::ESMWriter& esm, const GlobalEventQueue& globalEvents, const LocalEventQueue& localEvents)
|
||||
{
|
||||
// Used as a marker of a global event.
|
||||
constexpr ObjectId globalId;
|
||||
|
||||
for (const GlobalEvent& e : globalEvents)
|
||||
saveEvent(esm, globalId, e);
|
||||
for (const LocalEvent& e : localEvents)
|
||||
saveEvent(esm, e.mDest, e);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
#ifndef MWLUA_EVENTQUEUE_H
|
||||
#define MWLUA_EVENTQUEUE_H
|
||||
|
||||
#include "object.hpp"
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
class ESMReader;
|
||||
class ESMWriter;
|
||||
}
|
||||
|
||||
namespace LuaUtil
|
||||
{
|
||||
class UserdataSerializer;
|
||||
}
|
||||
|
||||
namespace sol
|
||||
{
|
||||
class state;
|
||||
}
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
struct GlobalEvent
|
||||
{
|
||||
std::string mEventName;
|
||||
std::string mEventData;
|
||||
};
|
||||
struct LocalEvent
|
||||
{
|
||||
ObjectId mDest;
|
||||
std::string mEventName;
|
||||
std::string mEventData;
|
||||
};
|
||||
using GlobalEventQueue = std::vector<GlobalEvent>;
|
||||
using LocalEventQueue = std::vector<LocalEvent>;
|
||||
|
||||
void loadEvents(sol::state_view& lua, ESM::ESMReader& esm, GlobalEventQueue&, LocalEventQueue&,
|
||||
const std::map<int, int>& contentFileMapping, const LuaUtil::UserdataSerializer* serializer);
|
||||
void saveEvents(ESM::ESMWriter& esm, const GlobalEventQueue&, const LocalEventQueue&);
|
||||
}
|
||||
|
||||
#endif // MWLUA_EVENTQUEUE_H
|
|
@ -13,7 +13,7 @@
|
|||
#include "../mwworld/scene.hpp"
|
||||
#include "../mwworld/store.hpp"
|
||||
|
||||
#include "eventqueue.hpp"
|
||||
#include "luaevents.hpp"
|
||||
#include "luamanagerimp.hpp"
|
||||
#include "worldview.hpp"
|
||||
|
||||
|
@ -57,7 +57,7 @@ namespace MWLua
|
|||
MWBase::Environment::get().getStateManager()->requestQuit();
|
||||
};
|
||||
api["sendGlobalEvent"] = [context](std::string eventName, const sol::object& eventData) {
|
||||
context.mGlobalEventQueue->push_back(
|
||||
context.mLuaEvents->addGlobalEvent(
|
||||
{ std::move(eventName), LuaUtil::serialize(eventData, context.mSerializer) });
|
||||
};
|
||||
addTimeBindings(api, context, false);
|
||||
|
|
108
apps/openmw/mwlua/luaevents.cpp
Normal file
108
apps/openmw/mwlua/luaevents.cpp
Normal file
|
@ -0,0 +1,108 @@
|
|||
#include "luaevents.hpp"
|
||||
|
||||
#include <components/debug/debuglog.hpp>
|
||||
|
||||
#include <components/esm/luascripts.hpp>
|
||||
#include <components/esm3/esmreader.hpp>
|
||||
#include <components/esm3/esmwriter.hpp>
|
||||
|
||||
#include <components/lua/serialization.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwworld/worldmodel.hpp"
|
||||
|
||||
#include "globalscripts.hpp"
|
||||
#include "localscripts.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
|
||||
void LuaEvents::clear()
|
||||
{
|
||||
mGlobalEventBatch.clear();
|
||||
mLocalEventBatch.clear();
|
||||
mNewGlobalEventBatch.clear();
|
||||
mNewLocalEventBatch.clear();
|
||||
}
|
||||
|
||||
void LuaEvents::finalizeEventBatch()
|
||||
{
|
||||
mNewGlobalEventBatch.swap(mGlobalEventBatch);
|
||||
mNewLocalEventBatch.swap(mLocalEventBatch);
|
||||
mNewGlobalEventBatch.clear();
|
||||
mNewLocalEventBatch.clear();
|
||||
}
|
||||
|
||||
void LuaEvents::callEventHandlers()
|
||||
{
|
||||
for (Global& e : mGlobalEventBatch)
|
||||
mGlobalScripts->receiveEvent(e.mEventName, e.mEventData);
|
||||
mGlobalEventBatch.clear();
|
||||
for (Local& e : mLocalEventBatch)
|
||||
{
|
||||
MWWorld::Ptr ptr = MWBase::Environment::get().getWorldModel()->getPtr(e.mDest);
|
||||
LocalScripts* scripts = ptr.isEmpty() ? nullptr : ptr.getRefData().getLuaScripts();
|
||||
if (scripts)
|
||||
scripts->receiveEvent(e.mEventName, e.mEventData);
|
||||
else
|
||||
Log(Debug::Debug) << "Ignored event " << e.mEventName << " to L" << e.mDest.toString()
|
||||
<< ". Object not found or has no attached scripts";
|
||||
}
|
||||
mLocalEventBatch.clear();
|
||||
}
|
||||
|
||||
template <typename Event>
|
||||
static void saveEvent(ESM::ESMWriter& esm, const ESM::RefNum& dest, const Event& event)
|
||||
{
|
||||
esm.writeHNString("LUAE", event.mEventName);
|
||||
dest.save(esm, true);
|
||||
if (!event.mEventData.empty())
|
||||
saveLuaBinaryData(esm, event.mEventData);
|
||||
}
|
||||
|
||||
void LuaEvents::load(lua_State* lua, ESM::ESMReader& esm, const std::map<int, int>& contentFileMapping,
|
||||
const LuaUtil::UserdataSerializer* serializer)
|
||||
{
|
||||
clear();
|
||||
while (esm.isNextSub("LUAE"))
|
||||
{
|
||||
std::string name = esm.getHString();
|
||||
ESM::RefNum dest;
|
||||
dest.load(esm, true);
|
||||
std::string data = loadLuaBinaryData(esm);
|
||||
try
|
||||
{
|
||||
data = LuaUtil::serialize(LuaUtil::deserialize(lua, data, serializer), serializer);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
Log(Debug::Error) << "loadEvent: invalid event data: " << e.what();
|
||||
}
|
||||
if (dest.isSet())
|
||||
{
|
||||
auto it = contentFileMapping.find(dest.mContentFile);
|
||||
if (it != contentFileMapping.end())
|
||||
dest.mContentFile = it->second;
|
||||
mLocalEventBatch.push_back({ dest, std::move(name), std::move(data) });
|
||||
}
|
||||
else
|
||||
mGlobalEventBatch.push_back({ std::move(name), std::move(data) });
|
||||
}
|
||||
}
|
||||
|
||||
void LuaEvents::save(ESM::ESMWriter& esm) const
|
||||
{
|
||||
// Used as a marker of a global event.
|
||||
constexpr ESM::RefNum globalId;
|
||||
|
||||
for (const Global& e : mGlobalEventBatch)
|
||||
saveEvent(esm, globalId, e);
|
||||
for (const Global& e : mNewGlobalEventBatch)
|
||||
saveEvent(esm, globalId, e);
|
||||
for (const Local& e : mLocalEventBatch)
|
||||
saveEvent(esm, e.mDest, e);
|
||||
for (const Local& e : mNewLocalEventBatch)
|
||||
saveEvent(esm, e.mDest, e);
|
||||
}
|
||||
|
||||
}
|
68
apps/openmw/mwlua/luaevents.hpp
Normal file
68
apps/openmw/mwlua/luaevents.hpp
Normal file
|
@ -0,0 +1,68 @@
|
|||
#ifndef MWLUA_LUAEVENTS_H
|
||||
#define MWLUA_LUAEVENTS_H
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include <components/esm3/cellref.hpp> // defines RefNum that is used as a unique id
|
||||
|
||||
struct lua_State;
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
class ESMReader;
|
||||
class ESMWriter;
|
||||
}
|
||||
|
||||
namespace LuaUtil
|
||||
{
|
||||
class UserdataSerializer;
|
||||
}
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
|
||||
class GlobalScripts;
|
||||
|
||||
class LuaEvents
|
||||
{
|
||||
public:
|
||||
explicit LuaEvents(GlobalScripts* globalScripts)
|
||||
: mGlobalScripts(globalScripts)
|
||||
{
|
||||
}
|
||||
|
||||
struct Global
|
||||
{
|
||||
std::string mEventName;
|
||||
std::string mEventData;
|
||||
};
|
||||
struct Local
|
||||
{
|
||||
ESM::RefNum mDest;
|
||||
std::string mEventName;
|
||||
std::string mEventData;
|
||||
};
|
||||
|
||||
void addGlobalEvent(Global event) { mNewGlobalEventBatch.push_back(std::move(event)); }
|
||||
void addLocalEvent(Local event) { mNewLocalEventBatch.push_back(std::move(event)); }
|
||||
|
||||
void clear();
|
||||
void finalizeEventBatch();
|
||||
void callEventHandlers();
|
||||
|
||||
void load(lua_State* lua, ESM::ESMReader& esm, const std::map<int, int>& contentFileMapping,
|
||||
const LuaUtil::UserdataSerializer* serializer);
|
||||
void save(ESM::ESMWriter& esm) const;
|
||||
|
||||
private:
|
||||
GlobalScripts* mGlobalScripts;
|
||||
std::vector<Global> mNewGlobalEventBatch;
|
||||
std::vector<Local> mNewLocalEventBatch;
|
||||
std::vector<Global> mGlobalEventBatch;
|
||||
std::vector<Local> mLocalEventBatch;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // MWLUA_LUAEVENTS_H
|
|
@ -81,8 +81,7 @@ namespace MWLua
|
|||
context.mLuaManager = this;
|
||||
context.mLua = &mLua;
|
||||
context.mWorldView = &mWorldView;
|
||||
context.mLocalEventQueue = &mLocalEvents;
|
||||
context.mGlobalEventQueue = &mGlobalEvents;
|
||||
context.mLuaEvents = &mLuaEvents;
|
||||
context.mSerializer = mGlobalSerializer.get();
|
||||
|
||||
Context localContext = context;
|
||||
|
@ -165,10 +164,7 @@ namespace MWLua
|
|||
for (LocalScripts* scripts : mActiveLocalScripts)
|
||||
scripts->statsNextFrame();
|
||||
|
||||
std::vector<GlobalEvent> globalEvents = std::move(mGlobalEvents);
|
||||
std::vector<LocalEvent> localEvents = std::move(mLocalEvents);
|
||||
mGlobalEvents = std::vector<GlobalEvent>();
|
||||
mLocalEvents = std::vector<LocalEvent>();
|
||||
mLuaEvents.finalizeEventBatch();
|
||||
|
||||
if (!mWorldView.isPaused())
|
||||
{ // Update time and process timers
|
||||
|
@ -181,20 +177,7 @@ namespace MWLua
|
|||
scripts->processTimers(simulationTime, gameTime);
|
||||
}
|
||||
|
||||
// Receive events
|
||||
for (GlobalEvent& e : globalEvents)
|
||||
mGlobalScripts.receiveEvent(e.mEventName, e.mEventData);
|
||||
for (LocalEvent& e : localEvents)
|
||||
{
|
||||
LObject obj(e.mDest);
|
||||
const MWWorld::Ptr& ptr = obj.ptrOrNull();
|
||||
LocalScripts* scripts = ptr.isEmpty() ? nullptr : ptr.getRefData().getLuaScripts();
|
||||
if (scripts)
|
||||
scripts->receiveEvent(e.mEventName, e.mEventData);
|
||||
else
|
||||
Log(Debug::Debug) << "Ignored event " << e.mEventName << " to L" << e.mDest.toString()
|
||||
<< ". Object not found or has no attached scripts";
|
||||
}
|
||||
mLuaEvents.callEventHandlers();
|
||||
|
||||
// Run queued callbacks
|
||||
for (CallbackWithData& c : mQueuedCallbacks)
|
||||
|
@ -302,8 +285,7 @@ namespace MWLua
|
|||
MWBase::Environment::get().getWindowManager()->setConsoleMode("");
|
||||
MWBase::Environment::get().getWorld()->getPostProcessor()->disableDynamicShaders();
|
||||
mActiveLocalScripts.clear();
|
||||
mLocalEvents.clear();
|
||||
mGlobalEvents.clear();
|
||||
mLuaEvents.clear();
|
||||
mInputEvents.clear();
|
||||
mObjectAddedEvents.clear();
|
||||
mLocalEngineEvents.clear();
|
||||
|
@ -470,7 +452,7 @@ namespace MWLua
|
|||
ESM::LuaScripts globalScripts;
|
||||
mGlobalScripts.save(globalScripts);
|
||||
globalScripts.save(writer);
|
||||
saveEvents(writer, mGlobalEvents, mLocalEvents);
|
||||
mLuaEvents.save(writer);
|
||||
|
||||
writer.endRecord(ESM::REC_LUAM);
|
||||
}
|
||||
|
@ -483,7 +465,7 @@ namespace MWLua
|
|||
mWorldView.load(reader);
|
||||
ESM::LuaScripts globalScripts;
|
||||
globalScripts.load(reader);
|
||||
loadEvents(mLua.sol(), reader, mGlobalEvents, mLocalEvents, mContentFileMapping, mGlobalLoader.get());
|
||||
mLuaEvents.load(mLua.sol(), reader, mContentFileMapping, mGlobalLoader.get());
|
||||
|
||||
mGlobalScripts.setSavedDataDeserializer(mGlobalLoader.get());
|
||||
mGlobalScripts.load(globalScripts);
|
||||
|
|
|
@ -14,9 +14,9 @@
|
|||
|
||||
#include "../mwbase/luamanager.hpp"
|
||||
|
||||
#include "eventqueue.hpp"
|
||||
#include "globalscripts.hpp"
|
||||
#include "localscripts.hpp"
|
||||
#include "luaevents.hpp"
|
||||
#include "object.hpp"
|
||||
#include "worldview.hpp"
|
||||
|
||||
|
@ -31,6 +31,8 @@ namespace MWLua
|
|||
{
|
||||
public:
|
||||
LuaManager(const VFS::Manager* vfs, const std::filesystem::path& libsDir);
|
||||
LuaManager(const LuaManager&) = delete;
|
||||
LuaManager(LuaManager&&) = delete;
|
||||
|
||||
// Called by engine.cpp when the environment is fully initialized.
|
||||
void init();
|
||||
|
@ -165,8 +167,7 @@ namespace MWLua
|
|||
bool mNewGameStarted = false;
|
||||
MWWorld::Ptr mPlayer;
|
||||
|
||||
GlobalEventQueue mGlobalEvents;
|
||||
LocalEventQueue mLocalEvents;
|
||||
LuaEvents mLuaEvents{ &mGlobalScripts };
|
||||
|
||||
std::unique_ptr<LuaUtil::UserdataSerializer> mGlobalSerializer;
|
||||
std::unique_ptr<LuaUtil::UserdataSerializer> mLocalSerializer;
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
#include "../mwmechanics/creaturestats.hpp"
|
||||
|
||||
#include "eventqueue.hpp"
|
||||
#include "luaevents.hpp"
|
||||
#include "luamanagerimp.hpp"
|
||||
#include "types/types.hpp"
|
||||
|
||||
|
@ -188,7 +188,7 @@ namespace MWLua
|
|||
objectT[sol::meta_function::equal_to] = [](const ObjectT& a, const ObjectT& b) { return a.id() == b.id(); };
|
||||
objectT[sol::meta_function::to_string] = &ObjectT::toString;
|
||||
objectT["sendEvent"] = [context](const ObjectT& dest, std::string eventName, const sol::object& eventData) {
|
||||
context.mLocalEventQueue->push_back(
|
||||
context.mLuaEvents->addLocalEvent(
|
||||
{ dest.id(), std::move(eventName), LuaUtil::serialize(eventData, context.mSerializer) });
|
||||
};
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <components/esm/defs.hpp>
|
||||
|
||||
#include "../context.hpp"
|
||||
#include "../object.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue