diff --git a/source/Bindings.cpp b/source/Bindings.cpp index 03510288c..d2a97f34e 100644 --- a/source/Bindings.cpp +++ b/source/Bindings.cpp @@ -1,6 +1,6 @@ /* ** Lua binding: AllToLua -** Generated automatically by tolua++-1.0.92 on 06/19/12 23:28:50. +** Generated automatically by tolua++-1.0.92 on 07/02/12 10:32:19. */ #ifndef __cplusplus @@ -10774,40 +10774,6 @@ static int tolua_AllToLua_cWorld_GetNumPlayers00(lua_State* tolua_S) } #endif //#ifndef TOLUA_DISABLE -/* method: GetPlayer of class cWorld */ -#ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_GetPlayer00 -static int tolua_AllToLua_cWorld_GetPlayer00(lua_State* tolua_S) -{ -#ifndef TOLUA_RELEASE - tolua_Error tolua_err; - if ( - !tolua_isusertype(tolua_S,1,"cWorld",0,&tolua_err) || - !tolua_isstring(tolua_S,2,0,&tolua_err) || - !tolua_isnoobj(tolua_S,3,&tolua_err) - ) - goto tolua_lerror; - else -#endif - { - cWorld* self = (cWorld*) tolua_tousertype(tolua_S,1,0); - const char* a_PlayerName = ((const char*) tolua_tostring(tolua_S,2,0)); -#ifndef TOLUA_RELEASE - if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetPlayer'", NULL); -#endif - { - cPlayer* tolua_ret = (cPlayer*) self->GetPlayer(a_PlayerName); - tolua_pushusertype(tolua_S,(void*)tolua_ret,"cPlayer"); - } - } - return 1; -#ifndef TOLUA_RELEASE - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'GetPlayer'.",&tolua_err); - return 0; -#endif -} -#endif //#ifndef TOLUA_DISABLE - /* method: UpdateSign of class cWorld */ #ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_UpdateSign00 static int tolua_AllToLua_cWorld_UpdateSign00(lua_State* tolua_S) @@ -21249,7 +21215,6 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S) tolua_function(tolua_S,"GetMaxPlayers",tolua_AllToLua_cWorld_GetMaxPlayers00); tolua_function(tolua_S,"SetMaxPlayers",tolua_AllToLua_cWorld_SetMaxPlayers00); tolua_function(tolua_S,"GetNumPlayers",tolua_AllToLua_cWorld_GetNumPlayers00); - tolua_function(tolua_S,"GetPlayer",tolua_AllToLua_cWorld_GetPlayer00); tolua_function(tolua_S,"UpdateSign",tolua_AllToLua_cWorld_UpdateSign00); tolua_function(tolua_S,"RegenerateChunk",tolua_AllToLua_cWorld_RegenerateChunk00); tolua_function(tolua_S,"GenerateChunk",tolua_AllToLua_cWorld_GenerateChunk00); diff --git a/source/Bindings.h b/source/Bindings.h index fa12076ed..a4762b61d 100644 --- a/source/Bindings.h +++ b/source/Bindings.h @@ -1,6 +1,6 @@ /* ** Lua binding: AllToLua -** Generated automatically by tolua++-1.0.92 on 06/19/12 23:28:50. +** Generated automatically by tolua++-1.0.92 on 07/02/12 10:32:19. */ /* Exported function */ diff --git a/source/ManualBindings.cpp b/source/ManualBindings.cpp index 92414d897..722e71a54 100644 --- a/source/ManualBindings.cpp +++ b/source/ManualBindings.cpp @@ -17,6 +17,9 @@ #include "md5/md5.h" + + + static bool report_errors(lua_State* lua, int status) { if ( status!=0 ) @@ -30,6 +33,9 @@ static bool report_errors(lua_State* lua, int status) } + + + /**************************** * Lua bound functions with special return types **/ @@ -102,6 +108,91 @@ static int tolua_LOGERROR(lua_State* tolua_S) +static int tolua_cWorld_DoWithPlayer(lua_State * tolua_S) +{ + int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */ + if ((NumArgs != 2) && (NumArgs != 3)) + { + LOGWARN("Error in function call 'cWorld:DoWithPlayer()': Requires 2 or 3 arguments, got %i", NumArgs ); + return 0; + } + + cWorld * self = (cWorld *) tolua_tousertype(tolua_S, 1, 0); + + const char * PlayerName = tolua_tocppstring(tolua_S, 2, ""); + if ((PlayerName == NULL) || (PlayerName[0] == 0)) + { + LOGWARN("Error in function call 'cWorld:DoWithPlayer()': Expected a non-empty string for parameter #1"); + return 0; + } + if (!lua_isfunction( tolua_S, 3)) + { + LOGWARN("Error in function call 'cWorld:DoWithPlayer()': Expected a function for parameter #2"); + 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 == 3) + { + TableRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX); + if (TableRef == LUA_REFNIL) + { + LOGWARN("Error in function call 'cWorld:DoWithPlayer()': Could not get value reference of parameter #3"); + 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 'cWorld:DoWithPlayer()': Could not get function reference of parameter #2"); + return 0; + } + + class cLuaCallback : public cItemCallback + { + public: + cLuaCallback(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_Item) override + { + lua_rawgeti( LuaState, LUA_REGISTRYINDEX, FuncRef); /* Push function reference */ + tolua_pushusertype(LuaState, a_Item, "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); + report_errors(LuaState, s); + return true; + } + lua_State * LuaState; + int FuncRef; + int TableRef; + } Callback(tolua_S, FuncRef, TableRef); + + bool bRetVal = self->DoWithPlayer(PlayerName, 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_FOREACHINCHUNK(CONTAINER,ITEM,FOREACH,FNNAME) \ static int FNNAME(lua_State * tolua_S) \ { \ @@ -601,6 +692,7 @@ void ManualBindings::Bind( lua_State* tolua_S ) tolua_function(tolua_S, "ForEachEntityInChunk", tolua_cWorld_ForEachEntityInChunk); tolua_function(tolua_S, "ForEachChestInChunk", tolua_cWorld_ForEachChestInChunk); tolua_function(tolua_S, "ForEachFurnaceInChunk", tolua_cWorld_ForEachFurnaceInChunk); + tolua_function(tolua_S, "DoWithPlayer", tolua_cWorld_DoWithPlayer); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cPlugin"); diff --git a/source/cWorld.cpp b/source/cWorld.cpp index e438760af..2c732df7f 100644 --- a/source/cWorld.cpp +++ b/source/cWorld.cpp @@ -1529,64 +1529,27 @@ bool cWorld::ForEachPlayer(cPlayerListCallback & a_Callback) -// TODO: This interface is dangerous! -cPlayer* cWorld::GetPlayer( const char* a_PlayerName ) + +bool cWorld::DoWithPlayer(const AString & a_PlayerName, cPlayerListCallback & a_Callback) { - cPlayer* BestMatch = 0; - unsigned int MatchedLetters = 0; - unsigned int NumMatches = 0; - bool bPerfectMatch = false; - - unsigned int NameLength = strlen( a_PlayerName ); + // Calls the callback for each player in the list cCSLock Lock(m_CSPlayers); - for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); itr++ ) + for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { - std::string Name = (*itr)->GetName(); - if( NameLength > Name.length() ) continue; // Definitely not a match - - for (unsigned int i = 0; i < NameLength; i++) + if ((*itr)->GetName() == a_PlayerName) { - char c1 = (char)toupper( a_PlayerName[i] ); - char c2 = (char)toupper( Name[i] ); - if( c1 == c2 ) - { - if( i+1 > MatchedLetters ) - { - MatchedLetters = i+1; - BestMatch = *itr; - } - if( i+1 == NameLength ) - { - NumMatches++; - if( NameLength == Name.length() ) - { - bPerfectMatch = true; - break; - } - } - } - else - { - if( BestMatch == *itr ) BestMatch = 0; - break; - } - if( bPerfectMatch ) - break; + a_Callback.Item(*itr); + return true; } - } - if ( NumMatches == 1 ) - { - return BestMatch; - } - - // More than one matches, so it's undefined. Return NULL instead - return NULL; + } // for itr - m_Players[] + return false; } +// TODO: This interface is dangerous! cPlayer * cWorld::FindClosestPlayer(const Vector3f & a_Pos, float a_SightLimit) { cTracer LineOfSight(this); diff --git a/source/cWorld.h b/source/cWorld.h index b356bdf0a..f885bfd35 100644 --- a/source/cWorld.h +++ b/source/cWorld.h @@ -133,12 +133,12 @@ public: /// Calls the callback for each player in the list; returns true if all players processed, false if the callback aborted by returning true bool ForEachPlayer(cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS << + + /// Calls the callback for the player of the given name; returns true if the player was found and the callback called, false if player not found. Callback return ignored + bool DoWithPlayer(const AString & a_PlayerName, cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS << unsigned int GetNumPlayers(); //tolua_export - // TODO: This interface is dangerous - rewrite to DoWithPlayer(playername, action) - cPlayer * GetPlayer( const char * a_PlayerName ); //tolua_export - // TODO: This interface is dangerous - rewrite to DoWithClosestPlayer(pos, sight, action) cPlayer * FindClosestPlayer(const Vector3f & a_Pos, float a_SightLimit);