diff options
Diffstat (limited to 'source/ManualBindings.cpp')
-rw-r--r-- | source/ManualBindings.cpp | 252 |
1 files changed, 86 insertions, 166 deletions
diff --git a/source/ManualBindings.cpp b/source/ManualBindings.cpp index 8349f52f0..383f792b2 100644 --- a/source/ManualBindings.cpp +++ b/source/ManualBindings.cpp @@ -102,177 +102,97 @@ static int tolua_LOGERROR(lua_State* tolua_S) -static int tolua_cRoot_ForEachWorld(lua_State * tolua_S) -{ - int NumArgs = lua_gettop( tolua_S ) - 1; // This includes 'self' - if ((NumArgs != 1) && (NumArgs != 2)) - { - LOGWARN("Error in function call 'ForEachWorld': Requires 1 or 2 arguments, got %i", NumArgs); - return 0; - } - - cRoot * self = (cRoot *)tolua_tousertype(tolua_S, 1, 0); - - if (!lua_isfunction(tolua_S, 2)) - { - LOGWARN("Error in function call 'ForEachWorld': Expected a function for parameter #1"); - return 0; - } - - // luaL_ref gets reference to value on top of the stack, the table is the last argument and therefore on the top - int TableRef = LUA_REFNIL; - if( NumArgs == 2 ) - { - TableRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX); - if( TableRef == LUA_REFNIL ) - { - LOGWARN("Error in function call 'ForEachWorld': Could not get value reference of parameter #2"); - return 0; - } - } - - // table value is popped, and now function is on top of the stack - int FuncRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX); - if( FuncRef == LUA_REFNIL ) - { - LOGWARN("Error in function call 'ForEachWorld': Could not get function reference of parameter #1"); - return 0; - } - - class cLuaWorldCallback : public cWorldListCallback - { - public: - cLuaWorldCallback( lua_State* a_LuaState, int a_FuncRef, int a_TableRef ) - : LuaState( a_LuaState ) - , FuncRef( a_FuncRef ) - , TableRef( a_TableRef ) - {} - - private: - virtual bool Item(cWorld * a_World) override - { - lua_rawgeti( LuaState, LUA_REGISTRYINDEX, FuncRef); // Push function reference - tolua_pushusertype( LuaState, a_World, "cWorld" ); - if (TableRef != LUA_REFNIL) - { - lua_rawgeti(LuaState, LUA_REGISTRYINDEX, TableRef); // Push table reference - } - - int s = lua_pcall( LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0); - if (report_errors(LuaState, s)) - { - return true; // break enumeration - } - - if (lua_isboolean( LuaState, -1)) - { - return (tolua_toboolean( LuaState, -1, 0) > 0); - } - return false; // continue enumeration - } - lua_State* LuaState; - int FuncRef; - int TableRef; - } Callback( tolua_S, FuncRef, TableRef ); - - bool bRetVal = self->ForEachWorld(Callback); - - // Unreference the values again, so the LUA_REGISTRYINDEX can make place for other references - luaL_unref( tolua_S, LUA_REGISTRYINDEX, TableRef ); - luaL_unref( tolua_S, LUA_REGISTRYINDEX, FuncRef ); - - // Push return value on stack - tolua_pushboolean( tolua_S, bRetVal ); - return 1; +#define DEFINE_LUA_FOREACH(CONTAINER,ITEM,FOREACH,FNNAME) \ +static int FNNAME(lua_State * tolua_S) \ +{ \ + int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */ \ + if( NumArgs != 1 && NumArgs != 2) \ + { \ + LOGWARN("Error in function call '" #FOREACH "': Requires 1 or 2 arguments, got %i", NumArgs ); \ + return 0; \ + } \ + \ + CONTAINER * self = (CONTAINER *) tolua_tousertype(tolua_S, 1, 0); \ + \ + if (!lua_isfunction( tolua_S, 2)) \ + { \ + LOGWARN("Error in function call '" #FOREACH "': Expected a function for parameter #1"); \ + return 0; \ + } \ + \ + /* luaL_ref gets reference to value on top of the stack, the table is the last argument and therefore on the top */ \ + int TableRef = LUA_REFNIL; \ + if (NumArgs == 2) \ + { \ + TableRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX); \ + if (TableRef == LUA_REFNIL) \ + { \ + LOGWARN("Error in function call '" #FOREACH "': Could not get value reference of parameter #2"); \ + return 0; \ + } \ + } \ + \ + /* table value is popped, and now function is on top of the stack */ \ + int FuncRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX); \ + if (FuncRef == LUA_REFNIL) \ + { \ + LOGWARN("Error in function call '" #FOREACH "': Could not get function reference of parameter #1"); \ + return 0; \ + } \ + \ + class cLuaPlayerCallback : public cItemCallback<ITEM> \ + { \ + public: \ + cLuaPlayerCallback(lua_State* a_LuaState, int a_FuncRef, int a_TableRef) \ + : LuaState( a_LuaState ) \ + , FuncRef( a_FuncRef ) \ + , TableRef( a_TableRef ) \ + {} \ + \ + private: \ + virtual bool Item(ITEM * a_Item) override \ + { \ + lua_rawgeti( LuaState, LUA_REGISTRYINDEX, FuncRef); /* Push function reference */ \ + tolua_pushusertype( LuaState, a_Item, #ITEM ); \ + if (TableRef != LUA_REFNIL) \ + { \ + lua_rawgeti( LuaState, LUA_REGISTRYINDEX, TableRef); /* Push table reference */ \ + } \ + \ + int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0); \ + if (report_errors(LuaState, s)) \ + { \ + return true; /* Abort enumeration */ \ + } \ + \ + if (lua_isboolean(LuaState, -1)) \ + { \ + return (tolua_toboolean( LuaState, -1, 0) > 0); \ + } \ + return false; /* Continue enumeration */ \ + } \ + lua_State * LuaState; \ + int FuncRef; \ + int TableRef; \ + } Callback(tolua_S, FuncRef, TableRef); \ + \ + bool bRetVal = self->FOREACH(Callback); \ + \ + /* Unreference the values again, so the LUA_REGISTRYINDEX can make place for other references */ \ + luaL_unref(tolua_S, LUA_REGISTRYINDEX, TableRef); \ + luaL_unref(tolua_S, LUA_REGISTRYINDEX, FuncRef); \ + \ + /* Push return value on stack */ \ + tolua_pushboolean(tolua_S, bRetVal ); \ + return 1; \ } - -static int tolua_cWorld_ForEachPlayer(lua_State* tolua_S) -{ - int NumArgs = lua_gettop( tolua_S )-1; // This includes 'self' - if( NumArgs != 1 && NumArgs != 2) - { - LOGWARN("Error in function call 'ForEachPlayer': Requires 1 or 2 arguments, got %i", NumArgs ); - return 0; - } - - cWorld* self = (cWorld*) tolua_tousertype(tolua_S,1,0); - - if( !lua_isfunction( tolua_S, 2 ) ) - { - LOGWARN("Error in function call 'ForEachPlayer': Expected a function for parameter #1"); - return 0; - } - - // luaL_ref gets reference to value on top of the stack, the table is the last argument and therefore on the top - int TableRef = LUA_REFNIL; - if( NumArgs == 2 ) - { - TableRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX); - if( TableRef == LUA_REFNIL ) - { - LOGWARN("Error in function call 'ForEachPlayer': Could not get value reference of parameter #2"); - return 0; - } - } - - // table value is popped, and now function is on top of the stack - int FuncRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX); - if( FuncRef == LUA_REFNIL ) - { - LOGWARN("Error in function call 'ForEachPlayer': Could not get function reference of parameter #1"); - return 0; - } - - class cLuaPlayerCallback : public cPlayerListCallback - { - public: - cLuaPlayerCallback( lua_State* a_LuaState, int a_FuncRef, int a_TableRef ) - : LuaState( a_LuaState ) - , FuncRef( a_FuncRef ) - , TableRef( a_TableRef ) - {} - - private: - virtual bool Item(cPlayer * a_Player) override - { - lua_rawgeti( LuaState, LUA_REGISTRYINDEX, FuncRef); // Push function reference - tolua_pushusertype( LuaState, a_Player, "cPlayer" ); - if( TableRef != LUA_REFNIL ) - { - lua_rawgeti( LuaState, LUA_REGISTRYINDEX, TableRef); // Push table reference - } - - int s = lua_pcall( LuaState, (TableRef==LUA_REFNIL?1:2), 1, 0); - if( report_errors( LuaState, s ) ) - { - return true; // Abort enumeration - } - - if( lua_isboolean( LuaState, -1 ) ) - { - return (tolua_toboolean( LuaState, -1, 0) > 0); - } - return false; // Continue enumeration - } - lua_State * LuaState; - int FuncRef; - int TableRef; - } Callback( tolua_S, FuncRef, TableRef ); - - bool bRetVal = self->ForEachPlayer( Callback ); - - // Unreference the values again, so the LUA_REGISTRYINDEX can make place for other references - luaL_unref( tolua_S, LUA_REGISTRYINDEX, TableRef ); - luaL_unref( tolua_S, LUA_REGISTRYINDEX, FuncRef ); - - // Push return value on stack - tolua_pushboolean( tolua_S, bRetVal ); - return 1; -} +// Define the ForEach enumerators: +DEFINE_LUA_FOREACH(cWorld,cPlayer,ForEachPlayer, tolua_cWorld_ForEachPlayer); +DEFINE_LUA_FOREACH(cRoot, cWorld, ForEachWorld, tolua_cRoot_ForEachWorld); |