summaryrefslogtreecommitdiffstats
path: root/src/Bindings
diff options
context:
space:
mode:
Diffstat (limited to 'src/Bindings')
-rw-r--r--src/Bindings/.gitignore1
-rw-r--r--src/Bindings/LuaState.cpp12
-rw-r--r--src/Bindings/LuaState.h634
-rw-r--r--src/Bindings/ManualBindings.cpp11
-rw-r--r--src/Bindings/Plugin.h1
-rw-r--r--src/Bindings/PluginLua.cpp27
-rw-r--r--src/Bindings/PluginLua.h1
-rw-r--r--src/Bindings/PluginManager.cpp86
-rw-r--r--src/Bindings/PluginManager.h30
-rw-r--r--src/Bindings/gen_LuaState_Call.lua196
-rw-r--r--src/Bindings/virtual_method_hooks.lua14
11 files changed, 350 insertions, 663 deletions
diff --git a/src/Bindings/.gitignore b/src/Bindings/.gitignore
index af8aa76fa..0d00dd578 100644
--- a/src/Bindings/.gitignore
+++ b/src/Bindings/.gitignore
@@ -1 +1,2 @@
lua51.dll
+LuaState_Call.inc
diff --git a/src/Bindings/LuaState.cpp b/src/Bindings/LuaState.cpp
index 7a5ed1425..32638df96 100644
--- a/src/Bindings/LuaState.cpp
+++ b/src/Bindings/LuaState.cpp
@@ -811,6 +811,18 @@ void cLuaState::GetStackValue(int a_StackPos, double & a_ReturnedVal)
+void cLuaState::GetStackValue(int a_StackPos, eWeather & a_ReturnedVal)
+{
+ if (lua_isnumber(m_LuaState, a_StackPos))
+ {
+ a_ReturnedVal = (eWeather)Clamp((int)tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal), (int)wSunny, (int)wThunderstorm);
+ }
+}
+
+
+
+
+
bool cLuaState::CallFunction(int a_NumResults)
{
ASSERT (m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
diff --git a/src/Bindings/LuaState.h b/src/Bindings/LuaState.h
index 066390e39..b1ac3578a 100644
--- a/src/Bindings/LuaState.h
+++ b/src/Bindings/LuaState.h
@@ -9,10 +9,11 @@ Owned lua_State is created by calling Create() and the cLuaState automatically c
Or, lua_State can be attached by calling Attach(), the cLuaState doesn't close such a state
Attaching a state will automatically close an owned state.
-Calling a Lua function is done by pushing the function, either by PushFunction() or PushFunctionFromRegistry(),
-then pushing the arguments (PushString(), PushNumber(), PushUserData() etc.) and finally
-executing CallFunction(). cLuaState automatically keeps track of the number of arguments and the name of the
-function (for logging purposes), which makes the call less error-prone.
+Calling a Lua function is done internally by pushing the function using PushFunction(), then pushing the
+arguments and finally executing CallFunction(). cLuaState automatically keeps track of the number of
+arguments and the name of the function (for logging purposes). After the call the return values are read from
+the stack using GetStackValue(). All of this is wrapped in a templated function overloads cLuaState::Call(),
+which is generated automatically by gen_LuaState_Call.lua script file into the LuaState_Call.inc file.
Reference management is provided by the cLuaState::cRef class. This is used when you need to hold a reference to
any Lua object across several function calls; usually this is used for callbacks. The class is RAII-like, with
@@ -30,6 +31,7 @@ extern "C"
}
#include "../Vector3.h"
+#include "../Defines.h"
@@ -222,625 +224,13 @@ public:
/** Retrieve value at a_StackPos, if it is a valid number. If not, a_Value is unchanged */
void GetStackValue(int a_StackPos, double & a_Value);
+ /** Retrieve value at a_StackPos, if it is a valid number, converting and clamping it to eWeather.
+ If not, a_Value is unchanged. */
+ void GetStackValue(int a_StackPos, eWeather & a_Value);
+
- /** Call any 0-param 0-return Lua function in a single line: */
- template <typename FnT>
- bool Call(FnT a_FnName)
- {
- if (!PushFunction(a_FnName))
- {
- return false;
- }
- return CallFunction(0);
- }
-
- /** Call any 1-param 0-return Lua function in a single line: */
- template<
- typename FnT,
- typename ArgT1
- >
- bool Call(FnT a_FnName, ArgT1 a_Arg1)
- {
- if (!PushFunction(a_FnName))
- {
- return false;
- }
- Push(a_Arg1);
- return CallFunction(0);
- }
-
- /** Call any 2-param 0-return Lua function in a single line: */
- template<
- typename FnT, typename ArgT1, typename ArgT2
- >
- bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2)
- {
- if (!PushFunction(a_FnName))
- {
- return false;
- }
- Push(a_Arg1);
- Push(a_Arg2);
- return CallFunction(0);
- }
-
- /** Call any 3-param 0-return Lua function in a single line: */
- template<
- typename FnT, typename ArgT1, typename ArgT2, typename ArgT3
- >
- bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3)
- {
- if (!PushFunction(a_FnName))
- {
- return false;
- }
- Push(a_Arg1);
- Push(a_Arg2);
- Push(a_Arg3);
- return CallFunction(0);
- }
-
- /** Call any 0-param 1-return Lua function in a single line: */
- template<
- typename FnT, typename RetT1
- >
- bool Call(FnT a_FnName, const cRet & a_Mark, RetT1 & a_Ret1)
- {
- UNUSED(a_Mark);
- if (!PushFunction(a_FnName))
- {
- return false;
- }
- if (!CallFunction(1))
- {
- return false;
- }
- GetStackValue(-1, a_Ret1);
- lua_pop(m_LuaState, 1);
- return true;
- }
-
- /** Call any 1-param 1-return Lua function in a single line: */
- template<
- typename FnT, typename ArgT1, typename RetT1
- >
- bool Call(FnT a_FnName, ArgT1 a_Arg1, const cRet & a_Mark, RetT1 & a_Ret1)
- {
- int InitialTop = lua_gettop(m_LuaState);
- UNUSED(a_Mark);
- if (!PushFunction(a_FnName))
- {
- return false;
- }
- Push(a_Arg1);
- if (!CallFunction(1))
- {
- return false;
- }
- GetStackValue(-1, a_Ret1);
- lua_pop(m_LuaState, 1);
- ASSERT(InitialTop == lua_gettop(m_LuaState));
- return true;
- }
-
- /** Call any 2-param 1-return Lua function in a single line: */
- template<
- typename FnT, typename ArgT1, typename ArgT2, typename RetT1
- >
- bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, const cRet & a_Mark, RetT1 & a_Ret1)
- {
- UNUSED(a_Mark);
- if (!PushFunction(a_FnName))
- {
- return false;
- }
- Push(a_Arg1);
- Push(a_Arg2);
- if (!CallFunction(1))
- {
- return false;
- }
- GetStackValue(-1, a_Ret1);
- lua_pop(m_LuaState, 1);
- return true;
- }
-
- /** Call any 3-param 1-return Lua function in a single line: */
- template<
- typename FnT, typename ArgT1, typename ArgT2, typename ArgT3, typename RetT1
- >
- bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, const cRet & a_Mark, RetT1 & a_Ret1)
- {
- UNUSED(a_Mark);
- if (!PushFunction(a_FnName))
- {
- return false;
- }
- Push(a_Arg1);
- Push(a_Arg2);
- Push(a_Arg3);
- if (!CallFunction(1))
- {
- return false;
- }
- GetStackValue(-1, a_Ret1);
- lua_pop(m_LuaState, 1);
- return true;
- }
-
- /** Call any 4-param 1-return Lua function in a single line: */
- template<
- typename FnT, typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename RetT1
- >
- bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, const cRet & a_Mark, RetT1 & a_Ret1)
- {
- UNUSED(a_Mark);
- if (!PushFunction(a_FnName))
- {
- return false;
- }
- Push(a_Arg1);
- Push(a_Arg2);
- Push(a_Arg3);
- Push(a_Arg4);
- if (!CallFunction(1))
- {
- return false;
- }
- GetStackValue(-1, a_Ret1);
- lua_pop(m_LuaState, 1);
- return true;
- }
-
- /** Call any 5-param 1-return Lua function in a single line: */
- template<
- typename FnT, typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename ArgT5, typename RetT1
- >
- bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, const cRet & a_Mark, RetT1 & a_Ret1)
- {
- UNUSED(a_Mark);
- if (!PushFunction(a_FnName))
- {
- return false;
- }
- Push(a_Arg1);
- Push(a_Arg2);
- Push(a_Arg3);
- Push(a_Arg4);
- Push(a_Arg5);
- if (!CallFunction(1))
- {
- return false;
- }
- GetStackValue(-1, a_Ret1);
- lua_pop(m_LuaState, 1);
- return true;
- }
-
- /** Call any 6-param 1-return Lua function in a single line: */
- template<
- typename FnT, typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename ArgT5, typename ArgT6,
- typename RetT1
- >
- bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, const cRet & a_Mark, RetT1 & a_Ret1)
- {
- UNUSED(a_Mark);
- if (!PushFunction(a_FnName))
- {
- return false;
- }
- Push(a_Arg1);
- Push(a_Arg2);
- Push(a_Arg3);
- Push(a_Arg4);
- Push(a_Arg5);
- Push(a_Arg6);
- if (!CallFunction(1))
- {
- return false;
- }
- GetStackValue(-1, a_Ret1);
- lua_pop(m_LuaState, 1);
- return true;
- }
-
- /** Call any 7-param 1-return Lua function in a single line: */
- template<
- typename FnT, typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename ArgT5, typename ArgT6,
- typename ArgT7, typename RetT1
- >
- bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, ArgT7 a_Arg7, const cRet & a_Mark, RetT1 & a_Ret1)
- {
- UNUSED(a_Mark);
- if (!PushFunction(a_FnName))
- {
- return false;
- }
- Push(a_Arg1);
- Push(a_Arg2);
- Push(a_Arg3);
- Push(a_Arg4);
- Push(a_Arg5);
- Push(a_Arg6);
- Push(a_Arg7);
- if (!CallFunction(1))
- {
- return false;
- }
- GetStackValue(-1, a_Ret1);
- lua_pop(m_LuaState, 1);
- return true;
- }
-
- /** Call any 8-param 1-return Lua function in a single line: */
- template<
- typename FnT, typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename ArgT5, typename ArgT6,
- typename ArgT7, typename ArgT8, typename RetT1
- >
- bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, ArgT7 a_Arg7, ArgT8 a_Arg8, const cRet & a_Mark, RetT1 & a_Ret1)
- {
- UNUSED(a_Mark);
- if (!PushFunction(a_FnName))
- {
- return false;
- }
- Push(a_Arg1);
- Push(a_Arg2);
- Push(a_Arg3);
- Push(a_Arg4);
- Push(a_Arg5);
- Push(a_Arg6);
- Push(a_Arg7);
- Push(a_Arg8);
- if (!CallFunction(1))
- {
- return false;
- }
- GetStackValue(-1, a_Ret1);
- lua_pop(m_LuaState, 1);
- return true;
- }
-
- /** Call any 9-param 1-return Lua function in a single line: */
- template<
- typename FnT, typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename ArgT5, typename ArgT6,
- typename ArgT7, typename ArgT8, typename ArgT9, typename RetT1
- >
- bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, ArgT7 a_Arg7, ArgT8 a_Arg8, ArgT9 a_Arg9, const cRet & a_Mark, RetT1 & a_Ret1)
- {
- UNUSED(a_Mark);
- if (!PushFunction(a_FnName))
- {
- return false;
- }
- Push(a_Arg1);
- Push(a_Arg2);
- Push(a_Arg3);
- Push(a_Arg4);
- Push(a_Arg5);
- Push(a_Arg6);
- Push(a_Arg7);
- Push(a_Arg8);
- Push(a_Arg9);
- if (!CallFunction(1))
- {
- return false;
- }
- GetStackValue(-1, a_Ret1);
- lua_pop(m_LuaState, 1);
- return true;
- }
-
- /** Call any 10-param 1-return Lua function in a single line: */
- template<
- typename FnT, typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename ArgT5, typename ArgT6,
- typename ArgT7, typename ArgT8, typename ArgT9, typename ArgT10, typename RetT1
- >
- bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, ArgT7 a_Arg7, ArgT8 a_Arg8, ArgT9 a_Arg9, ArgT10 a_Arg10, const cRet & a_Mark, RetT1 & a_Ret1)
- {
- UNUSED(a_Mark);
- if (!PushFunction(a_FnName))
- {
- return false;
- }
- Push(a_Arg1);
- Push(a_Arg2);
- Push(a_Arg3);
- Push(a_Arg4);
- Push(a_Arg5);
- Push(a_Arg6);
- Push(a_Arg7);
- Push(a_Arg8);
- Push(a_Arg9);
- Push(a_Arg10);
- if (!CallFunction(1))
- {
- return false;
- }
- GetStackValue(-1, a_Ret1);
- lua_pop(m_LuaState, 1);
- return true;
- }
-
- /** Call any 1-param 2-return Lua function in a single line: */
- template<
- typename FnT, typename ArgT1, typename RetT1, typename RetT2
- >
- bool Call(FnT a_FnName, ArgT1 a_Arg1, const cRet & a_Mark, RetT1 & a_Ret1, RetT2 & a_Ret2)
- {
- UNUSED(a_Mark);
- if (!PushFunction(a_FnName))
- {
- return false;
- }
- Push(a_Arg1);
- if (!CallFunction(2))
- {
- return false;
- }
- GetStackValue(-2, a_Ret1);
- GetStackValue(-1, a_Ret2);
- lua_pop(m_LuaState, 2);
- return true;
- }
-
- /** Call any 2-param 2-return Lua function in a single line: */
- template<
- typename FnT, typename ArgT1, typename ArgT2, typename RetT1, typename RetT2
- >
- bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, const cRet & a_Mark, RetT1 & a_Ret1, RetT2 & a_Ret2)
- {
- UNUSED(a_Mark);
- if (!PushFunction(a_FnName))
- {
- return false;
- }
- Push(a_Arg1);
- Push(a_Arg2);
- if (!CallFunction(2))
- {
- return false;
- }
- GetStackValue(-2, a_Ret1);
- GetStackValue(-1, a_Ret2);
- lua_pop(m_LuaState, 2);
- return true;
- }
-
- /** Call any 3-param 2-return Lua function in a single line: */
- template<
- typename FnT, typename ArgT1, typename ArgT2, typename ArgT3,
- typename RetT1, typename RetT2
- >
- bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, const cRet & a_Mark, RetT1 & a_Ret1, RetT2 & a_Ret2)
- {
- UNUSED(a_Mark);
- if (!PushFunction(a_FnName))
- {
- return false;
- }
- Push(a_Arg1);
- Push(a_Arg2);
- Push(a_Arg3);
- if (!CallFunction(2))
- {
- return false;
- }
- GetStackValue(-2, a_Ret1);
- GetStackValue(-1, a_Ret2);
- lua_pop(m_LuaState, 2);
- return true;
- }
-
- /** Call any 4-param 2-return Lua function in a single line: */
- template<
- typename FnT, typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4,
- typename RetT1, typename RetT2
- >
- bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, const cRet & a_Mark, RetT1 & a_Ret1, RetT2 & a_Ret2)
- {
- UNUSED(a_Mark);
- if (!PushFunction(a_FnName))
- {
- return false;
- }
- Push(a_Arg1);
- Push(a_Arg2);
- Push(a_Arg3);
- Push(a_Arg4);
- if (!CallFunction(2))
- {
- return false;
- }
- GetStackValue(-2, a_Ret1);
- GetStackValue(-1, a_Ret2);
- lua_pop(m_LuaState, 2);
- return true;
- }
-
- /** Call any 5-param 2-return Lua function in a single line: */
- template<
- typename FnT, typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename ArgT5,
- typename RetT1, typename RetT2
- >
- bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, const cRet & a_Mark, RetT1 & a_Ret1, RetT2 & a_Ret2)
- {
- UNUSED(a_Mark);
- if (!PushFunction(a_FnName))
- {
- return false;
- }
- Push(a_Arg1);
- Push(a_Arg2);
- Push(a_Arg3);
- Push(a_Arg4);
- Push(a_Arg5);
- if (!CallFunction(2))
- {
- return false;
- }
- GetStackValue(-2, a_Ret1);
- GetStackValue(-1, a_Ret2);
- lua_pop(m_LuaState, 2);
- return true;
- }
-
- /** Call any 6-param 2-return Lua function in a single line: */
- template<
- typename FnT, typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename ArgT5,
- typename ArgT6,
- typename RetT1, typename RetT2
- >
- bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, const cRet & a_Mark, RetT1 & a_Ret1, RetT2 & a_Ret2)
- {
- UNUSED(a_Mark);
- if (!PushFunction(a_FnName))
- {
- return false;
- }
- Push(a_Arg1);
- Push(a_Arg2);
- Push(a_Arg3);
- Push(a_Arg4);
- Push(a_Arg5);
- Push(a_Arg6);
- if (!CallFunction(2))
- {
- return false;
- }
- GetStackValue(-2, a_Ret1);
- GetStackValue(-1, a_Ret2);
- lua_pop(m_LuaState, 2);
- return true;
- }
-
- /** Call any 7-param 2-return Lua function in a single line: */
- template<
- typename FnT, typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename ArgT5,
- typename ArgT6, typename ArgT7,
- typename RetT1, typename RetT2
- >
- bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, ArgT7 a_Arg7, const cRet & a_Mark, RetT1 & a_Ret1, RetT2 & a_Ret2)
- {
- UNUSED(a_Mark);
- if (!PushFunction(a_FnName))
- {
- return false;
- }
- Push(a_Arg1);
- Push(a_Arg2);
- Push(a_Arg3);
- Push(a_Arg4);
- Push(a_Arg5);
- Push(a_Arg6);
- Push(a_Arg7);
- if (!CallFunction(2))
- {
- return false;
- }
- GetStackValue(-2, a_Ret1);
- GetStackValue(-1, a_Ret2);
- lua_pop(m_LuaState, 2);
- return true;
- }
-
- /** Call any 7-param 3-return Lua function in a single line: */
- template<
- typename FnT, typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename ArgT5,
- typename ArgT6, typename ArgT7,
- typename RetT1, typename RetT2, typename RetT3
- >
- bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, ArgT7 a_Arg7, const cRet & a_Mark, RetT1 & a_Ret1, RetT2 & a_Ret2, RetT3 & a_Ret3)
- {
- UNUSED(a_Mark);
- if (!PushFunction(a_FnName))
- {
- return false;
- }
- Push(a_Arg1);
- Push(a_Arg2);
- Push(a_Arg3);
- Push(a_Arg4);
- Push(a_Arg5);
- Push(a_Arg6);
- Push(a_Arg7);
- if (!CallFunction(3))
- {
- return false;
- }
- GetStackValue(-3, a_Ret1);
- GetStackValue(-2, a_Ret2);
- GetStackValue(-1, a_Ret3);
- lua_pop(m_LuaState, 3);
- return true;
- }
-
- /** Call any 8-param 3-return Lua function in a single line: */
- template<
- typename FnT, typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename ArgT5,
- typename ArgT6, typename ArgT7, typename ArgT8,
- typename RetT1, typename RetT2, typename RetT3
- >
- bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, ArgT7 a_Arg7, ArgT8 a_Arg8, const cRet & a_Mark, RetT1 & a_Ret1, RetT2 & a_Ret2, RetT3 & a_Ret3)
- {
- UNUSED(a_Mark);
- if (!PushFunction(a_FnName))
- {
- return false;
- }
- Push(a_Arg1);
- Push(a_Arg2);
- Push(a_Arg3);
- Push(a_Arg4);
- Push(a_Arg5);
- Push(a_Arg6);
- Push(a_Arg7);
- Push(a_Arg8);
- if (!CallFunction(3))
- {
- return false;
- }
- GetStackValue(-3, a_Ret1);
- GetStackValue(-2, a_Ret2);
- GetStackValue(-1, a_Ret3);
- lua_pop(m_LuaState, 3);
- return true;
- }
-
- /** Call any 9-param 5-return Lua function in a single line: */
- template<
- typename FnT, typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename ArgT5,
- typename ArgT6, typename ArgT7, typename ArgT8, typename ArgT9,
- typename RetT1, typename RetT2, typename RetT3, typename RetT4, typename RetT5
- >
- bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, ArgT7 a_Arg7, ArgT8 a_Arg8, ArgT9 a_Arg9, const cRet & a_Mark, RetT1 & a_Ret1, RetT2 & a_Ret2, RetT3 & a_Ret3, RetT4 & a_Ret4, RetT5 & a_Ret5)
- {
- UNUSED(a_Mark);
- if (!PushFunction(a_FnName))
- {
- return false;
- }
- Push(a_Arg1);
- Push(a_Arg2);
- Push(a_Arg3);
- Push(a_Arg4);
- Push(a_Arg5);
- Push(a_Arg6);
- Push(a_Arg7);
- Push(a_Arg8);
- Push(a_Arg9);
- if (!CallFunction(5))
- {
- return false;
- }
- GetStackValue(-5, a_Ret1);
- GetStackValue(-4, a_Ret2);
- GetStackValue(-3, a_Ret3);
- GetStackValue(-2, a_Ret4);
- GetStackValue(-1, a_Ret5);
- lua_pop(m_LuaState, 5);
- return true;
- }
+ // Include the cLuaState::Call() overload implementation that is generated by the gen_LuaState_Call.lua script:
+ #include "LuaState_Call.inc"
/** Returns true if the specified parameters on the stack are of the specified usertable type; also logs warning if not. Used for static functions */
diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp
index f52d970bf..88d40bfd9 100644
--- a/src/Bindings/ManualBindings.cpp
+++ b/src/Bindings/ManualBindings.cpp
@@ -4,7 +4,7 @@
#include "ManualBindings.h"
#undef TOLUA_TEMPLATE_BIND
#include "tolua++/include/tolua++.h"
-
+#include "polarssl/md5.h"
#include "Plugin.h"
#include "PluginLua.h"
#include "PluginManager.h"
@@ -25,7 +25,6 @@
#include "../BlockEntities/NoteEntity.h"
#include "../BlockEntities/MobHeadEntity.h"
#include "../BlockEntities/FlowerPotEntity.h"
-#include "md5/md5.h"
#include "../LineBlockTracer.h"
#include "../WorldStorage/SchematicFileSerializer.h"
#include "../CompositeChat.h"
@@ -2001,9 +2000,11 @@ static int tolua_cPlugin_Call(lua_State * tolua_S)
static int tolua_md5(lua_State* tolua_S)
{
- std::string SourceString = tolua_tostring(tolua_S, 1, 0);
- std::string CryptedString = md5( SourceString );
- tolua_pushstring( tolua_S, CryptedString.c_str() );
+ unsigned char Output[16];
+ size_t len = 0;
+ const unsigned char * SourceString = (const unsigned char *)lua_tolstring(tolua_S, 1, &len);
+ md5(SourceString, len, Output);
+ lua_pushlstring(tolua_S, (const char *)Output, ARRAYCOUNT(Output));
return 1;
}
diff --git a/src/Bindings/Plugin.h b/src/Bindings/Plugin.h
index c6461c861..8ba20c026 100644
--- a/src/Bindings/Plugin.h
+++ b/src/Bindings/Plugin.h
@@ -72,6 +72,7 @@ public:
virtual bool OnPlayerEating (cPlayer & a_Player) = 0;
virtual bool OnPlayerFished (cPlayer & a_Player, const cItems & a_Reward) = 0;
virtual bool OnPlayerFishing (cPlayer & a_Player, cItems & a_Reward) = 0;
+ virtual bool OnPlayerFoodLevelChange (cPlayer & a_Player, int a_NewFoodLevel) = 0;
virtual bool OnPlayerJoined (cPlayer & a_Player) = 0;
virtual bool OnPlayerLeftClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status) = 0;
virtual bool OnPlayerMoved (cPlayer & a_Player) = 0;
diff --git a/src/Bindings/PluginLua.cpp b/src/Bindings/PluginLua.cpp
index 96c5ccde7..104380ea4 100644
--- a/src/Bindings/PluginLua.cpp
+++ b/src/Bindings/PluginLua.cpp
@@ -715,6 +715,26 @@ bool cPluginLua::OnPlayerEating(cPlayer & a_Player)
+bool cPluginLua::OnPlayerFoodLevelChange(cPlayer & a_Player, int a_NewFoodLevel)
+{
+ cCSLock Lock(m_CriticalSection);
+ bool res = false;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_FOOD_LEVEL_CHANGE];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_Player, a_NewFoodLevel, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+
+
+
bool cPluginLua::OnPlayerFished(cPlayer & a_Player, const cItems & a_Reward)
{
cCSLock Lock(m_CriticalSection);
@@ -1327,18 +1347,15 @@ bool cPluginLua::OnWeatherChanging(cWorld & a_World, eWeather & a_NewWeather)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- int NewWeather = a_NewWeather;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_WEATHER_CHANGING];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{
- m_LuaState.Call((int)(**itr), &a_World, NewWeather, cLuaState::Return, res, NewWeather);
+ m_LuaState.Call((int)(**itr), &a_World, a_NewWeather, cLuaState::Return, res, a_NewWeather);
if (res)
{
- a_NewWeather = (eWeather)NewWeather;
return true;
}
}
- a_NewWeather = (eWeather)NewWeather;
return false;
}
@@ -1714,7 +1731,7 @@ bool cPluginLua::CallbackWindowClosing(int a_FnRef, cWindow & a_Window, cPlayer
ASSERT(a_FnRef != LUA_REFNIL);
cCSLock Lock(m_CriticalSection);
- bool res;
+ bool res = false;
m_LuaState.Call(a_FnRef, &a_Window, &a_Player, a_CanRefuse, cLuaState::Return, res);
return res;
}
diff --git a/src/Bindings/PluginLua.h b/src/Bindings/PluginLua.h
index 598e031c0..9c9de95c6 100644
--- a/src/Bindings/PluginLua.h
+++ b/src/Bindings/PluginLua.h
@@ -95,6 +95,7 @@ public:
virtual bool OnPlayerEating (cPlayer & a_Player) override;
virtual bool OnPlayerFished (cPlayer & a_Player, const cItems & a_Reward) override;
virtual bool OnPlayerFishing (cPlayer & a_Player, cItems & a_Reward) override;
+ virtual bool OnPlayerFoodLevelChange (cPlayer & a_Player, int a_NewFoodLevel) override;
virtual bool OnPlayerJoined (cPlayer & a_Player) override;
virtual bool OnPlayerMoved (cPlayer & a_Player) override;
virtual bool OnPlayerLeftClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status) override;
diff --git a/src/Bindings/PluginManager.cpp b/src/Bindings/PluginManager.cpp
index c50100d6f..7e6502515 100644
--- a/src/Bindings/PluginManager.cpp
+++ b/src/Bindings/PluginManager.cpp
@@ -257,18 +257,44 @@ bool cPluginManager::CallHookBlockToPickups(
bool cPluginManager::CallHookChat(cPlayer * a_Player, AString & a_Message)
{
- bool WasCommandForbidden = false;
- if (HandleCommand(a_Player, a_Message, true, WasCommandForbidden)) // We use HandleCommand as opposed to ExecuteCommand to accomodate the need to the WasCommandForbidden bool
+ // Check if the message contains a command, execute it:
+ switch (HandleCommand(a_Player, a_Message, true))
{
- return true; // Chat message was handled as command
- }
- else if (WasCommandForbidden) // Couldn't be handled as command, was it because of insufficient permissions?
- {
- return true; // Yes - message was sent in HandleCommand, abort
+ case crExecuted:
+ {
+ // The command has executed successfully
+ return true;
+ }
+
+ case crBlocked:
+ {
+ // The command was blocked by a plugin using HOOK_EXECUTE_COMMAND
+ // The plugin has most likely sent a message to the player already
+ return true;
+ }
+
+ case crError:
+ {
+ // An error in the plugin has prevented the command from executing. Report the error to the player:
+ a_Player->SendMessageFailure(Printf("Something went wrong while executing command \"%s\"", a_Message.c_str()));
+ return true;
+ }
+
+ case crNoPermission:
+ {
+ // The player is not allowed to execute this command
+ a_Player->SendMessageFailure(Printf("Forbidden command; insufficient privileges: \"%s\"", a_Message.c_str()));
+ return true;
+ }
+
+ case crUnknownCommand:
+ {
+ // This was not a known command, keep processing as a message
+ break;
+ }
}
- // Check if it was a standard command (starts with a slash)
- // If it was, we know that it was completely unrecognised (WasCommandForbidden == false)
+ // Check if the message is a command (starts with a slash). If it is, we know that it wasn't recognised:
if (!a_Message.empty() && (a_Message[0] == '/'))
{
AStringVector Split(StringSplit(a_Message, " "));
@@ -695,6 +721,25 @@ bool cPluginManager::CallHookPlayerEating(cPlayer & a_Player)
+bool cPluginManager::CallHookPlayerFoodLevelChange(cPlayer & a_Player, int a_NewFoodLevel)
+{
+ FIND_HOOK(HOOK_PLAYER_FOOD_LEVEL_CHANGE);
+ VERIFY_HOOK;
+
+ for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
+ {
+ if ((*itr)->OnPlayerFoodLevelChange(a_Player, a_NewFoodLevel))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+
+
+
bool cPluginManager::CallHookPlayerFished(cPlayer & a_Player, const cItems a_Reward)
{
FIND_HOOK(HOOK_PLAYER_FISHED);
@@ -1318,28 +1363,28 @@ bool cPluginManager::CallHookWorldTick(cWorld & a_World, float a_Dt, int a_LastT
-bool cPluginManager::HandleCommand(cPlayer * a_Player, const AString & a_Command, bool a_ShouldCheckPermissions, bool & a_WasCommandForbidden)
+cPluginManager::CommandResult cPluginManager::HandleCommand(cPlayer * a_Player, const AString & a_Command, bool a_ShouldCheckPermissions)
{
ASSERT(a_Player != NULL);
AStringVector Split(StringSplit(a_Command, " "));
if (Split.empty())
{
- return false;
+ return crUnknownCommand;
}
CommandMap::iterator cmd = m_Commands.find(Split[0]);
if (cmd == m_Commands.end())
{
// Command not found
- return false;
+ return crUnknownCommand;
}
// Ask plugins first if a command is okay to execute the command:
if (CallHookExecuteCommand(a_Player, Split))
{
LOGINFO("Player %s tried executing command \"%s\" that was stopped by the HOOK_EXECUTE_COMMAND hook", a_Player->GetName().c_str(), Split[0].c_str());
- return false;
+ return crBlocked;
}
if (
@@ -1348,15 +1393,18 @@ bool cPluginManager::HandleCommand(cPlayer * a_Player, const AString & a_Command
!a_Player->HasPermission(cmd->second.m_Permission)
)
{
- a_Player->SendMessageFailure(Printf("Forbidden command; insufficient privileges: \"%s\"", Split[0].c_str()));
LOGINFO("Player %s tried to execute forbidden command: \"%s\"", a_Player->GetName().c_str(), Split[0].c_str());
- a_WasCommandForbidden = true;
- return false;
+ return crNoPermission;
}
ASSERT(cmd->second.m_Plugin != NULL);
- return cmd->second.m_Plugin->HandleCommand(Split, a_Player);
+ if (!cmd->second.m_Plugin->HandleCommand(Split, a_Player))
+ {
+ return crError;
+ }
+
+ return crExecuted;
}
@@ -1554,7 +1602,7 @@ AString cPluginManager::GetCommandPermission(const AString & a_Command)
-bool cPluginManager::ExecuteCommand(cPlayer * a_Player, const AString & a_Command)
+cPluginManager::CommandResult cPluginManager::ExecuteCommand(cPlayer * a_Player, const AString & a_Command)
{
return HandleCommand(a_Player, a_Command, true);
}
@@ -1563,7 +1611,7 @@ bool cPluginManager::ExecuteCommand(cPlayer * a_Player, const AString & a_Comman
-bool cPluginManager::ForceExecuteCommand(cPlayer * a_Player, const AString & a_Command)
+cPluginManager::CommandResult cPluginManager::ForceExecuteCommand(cPlayer * a_Player, const AString & a_Command)
{
return HandleCommand(a_Player, a_Command, false);
}
diff --git a/src/Bindings/PluginManager.h b/src/Bindings/PluginManager.h
index be40bd2f7..d435024bb 100644
--- a/src/Bindings/PluginManager.h
+++ b/src/Bindings/PluginManager.h
@@ -57,8 +57,17 @@ public: // tolua_export
// Called each tick
virtual void Tick(float a_Dt);
-
+
// tolua_begin
+ enum CommandResult
+ {
+ crExecuted,
+ crUnknownCommand,
+ crError,
+ crBlocked,
+ crNoPermission,
+ } ;
+
enum PluginHook
{
HOOK_BLOCK_SPREAD,
@@ -87,6 +96,7 @@ public: // tolua_export
HOOK_PLAYER_EATING,
HOOK_PLAYER_FISHED,
HOOK_PLAYER_FISHING,
+ HOOK_PLAYER_FOOD_LEVEL_CHANGE,
HOOK_PLAYER_JOINED,
HOOK_PLAYER_LEFT_CLICK,
HOOK_PLAYER_MOVING,
@@ -188,6 +198,7 @@ public: // tolua_export
bool CallHookPlayerEating (cPlayer & a_Player);
bool CallHookPlayerFished (cPlayer & a_Player, const cItems a_Reward);
bool CallHookPlayerFishing (cPlayer & a_Player, cItems a_Reward);
+ bool CallHookPlayerFoodLevelChange (cPlayer & a_Player, int a_NewFoodLevel);
bool CallHookPlayerJoined (cPlayer & a_Player);
bool CallHookPlayerMoving (cPlayer & a_Player);
bool CallHookPlayerLeftClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status);
@@ -244,11 +255,11 @@ public: // tolua_export
/** Returns the permission needed for the specified command; empty string if command not found */
AString GetCommandPermission(const AString & a_Command); // tolua_export
- /** Executes the command, as if it was requested by a_Player. Checks permissions first. Returns true if executed. */
- bool ExecuteCommand(cPlayer * a_Player, const AString & a_Command); // tolua_export
+ /** Executes the command, as if it was requested by a_Player. Checks permissions first. Returns crExecuted if executed. */
+ CommandResult ExecuteCommand(cPlayer * a_Player, const AString & a_Command); // tolua_export
- /** Executes the command, as if it was requested by a_Player. Permisssions are not checked. Returns true if executed (false if not found) */
- bool ForceExecuteCommand(cPlayer * a_Player, const AString & a_Command); // tolua_export
+ /** Executes the command, as if it was requested by a_Player. Permisssions are not checked. Returns crExecuted if executed. */
+ CommandResult ForceExecuteCommand(cPlayer * a_Player, const AString & a_Command); // tolua_export
/** Removes all console command bindings that the specified plugin has made */
void RemovePluginConsoleCommands(cPlugin * a_Plugin);
@@ -321,13 +332,8 @@ private:
/** Adds the plugin into the internal list of plugins and initializes it. If initialization fails, the plugin is removed again. */
bool AddPlugin(cPlugin * a_Plugin);
- /** Tries to match a_Command to the internal table of commands, if a match is found, the corresponding plugin is called. Returns true if the command is handled. */
- bool HandleCommand(cPlayer * a_Player, const AString & a_Command, bool a_ShouldCheckPermissions, bool & a_WasCommandForbidden);
- bool HandleCommand(cPlayer * a_Player, const AString & a_Command, bool a_ShouldCheckPermissions)
- {
- bool DummyBoolean = false;
- return HandleCommand(a_Player, a_Command, a_ShouldCheckPermissions, DummyBoolean);
- }
+ /** Tries to match a_Command to the internal table of commands, if a match is found, the corresponding plugin is called. Returns crExecuted if the command is executed. */
+ cPluginManager::CommandResult HandleCommand(cPlayer * a_Player, const AString & a_Command, bool a_ShouldCheckPermissions);
} ; // tolua_export
diff --git a/src/Bindings/gen_LuaState_Call.lua b/src/Bindings/gen_LuaState_Call.lua
new file mode 100644
index 000000000..fb1797dc0
--- /dev/null
+++ b/src/Bindings/gen_LuaState_Call.lua
@@ -0,0 +1,196 @@
+
+-- gen_LuaState_Call.lua
+
+-- Generates the cLuaState::Call() function templates that are included from LuaState.h
+
+--[[
+The cLuaState::Call() family of functions provides a template-based system for calling any Lua function
+either by name or by reference with almost any number of parameters and return values. This is done by
+providing a number of overloads of the same name with variable number of template-type parameters. To
+separate the arguments from the return values, a special type of cLuaState::cRet is used.
+--]]
+
+
+
+
+print("Generating LuaState_Call.inc...")
+
+
+
+
+-- List of combinations (# params, # returns) to generate:
+local Combinations =
+{
+ -- no return values:
+ {0, 0},
+ {1, 0},
+ {2, 0},
+ {3, 0},
+ {4, 0},
+
+ -- 1 return value:
+ {0, 1},
+ {1, 1},
+ {2, 1},
+ {3, 1},
+ {4, 1},
+ {5, 1},
+ {6, 1},
+ {7, 1},
+ {8, 1},
+ {9, 1},
+ {10, 1},
+
+ -- 2 return values:
+ {0, 2},
+ {1, 2},
+ {2, 2},
+ {3, 2},
+ {4, 2},
+ {5, 2},
+ {6, 2},
+ {7, 2},
+ {8, 2},
+ {9, 2},
+
+ -- Special combinations:
+ {7, 3},
+ {8, 3},
+ {9, 5},
+}
+
+
+
+
+--- Writes a single overloaded function definition for the specified number of params and returns into f
+--[[
+The format for the generated function is this:
+/** Call the specified 3-param 2-return Lua function:
+Returns true if call succeeded, false if there was an error. */
+template <typename FnT, typename ParamT1, typename ParamT2, typename ParamT3, typename RetT1, typename RetT2>
+bool Call(FnT a_Function, ParamT1 a_Param1, ParamT2 a_Param2, ParamT3 a_Param3, const cLuaState::cRet & a_RetMark, RetT1 & a_Ret1, RetT2 & a_Ret2)
+{
+ UNUSED(a_RetMark);
+ if (!PushFunction(a_Function))
+ {
+ return false;
+ }
+ Push(a_Param1);
+ Push(a_Param2);
+ Push(a_Param3);
+ if (!CallFunction(2))
+ {
+ return false;
+ }
+ GetStackValue(-2, a_Ret1);
+ GetStackValue(-1, a_Ret2);
+ lua_pop(m_LuaState, 2);
+ return true;
+}
+Note especially the negative numbers in GetStackValue() calls.
+--]]
+local function WriteOverload(f, a_NumParams, a_NumReturns)
+ -- Write the function doxy-comments:
+ f:write("/** Call the specified ", a_NumParams, "-param ", a_NumReturns, "-return Lua function:\n")
+ f:write("Returns true if call succeeded, false if there was an error. */\n")
+
+ -- Write the template <...> line:
+ f:write("template <typename FnT")
+ for i = 1, a_NumParams do
+ f:write(", typename ParamT", i)
+ end
+ if (a_NumReturns > 0) then
+ for i = 1, a_NumReturns do
+ f:write(", typename RetT", i)
+ end
+ end
+ f:write(">\n")
+
+ -- Write the function signature:
+ f:write("bool Call(")
+ f:write("FnT a_Function")
+ for i = 1, a_NumParams do
+ f:write(", ParamT", i, " a_Param", i)
+ end
+ if (a_NumReturns > 0) then
+ f:write(", const cLuaState::cRet & a_RetMark")
+ for i = 1, a_NumReturns do
+ f:write(", RetT", i, " & a_Ret", i)
+ end
+ end
+ f:write(")\n")
+
+ -- Common code:
+ f:write("{\n")
+ if (a_NumReturns > 0) then
+ f:write("\tUNUSED(a_RetMark);\n")
+ end
+ f:write("\tif (!PushFunction(a_Function))\n")
+ f:write("\t{\n")
+ f:write("\t\treturn false;\n")
+ f:write("\t}\n")
+
+ -- Push the params:
+ for i = 1, a_NumParams do
+ f:write("\tPush(a_Param", i, ");\n")
+ end
+
+ -- Call the function:
+ f:write("\tif (!CallFunction(", a_NumReturns, "))\n")
+ f:write("\t{\n")
+ f:write("\t\treturn false;\n")
+ f:write("\t}\n")
+
+ -- Get the return values:
+ for i = 1, a_NumReturns do
+ f:write("\tGetStackValue(", -1 - a_NumReturns + i, ", a_Ret", i, ");\n")
+ end
+
+ -- Pop the returns off the stack, if needed:
+ if (a_NumReturns > 0) then
+ f:write("\tlua_pop(m_LuaState, ", a_NumReturns, ");\n")
+ end
+
+ -- Everything ok:
+ f:write("\treturn true;\n")
+ f:write("}\n")
+
+ -- Separate from the next function:
+ f:write("\n\n\n\n\n")
+end
+
+
+
+
+
+local f = assert(io.open("LuaState_Call.inc", "w"))
+
+-- Write file header:
+f:write([[
+// LuaState_Call.inc
+
+// This file is auto-generated by gen_LuaState_Call.lua
+// Make changes to the generator instead of to this file!
+
+// This file contains the various overloads for the cLuaState::Call() function
+// Each overload handles a different number of parameters / return values
+]])
+f:write("\n\n\n\n\n")
+
+-- Write out a template function for each overload:
+for _, combination in ipairs(Combinations) do
+ WriteOverload(f, combination[1], combination[2])
+end
+
+-- Close the generated file
+f:close()
+
+
+
+
+
+print("LuaState_Call.inc generated")
+
+
+
+
diff --git a/src/Bindings/virtual_method_hooks.lua b/src/Bindings/virtual_method_hooks.lua
index c610d424f..8ad30bf78 100644
--- a/src/Bindings/virtual_method_hooks.lua
+++ b/src/Bindings/virtual_method_hooks.lua
@@ -3,6 +3,20 @@ local disable_virtual_hooks = true
local enable_pure_virtual = true
local default_private_access = false
+
+
+
+
+-- Code generators used by the build
+-- Note that these are not exactly needed for the bindings, but rather we
+-- misuse tolua's Lua engine to process files for us
+dofile("gen_LuaState_Call.lua")
+
+
+
+
+
+
local access = {public = 0, protected = 1, private = 2}
function preparse_hook(p)