1
0

Added a GetClassStatic function to all entities, as well as cFurnaceEntity, cChestEntity and cWorld

Using templates to generate ForEach* functions instead of MACROS
Better error reporting in ForEach* functions

git-svn-id: http://mc-server.googlecode.com/svn/trunk@1191 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
faketruth 2013-02-02 23:55:29 +00:00
parent 5856500be7
commit fdcad8a72d
6 changed files with 433 additions and 415 deletions

View File

@ -31,6 +31,8 @@ public:
virtual ~cChestEntity(); virtual ~cChestEntity();
virtual void Destroy(); virtual void Destroy();
static const char * GetClassStatic() { return "cChestEntity"; }
const cItem * GetSlot(int a_Slot) const; // tolua_export const cItem * GetSlot(int a_Slot) const; // tolua_export
void SetSlot(int a_Slot, const cItem & a_Item ); // tolua_export void SetSlot(int a_Slot, const cItem & a_Item ); // tolua_export

View File

@ -70,7 +70,19 @@ cEntity::~cEntity()
CLASS_DEF_GETCLASS(cEntity); const char * cEntity::GetClass(void) const
{
return "cEntity";
}
const char * cEntity::GetClassStatic(void)
{
return "cEntity";
}

View File

@ -11,31 +11,6 @@
#define CLASS_PROT_ISA() virtual bool IsA(const char * a_EntityType) const override;
#define CLASS_PROT_GETCLASS() virtual const char * GetClass (void) const override;
#define CLASS_PROT_GETPARENT() virtual const char * GetParentClass(void) const override;
#define CLASS_PROTOTYPE() \
CLASS_PROT_ISA(); \
CLASS_PROT_GETCLASS(); \
CLASS_PROT_GETPARENT();
#define CLASS_DEF_ISA(classname) \
bool classname::IsA(const char * a_ClassName) const \
{ \
return ((strcmp(a_ClassName, #classname) == 0) || super::IsA(a_ClassName)); \
}
#define CLASS_DEF_GETCLASS(classname) \
const char * classname::GetClass(void) const \
{ \
return #classname; \
}
#define CLASS_DEFINITION(classname) \
CLASS_DEF_ISA(classname) \
CLASS_DEF_GETCLASS(classname)
// Place this macro in the header of each cEntity descendant class and you're done :) // Place this macro in the header of each cEntity descendant class and you're done :)
#define CLASS_PROTODEF(classname) \ #define CLASS_PROTODEF(classname) \
virtual bool IsA(const char * a_ClassName) const override\ virtual bool IsA(const char * a_ClassName) const override\
@ -46,6 +21,10 @@
{ \ { \
return #classname; \ return #classname; \
} \ } \
static const char * GetClassStatic(void) \
{ \
return #classname; \
} \
virtual const char * GetParentClass(void) const override \ virtual const char * GetParentClass(void) const override \
{ \ { \
return super::GetClass(); \ return super::GetClass(); \
@ -109,6 +88,9 @@ public:
/// Returns the topmost class name for the object /// Returns the topmost class name for the object
virtual const char * GetClass(void) const; virtual const char * GetClass(void) const;
// Returns the class name of this class
static const char * GetClassStatic(void);
/// Returns the topmost class's parent class name for the object. cEntity returns an empty string (no parent). /// Returns the topmost class's parent class name for the object. cEntity returns an empty string (no parent).
virtual const char * GetParentClass(void) const; virtual const char * GetParentClass(void) const;

View File

@ -30,6 +30,8 @@ public:
virtual ~cFurnaceEntity(); virtual ~cFurnaceEntity();
virtual void Destroy(); virtual void Destroy();
static const char * GetClassStatic() { return "cFurnaceEntity"; }
bool LoadFromFile(cFile & a_File); // deprecated format bool LoadFromFile(cFile & a_File); // deprecated format
bool LoadFromJson(const Json::Value& a_Value ); bool LoadFromJson(const Json::Value& a_Value );

View File

@ -13,6 +13,8 @@
#include "WebAdmin.h" #include "WebAdmin.h"
#include "StringMap.h" #include "StringMap.h"
#include "ClientHandle.h" #include "ClientHandle.h"
#include "ChestEntity.h"
#include "FurnaceEntity.h"
#include "md5/md5.h" #include "md5/md5.h"
@ -26,6 +28,54 @@ bool report_errors(lua_State* lua, int status);
/****************************
* Better error reporting for Lua
**/
int tolua_do_error(lua_State* L, const char * a_pMsg, tolua_Error * a_pToLuaError)
{
// Retrieve current function name
lua_Debug entry;
ASSERT( lua_getstack(L, 0, &entry) );
ASSERT( lua_getinfo(L, "n", &entry) );
// Insert function name into error msg
AString msg(a_pMsg);
ReplaceString(msg, "#funcname#", entry.name?entry.name:"?");
// Send the error to Lua
tolua_error(L, msg.c_str(), a_pToLuaError);
return 0;
}
int lua_do_error(lua_State* L, const char * a_pFormat, ...)
{
// Retrieve current function name
lua_Debug entry;
ASSERT( lua_getstack(L, 0, &entry) );
ASSERT( lua_getinfo(L, "n", &entry) );
// Insert function name into error msg
AString msg(a_pFormat);
ReplaceString(msg, "#funcname#", entry.name?entry.name:"?");
// Copied from luaL_error and modified
va_list argp;
va_start(argp, a_pFormat);
luaL_where(L, 1);
lua_pushvfstring(L, msg.c_str(), argp);
va_end(argp);
lua_concat(L, 2);
return lua_error(L);
}
/**************************** /****************************
* Lua bound functions with special return types * Lua bound functions with special return types
**/ **/
@ -98,395 +148,365 @@ static int tolua_LOGERROR(lua_State* tolua_S)
#define DEFINE_LUA_DOWITH(CONTAINER,ITEM,FOREACH,FNNAME) \ template<
static int FNNAME(lua_State * tolua_S) \ class Ty1,
{ \ class Ty2,
int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */ \ bool (Ty1::*Func1)(const AString &, cItemCallback<Ty2> &)
if ((NumArgs != 2) && (NumArgs != 3)) \ >
{ \ static int tolua_DoWith(lua_State* tolua_S)
LOGWARN("Error in function call '" #FOREACH "': Requires 2 or 3 arguments, got %i", NumArgs ); \ {
return 0; \ int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */
} \ if ((NumArgs != 2) && (NumArgs != 3))
\ {
CONTAINER * self = (CONTAINER *) tolua_tousertype(tolua_S, 1, 0); \ return lua_do_error(tolua_S, "Error in function call '#funcname#': Requires 2 or 3 arguments, got %i", NumArgs);
\ }
const char * ItemName = tolua_tocppstring(tolua_S, 2, ""); \
if ((ItemName == NULL) || (ItemName[0] == 0)) \ Ty1 * self = (Ty1 *) tolua_tousertype(tolua_S, 1, 0);
{ \
LOGWARN("Error in function call '" #FOREACH "': Expected a non-empty string for parameter #1"); \ const char * ItemName = tolua_tocppstring(tolua_S, 2, "");
return 0; \ if ((ItemName == NULL) || (ItemName[0] == 0))
} \ {
if (!lua_isfunction( tolua_S, 3)) \ return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a non-empty string for parameter #1", NumArgs);
{ \ }
LOGWARN("Error in function call '" #FOREACH "': Expected a function for parameter #2"); \ if (!lua_isfunction( tolua_S, 3))
return 0; \ {
} \ return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a function for parameter #2", NumArgs);
\ }
/* 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; \ /* luaL_ref gets reference to value on top of the stack, the table is the last argument and therefore on the top */
if (NumArgs == 3) \ int TableRef = LUA_REFNIL;
{ \ if (NumArgs == 3)
TableRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX); \ {
if (TableRef == LUA_REFNIL) \ TableRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
{ \ if (TableRef == LUA_REFNIL)
LOGWARN("Error in function call '" #FOREACH "': Could not get value reference of parameter #3"); \ {
return 0; \ return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get value reference of parameter #3", NumArgs);
} \ }
} \ }
\
/* table value is popped, and now function is on top of the stack */ \ /* table value is popped, and now function is on top of the stack */
int FuncRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX); \ int FuncRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
if (FuncRef == LUA_REFNIL) \ if (FuncRef == LUA_REFNIL)
{ \ {
LOGWARN("Error in function call '" #FOREACH "': Could not get function reference of parameter #2"); \ return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #2", NumArgs);
return 0; \ }
} \
\ class cLuaCallback : public cItemCallback<Ty2>
class cLuaCallback : public cItemCallback<ITEM> \ {
{ \ public:
public: \ cLuaCallback(lua_State* a_LuaState, int a_FuncRef, int a_TableRef)
cLuaCallback(lua_State* a_LuaState, int a_FuncRef, int a_TableRef) \ : LuaState( a_LuaState )
: LuaState( a_LuaState ) \ , FuncRef( a_FuncRef )
, FuncRef( a_FuncRef ) \ , TableRef( a_TableRef )
, TableRef( a_TableRef ) \ {}
{} \
\ private:
private: \ virtual bool Item(Ty2 * a_Item) override
virtual bool Item(ITEM * a_Item) override \ {
{ \ lua_rawgeti( LuaState, LUA_REGISTRYINDEX, FuncRef); /* Push function reference */
lua_rawgeti( LuaState, LUA_REGISTRYINDEX, FuncRef); /* Push function reference */ \ tolua_pushusertype(LuaState, a_Item, Ty2::GetClassStatic());
tolua_pushusertype(LuaState, a_Item, #ITEM); \ if (TableRef != LUA_REFNIL)
if (TableRef != LUA_REFNIL) \ {
{ \ lua_rawgeti( LuaState, LUA_REGISTRYINDEX, TableRef); /* Push table reference */
lua_rawgeti( LuaState, LUA_REGISTRYINDEX, TableRef); /* Push table reference */ \ }
} \
\ int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0);
int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0); \ report_errors(LuaState, s);
report_errors(LuaState, s); \ return true;
return true; \ }
} \ lua_State * LuaState;
lua_State * LuaState; \ int FuncRef;
int FuncRef; \ int TableRef;
int TableRef; \ } Callback(tolua_S, FuncRef, TableRef);
} Callback(tolua_S, FuncRef, TableRef); \
\
bool bRetVal = self->FOREACH(ItemName, Callback); \ bool bRetVal = (self->*Func1)(ItemName, Callback);
\
/* Unreference the values again, so the LUA_REGISTRYINDEX can make place for other references */ \ /* 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, TableRef);
luaL_unref(tolua_S, LUA_REGISTRYINDEX, FuncRef); \ luaL_unref(tolua_S, LUA_REGISTRYINDEX, FuncRef);
\
/* Push return value on stack */ \ /* Push return value on stack */
tolua_pushboolean(tolua_S, bRetVal ); \ tolua_pushboolean(tolua_S, bRetVal );
return 1; \ return 1;
} }
#define DEFINE_LUA_DOWITH_XYZ(CONTAINER,ITEM,FOREACH,FNNAME) \
static int FNNAME(lua_State * tolua_S) \ template< class Ty1,
{ \ class Ty2,
int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */ \ bool (Ty1::*Func1)(int, int, int, cItemCallback<Ty2> &) >
if ((NumArgs != 4) && (NumArgs != 5)) \ static int tolua_DoWithXYZ(lua_State* tolua_S)
{ \ {
LOGWARN("Error in function call '" #FOREACH "': Requires 4 or 5 arguments, got %i", NumArgs ); \ int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */
return 0; \ if ((NumArgs != 4) && (NumArgs != 5))
} \ {
\ return lua_do_error(tolua_S, "Error in function call '#funcname#': Requires 4 or 5 arguments, got %i", NumArgs);
CONTAINER * self = (CONTAINER *) tolua_tousertype(tolua_S, 1, 0); \ }
if (!lua_isnumber(tolua_S, 2) || !lua_isnumber(tolua_S, 3) || !lua_isnumber(tolua_S, 4)) \
{ \ Ty1 * self = (Ty1 *) tolua_tousertype(tolua_S, 1, 0);
LOGWARN("Error in function call '" #FOREACH "': Expected a number for parameters #1, #2 and #3"); \ if (!lua_isnumber(tolua_S, 2) || !lua_isnumber(tolua_S, 3) || !lua_isnumber(tolua_S, 4))
return 0; \ {
} \ return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a number for parameters #1, #2 and #3");
\ }
int ItemX = ((int)tolua_tonumber(tolua_S, 2, 0)); \
int ItemY = ((int)tolua_tonumber(tolua_S, 3, 0)); \ int ItemX = ((int)tolua_tonumber(tolua_S, 2, 0));
int ItemZ = ((int)tolua_tonumber(tolua_S, 4, 0)); \ int ItemY = ((int)tolua_tonumber(tolua_S, 3, 0));
LOG("x %i y %i z %i", ItemX, ItemY, ItemZ ); \ int ItemZ = ((int)tolua_tonumber(tolua_S, 4, 0));
if (!lua_isfunction( tolua_S, 5)) \ LOG("x %i y %i z %i", ItemX, ItemY, ItemZ );
{ \ if (!lua_isfunction( tolua_S, 5))
LOGWARN("Error in function call '" #FOREACH "': Expected a function for parameter #2"); \ {
return 0; \ return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a function for parameter #4");
} \ }
\
/* luaL_ref gets reference to value on top of the stack, the table is the last argument and therefore on the top */ \ /* 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; \ int TableRef = LUA_REFNIL;
if (NumArgs == 5) \ if (NumArgs == 5)
{ \ {
TableRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX); \ TableRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
if (TableRef == LUA_REFNIL) \ if (TableRef == LUA_REFNIL)
{ \ {
LOGWARN("Error in function call '" #FOREACH "': Could not get value reference of parameter #3"); \ return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get value reference of parameter #5");
return 0; \ }
} \ }
} \
\ /* table value is popped, and now function is on top of the stack */
/* table value is popped, and now function is on top of the stack */ \ int FuncRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
int FuncRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX); \ if (FuncRef == LUA_REFNIL)
if (FuncRef == LUA_REFNIL) \ {
{ \ return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #4");
LOGWARN("Error in function call '" #FOREACH "': Could not get function reference of parameter #2"); \ }
return 0; \
} \ class cLuaCallback : public cItemCallback<Ty2>
\ {
class cLuaCallback : public cItemCallback<ITEM> \ public:
{ \ cLuaCallback(lua_State* a_LuaState, int a_FuncRef, int a_TableRef)
public: \ : LuaState( a_LuaState )
cLuaCallback(lua_State* a_LuaState, int a_FuncRef, int a_TableRef) \ , FuncRef( a_FuncRef )
: LuaState( a_LuaState ) \ , TableRef( a_TableRef )
, FuncRef( a_FuncRef ) \ {}
, TableRef( a_TableRef ) \
{} \ private:
\ virtual bool Item(Ty2 * a_Item) override
private: \ {
virtual bool Item(ITEM * a_Item) override \ lua_rawgeti( LuaState, LUA_REGISTRYINDEX, FuncRef); /* Push function reference */
{ \ tolua_pushusertype(LuaState, a_Item, Ty2::GetClassStatic());
lua_rawgeti( LuaState, LUA_REGISTRYINDEX, FuncRef); /* Push function reference */ \ if (TableRef != LUA_REFNIL)
tolua_pushusertype(LuaState, a_Item, #ITEM); \ {
if (TableRef != LUA_REFNIL) \ lua_rawgeti( LuaState, LUA_REGISTRYINDEX, TableRef); /* Push table reference */
{ \ }
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);
int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0); \ return true;
report_errors(LuaState, s); \ }
return true; \ lua_State * LuaState;
} \ int FuncRef;
lua_State * LuaState; \ int TableRef;
int FuncRef; \ } Callback(tolua_S, FuncRef, TableRef);
int TableRef; \
} Callback(tolua_S, FuncRef, TableRef); \ bool bRetVal = (self->*Func1)(ItemX, ItemY, ItemZ, Callback);
\
bool bRetVal = self->FOREACH(ItemX, ItemY, ItemZ, Callback); \ /* Unreference the values again, so the LUA_REGISTRYINDEX can make place for other references */
\ luaL_unref(tolua_S, LUA_REGISTRYINDEX, TableRef);
/* Unreference the values again, so the LUA_REGISTRYINDEX can make place for other references */ \ luaL_unref(tolua_S, LUA_REGISTRYINDEX, FuncRef);
luaL_unref(tolua_S, LUA_REGISTRYINDEX, TableRef); \
luaL_unref(tolua_S, LUA_REGISTRYINDEX, FuncRef); \ /* Push return value on stack */
\ tolua_pushboolean(tolua_S, bRetVal );
/* Push return value on stack */ \ return 1;
tolua_pushboolean(tolua_S, bRetVal ); \ }
return 1; \
template< class Ty1,
class Ty2,
bool (Ty1::*Func1)(int, int, cItemCallback<Ty2> &) >
static int tolua_ForEachInChunk(lua_State* tolua_S)
{
int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */
if ((NumArgs != 3) && (NumArgs != 4))
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Requires 3 or 4 arguments, got %i", NumArgs);
}
Ty1 * self = (Ty1 *) tolua_tousertype(tolua_S, 1, 0);
if (!lua_isnumber(tolua_S, 2) || !lua_isnumber(tolua_S, 3))
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a number for parameters #1 and #2");
}
int ChunkX = ((int)tolua_tonumber(tolua_S, 2, 0));
int ChunkZ = ((int)tolua_tonumber(tolua_S, 3, 0));
if (!lua_isfunction( tolua_S, 4))
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a function for parameter #3");
}
/* 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 == 4)
{
TableRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
if (TableRef == LUA_REFNIL)
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get value reference of parameter #4");
}
}
/* 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)
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #3");
}
class cLuaCallback : public cItemCallback<Ty2>
{
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(Ty2 * a_Item) override
{
lua_rawgeti( LuaState, LUA_REGISTRYINDEX, FuncRef); /* Push function reference */
tolua_pushusertype(LuaState, a_Item, Ty2::GetClassStatic());
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->*Func1)(ChunkX, ChunkZ, 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;
}
template< class Ty1,
class Ty2,
bool (Ty1::*Func1)(cItemCallback<Ty2> &) >
static int tolua_ForEach(lua_State * tolua_S)
{
int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */
if( NumArgs != 1 && NumArgs != 2)
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Requires 1 or 2 arguments, got %i", NumArgs);
} }
Ty1 * self = (Ty1 *) 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");
}
/* 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)
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get value reference of parameter #2");
}
}
/* 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)
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #1");
}
#define DEFINE_LUA_FOREACHINCHUNK(CONTAINER,ITEM,FOREACH,FNNAME) \ class cLuaCallback : public cItemCallback<Ty2>
static int FNNAME(lua_State * tolua_S) \ {
{ \ public:
int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */ \ cLuaCallback(lua_State* a_LuaState, int a_FuncRef, int a_TableRef)
if ((NumArgs != 3) && (NumArgs != 4)) \ : LuaState( a_LuaState )
{ \ , FuncRef( a_FuncRef )
LOGWARN("Error in function call '" #FOREACH "': Requires 3 or 4 arguments, got %i", NumArgs); \ , TableRef( a_TableRef )
return 0; \ {}
} \
\ private:
CONTAINER * self = (CONTAINER *) tolua_tousertype(tolua_S, 1, 0); \ virtual bool Item(Ty2 * a_Item) override
if (!lua_isnumber(tolua_S, 2) || !lua_isnumber(tolua_S, 3)) \ {
{ \ lua_rawgeti( LuaState, LUA_REGISTRYINDEX, FuncRef); /* Push function reference */
LOGWARN("Errorin function call '" #FOREACH "': Expected a number for parameters #1 and #2"); \ tolua_pushusertype( LuaState, a_Item, Ty2::GetClassStatic() );
return 0; \ if (TableRef != LUA_REFNIL)
} \ {
\ lua_rawgeti( LuaState, LUA_REGISTRYINDEX, TableRef); /* Push table reference */
int ChunkX = ((int)tolua_tonumber(tolua_S, 2, 0)); \ }
int ChunkZ = ((int)tolua_tonumber(tolua_S, 3, 0)); \
\ int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0);
if (!lua_isfunction( tolua_S, 4)) \ if (report_errors(LuaState, s))
{ \ {
LOGWARN("Error in function call '" #FOREACH "': Expected a function for parameter #3"); \ return true; /* Abort enumeration */
return 0; \ }
} \
\ if (lua_isboolean(LuaState, -1))
/* 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; \ return (tolua_toboolean( LuaState, -1, 0) > 0);
if (NumArgs == 4) \ }
{ \ return false; /* Continue enumeration */
TableRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX); \ }
if (TableRef == LUA_REFNIL) \ lua_State * LuaState;
{ \ int FuncRef;
LOGWARN("Error in function call '" #FOREACH "': Could not get value reference of parameter #4"); \ int TableRef;
return 0; \ } Callback(tolua_S, FuncRef, TableRef);
} \
} \ bool bRetVal = (self->*Func1)(Callback);
\
/* table value is popped, and now function is on top of the stack */ \ /* Unreference the values again, so the LUA_REGISTRYINDEX can make place for other references */
int FuncRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX); \ luaL_unref(tolua_S, LUA_REGISTRYINDEX, TableRef);
if (FuncRef == LUA_REFNIL) \ luaL_unref(tolua_S, LUA_REGISTRYINDEX, FuncRef);
{ \
LOGWARN("Error in function call '" #FOREACH "': Could not get function reference of parameter #3"); \ /* Push return value on stack */
return 0; \ tolua_pushboolean(tolua_S, bRetVal );
} \ return 1;
\
class cLuaCallback : public cItemCallback<ITEM> \
{ \
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(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(ChunkX, ChunkZ, 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 (self == NULL) \
{ \
LOGWARN("Error in function call '" #FOREACH "': Not called on an object instance"); \
return 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 cLuaCallback : public cItemCallback<ITEM> \
{ \
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(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; \
}
// Define the DoWith enumerators: (they take a string and a callback class)
DEFINE_LUA_DOWITH(cWorld, cPlayer, DoWithPlayer, tolua_cWorld_DoWithPlayer);
DEFINE_LUA_DOWITH(cWorld, cPlayer, FindAndDoWithPlayer, tolua_cWorld_FindAndDoWithPlayer);
DEFINE_LUA_DOWITH(cRoot, cPlayer, FindAndDoWithPlayer, tolua_cRoot_FindAndDoWithPlayer);
// Define the DoWith...At enumerators: (takes one 3D coordinate and a callback class)
DEFINE_LUA_DOWITH_XYZ(cWorld, cChestEntity, DoWithChestAt, tolua_cWorld_DoWithChestAt );
// Define the ForEach enumerators:
DEFINE_LUA_FOREACH(cWorld, cPlayer, ForEachPlayer, tolua_cWorld_ForEachPlayer);
DEFINE_LUA_FOREACH(cWorld, cEntity, ForEachEntity, tolua_cWorld_ForEachEntity);
DEFINE_LUA_FOREACH(cRoot, cWorld, ForEachWorld, tolua_cRoot_ForEachWorld);
DEFINE_LUA_FOREACH(cRoot, cPlayer, ForEachPlayer, tolua_cRoot_ForEachPlayer);
DEFINE_LUA_FOREACHINCHUNK(cWorld, cEntity, ForEachEntityInChunk, tolua_cWorld_ForEachEntityInChunk);
DEFINE_LUA_FOREACHINCHUNK(cWorld, cChestEntity, ForEachChestInChunk, tolua_cWorld_ForEachChestInChunk);
DEFINE_LUA_FOREACHINCHUNK(cWorld, cFurnaceEntity, ForEachFurnaceInChunk, tolua_cWorld_ForEachFurnaceInChunk);
static int tolua_cPluginManager_ForEachCommand(lua_State * tolua_S) static int tolua_cPluginManager_ForEachCommand(lua_State * tolua_S)
{ {
int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */ int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */
@ -786,12 +806,7 @@ static int tolua_cPlugin_NewLua_AddWebTab(lua_State * tolua_S)
} }
else else
{ {
if( tolua_err.type == 0 ) return tolua_do_error(tolua_S, "#ferror calling function '#funcname#'", &tolua_err);
{
tolua_err.type = "function";
}
tolua_error(tolua_S,"#ferror in function 'AddWebTab'.",&tolua_err);
return 0;
} }
if( Reference != LUA_REFNIL ) if( Reference != LUA_REFNIL )
@ -1020,20 +1035,20 @@ void ManualBindings::Bind( lua_State* tolua_S )
tolua_function(tolua_S, "Log", tolua_LOG); // Deprecated tolua_function(tolua_S, "Log", tolua_LOG); // Deprecated
tolua_beginmodule(tolua_S, "cRoot"); tolua_beginmodule(tolua_S, "cRoot");
tolua_function(tolua_S, "ForEachWorld", tolua_cRoot_ForEachWorld); tolua_function(tolua_S, "ForEachWorld", tolua_ForEach<cRoot, cWorld, &cRoot::ForEachWorld>);
tolua_function(tolua_S, "FindAndDoWithPlayer", tolua_cRoot_FindAndDoWithPlayer); tolua_function(tolua_S, "FindAndDoWithPlayer", tolua_DoWith <cRoot, cPlayer, &cRoot::FindAndDoWithPlayer>);
tolua_function(tolua_S, "ForEachPlayer", tolua_cRoot_ForEachPlayer); tolua_function(tolua_S, "ForEachPlayer", tolua_ForEach<cRoot, cPlayer, &cRoot::ForEachPlayer>);
tolua_endmodule(tolua_S); tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cWorld"); tolua_beginmodule(tolua_S, "cWorld");
tolua_function(tolua_S, "ForEachPlayer", tolua_cWorld_ForEachPlayer); tolua_function(tolua_S, "ForEachPlayer", tolua_ForEach<cWorld, cPlayer, &cWorld::ForEachPlayer>);
tolua_function(tolua_S, "ForEachEntity", tolua_cWorld_ForEachEntity); tolua_function(tolua_S, "ForEachEntity", tolua_ForEach<cWorld, cEntity, &cWorld::ForEachEntity>);
tolua_function(tolua_S, "ForEachEntityInChunk", tolua_cWorld_ForEachEntityInChunk); tolua_function(tolua_S, "ForEachEntityInChunk", tolua_ForEachInChunk<cWorld, cEntity, &cWorld::ForEachEntityInChunk>);
tolua_function(tolua_S, "ForEachChestInChunk", tolua_cWorld_ForEachChestInChunk); tolua_function(tolua_S, "ForEachChestInChunk", tolua_ForEachInChunk<cWorld, cChestEntity, &cWorld::ForEachChestInChunk>);
tolua_function(tolua_S, "ForEachFurnaceInChunk", tolua_cWorld_ForEachFurnaceInChunk); tolua_function(tolua_S, "ForEachFurnaceInChunk", tolua_ForEachInChunk<cWorld, cFurnaceEntity, &cWorld::ForEachFurnaceInChunk>);
tolua_function(tolua_S, "DoWithPlayer", tolua_cWorld_DoWithPlayer); tolua_function(tolua_S, "DoWithPlayer", tolua_DoWith<cWorld, cPlayer, &cWorld::DoWithPlayer>);
tolua_function(tolua_S, "FindAndDoWithPlayer", tolua_cWorld_FindAndDoWithPlayer); tolua_function(tolua_S, "FindAndDoWithPlayer", tolua_DoWith<cWorld, cPlayer, &cWorld::FindAndDoWithPlayer>);
tolua_function(tolua_S, "DoWithChestAt", tolua_cWorld_DoWithChestAt); tolua_function(tolua_S, "DoWithChestAt", tolua_DoWithXYZ<cWorld, cChestEntity, &cWorld::DoWithChestAt>);
tolua_endmodule(tolua_S); tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cPlugin"); tolua_beginmodule(tolua_S, "cPlugin");

View File

@ -60,6 +60,11 @@ class cWorld // tolua_export
public: public:
// tolua_begin // tolua_begin
static const char * GetClassStatic(void)
{
return "cWorld";
}
/// Return time in seconds /// Return time in seconds
inline static float GetTime(void) inline static float GetTime(void)