diff --git a/source/ManualBindings.cpp b/source/ManualBindings.cpp index a2b4c8810..4242db46a 100644 --- a/source/ManualBindings.cpp +++ b/source/ManualBindings.cpp @@ -896,6 +896,70 @@ tolua_lerror: +class cLuaWorldTask : + public cWorld::cTask +{ +public: + cLuaWorldTask(cPluginLua & a_Plugin, int a_FnRef) : + m_Plugin(a_Plugin), + m_FnRef(a_FnRef) + { + } + +protected: + cPluginLua & m_Plugin; + int m_FnRef; + + // cWorld::cTask overrides: + virtual void Run(cWorld & a_World) override + { + m_Plugin.Call(m_FnRef, &a_World); + } +} ; + + + + + +static int tolua_cWorld_QueueTask(lua_State * tolua_S) +{ + // Binding for cWorld::QueueTask + // Params: function + + // Retrieve the cPlugin from the LuaState: + cPluginLua * Plugin = GetLuaPlugin(tolua_S); + if (Plugin == NULL) + { + // An error message has been already printed in GetLuaPlugin() + return 0; + } + + // Retrieve the args: + cWorld * self = (cWorld *)tolua_tousertype(tolua_S, 1, 0); + if (self == NULL) + { + return lua_do_error(tolua_S, "Error in function call '#funcname#': Not called on an object instance"); + } + if (!lua_isfunction(tolua_S, 2)) + { + return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a function for parameter #1"); + } + + // Create a reference to the function: + int FnRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX); + if (FnRef == LUA_REFNIL) + { + return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #1"); + } + + self->QueueTask(new cLuaWorldTask(*Plugin, FnRef)); + return 0; +} + + + + + static int tolua_cPluginManager_GetAllPlugins(lua_State * tolua_S) { cPluginManager* self = (cPluginManager*) tolua_tousertype(tolua_S,1,0); @@ -2032,6 +2096,7 @@ void ManualBindings::Bind(lua_State * tolua_S) tolua_function(tolua_S, "ForEachPlayer", tolua_ForEach< cWorld, cPlayer, &cWorld::ForEachPlayer>); tolua_function(tolua_S, "GetBlockInfo", tolua_cWorld_GetBlockInfo); tolua_function(tolua_S, "GetBlockTypeMeta", tolua_cWorld_GetBlockTypeMeta); + tolua_function(tolua_S, "QueueTask", tolua_cWorld_QueueTask); tolua_function(tolua_S, "SetSignLines", tolua_cWorld_SetSignLines); tolua_function(tolua_S, "TryGetHeight", tolua_cWorld_TryGetHeight); tolua_function(tolua_S, "UpdateSign", tolua_cWorld_SetSignLines); diff --git a/source/PluginLua.h b/source/PluginLua.h index fee9c4986..d5d202bf0 100644 --- a/source/PluginLua.h +++ b/source/PluginLua.h @@ -137,6 +137,43 @@ public: Returns true if the hook was added successfully. */ bool AddHookRef(int a_HookType, int a_FnRefIdx); + + // The following templates allow calls to arbitrary Lua functions residing in the plugin: + + /// Call a Lua function with 0 args + template bool Call(FnT a_Fn) + { + cCSLock Lock(m_CriticalSection); + return m_LuaState.Call(a_Fn); + } + + /// Call a Lua function with 1 arg + template bool Call(FnT a_Fn, ArgT0 a_Arg0) + { + cCSLock Lock(m_CriticalSection); + return m_LuaState.Call(a_Fn, a_Arg0); + } + + /// Call a Lua function with 2 args + template bool Call(FnT a_Fn, ArgT0 a_Arg0, ArgT1 a_Arg1) + { + cCSLock Lock(m_CriticalSection); + return m_LuaState.Call(a_Fn, a_Arg0, a_Arg1); + } + + /// Call a Lua function with 3 args + template bool Call(FnT a_Fn, ArgT0 a_Arg0, ArgT1 a_Arg1, ArgT2 a_Arg2) + { + cCSLock Lock(m_CriticalSection); + return m_LuaState.Call(a_Fn, a_Arg0, a_Arg1, a_Arg2); + } + + /// Call a Lua function with 4 args + template bool Call(FnT a_Fn, ArgT0 a_Arg0, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_ArgT3) + { + cCSLock Lock(m_CriticalSection); + return m_LuaState.Call(a_Fn, a_Arg0, a_Arg1, a_Arg2, a_Arg3); + } protected: /// Maps command name into Lua function reference diff --git a/source/World.cpp b/source/World.cpp index bbbe7d382..2011f5a97 100644 --- a/source/World.cpp +++ b/source/World.cpp @@ -848,7 +848,7 @@ void cWorld::TickQueuedTasks(void) } // Execute and delete each task: - for (cTasks::iterator itr = m_Tasks.begin(), end = m_Tasks.end(); itr != end; ++itr) + for (cTasks::iterator itr = Tasks.begin(), end = Tasks.end(); itr != end; ++itr) { (*itr)->Run(*this); delete *itr; diff --git a/source/World.h b/source/World.h index dcb197bd0..25bc0b338 100644 --- a/source/World.h +++ b/source/World.h @@ -508,7 +508,7 @@ public: void QueueSaveAllChunks(void); // tolua_export /// Queues a task onto the tick thread. The task object will be deleted once the task is finished - void QueueTask(cTask * a_Task); + void QueueTask(cTask * a_Task); // Exported in ManualBindings.cpp /// Returns the number of chunks loaded int GetNumChunks() const; // tolua_export @@ -589,7 +589,7 @@ public: /// Appends all usernames starting with a_Text (case-insensitive) into Results void TabCompleteUserName(const AString & a_Text, AStringVector & a_Results); - + private: friend class cRoot;