From 4cd1957231605e976c5cf001eddea80d5e49272f Mon Sep 17 00:00:00 2001 From: Thorbjørn Lindeijer Date: Mon, 30 Jan 2012 22:16:40 +0100 Subject: Use a full user data object for MapObject references Based on a templated helper class, MapObject references in Lua scripts are now full user data objects. Using the '__index' member of their metatable, a library is associated with it so that member functions can be called directly on the object. Reviewed-by: Yohann Ferreira Reviewed-by: Erik Schilling --- src/scripting/luautil.h | 66 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 2 deletions(-) (limited to 'src/scripting/luautil.h') diff --git a/src/scripting/luautil.h b/src/scripting/luautil.h index ee3f1142..4f456ab6 100644 --- a/src/scripting/luautil.h +++ b/src/scripting/luautil.h @@ -44,19 +44,81 @@ void raiseScriptError(lua_State *s, const char *format, ...); void raiseWarning(lua_State *s, const char *format, ...); +/** + * A helper class for pushing and checking custom Lua user data types. + */ +template +class LuaUserData +{ +public: + /** + * Creates a metatable to be used for the user data associated with the + * type. Then, registers the \a members with a library named \a typeName, + * and sets the '__index' member of the metatable to this library. + */ + static void registerType(lua_State *s, + const char *typeName, + const luaL_Reg *members) + { + mTypeName = typeName; + + luaL_newmetatable(s, mTypeName); // metatable + lua_pushstring(s, "__index"); // metatable, "__index" + luaL_register(s, typeName, members); // metatable, "__index", {} + lua_rawset(s, -3); // metatable + lua_pop(s, 1); // -empty- + } + + /** + * Pushes a userdata reference to the given object on the stack. Either by + * creating one, or reusing an existing one. + */ + static int push(lua_State *L, T *object) + { + T **userData = static_cast(lua_newuserdata(L, sizeof(T*))); + *userData = object; + + luaL_newmetatable(L, mTypeName); + lua_setmetatable(L, -2); + + return 1; + } + + /** + * Returns the argument at position \a narg when it is of the right type, + * and raises a Lua error otherwise. + */ + static T *check(lua_State *L, int narg) + { + void *userData = luaL_checkudata(L, narg, mTypeName); + return *(static_cast(userData)); + } + +private: + static const char *mTypeName; +}; + +template const char * LuaUserData::mTypeName; + +typedef LuaUserData LuaMapObject; + + NPC *getNPC(lua_State *s, int p); Character *getCharacter(lua_State *s, int p); Monster *getMonster(lua_State *s, int p); Being *getBeing(lua_State *s, int p); - /* Polymorphic wrapper for pushing variables. Useful for templates.*/ void push(lua_State *s, int val); void push(lua_State *s, const std::string &val); void push(lua_State *s, Thing *val); void push(lua_State *s, double val); -void push(lua_State *s, MapObject *val); + +inline void push(lua_State *s, MapObject *val) +{ + LuaMapObject::push(s, val); +} /* Pushes an STL LIST */ -- cgit v1.2.3-60-g2f50