summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/scripting/lua.cpp66
-rw-r--r--src/scripting/luautil.cpp5
-rw-r--r--src/scripting/luautil.h66
3 files changed, 84 insertions, 53 deletions
diff --git a/src/scripting/lua.cpp b/src/scripting/lua.cpp
index c7053b3c..63149792 100644
--- a/src/scripting/lua.cpp
+++ b/src/scripting/lua.cpp
@@ -2500,31 +2500,17 @@ static int map_get_objects(lua_State *s)
static int map_object_get_property(lua_State *s)
{
const char *key = luaL_checkstring(s, 2);
- if (!lua_islightuserdata(s, 1))
- {
- raiseScriptError(s, "map_object_get_property called with invalid"
- "object handle");
- return 0;
- }
- MapObject *obj = static_cast<MapObject *>(lua_touserdata(s, 1));
- if (obj)
+ MapObject *obj = LuaMapObject::check(s, 1);
+
+ std::string property = obj->getProperty(key);
+ if (!property.empty())
{
- std::string property = obj->getProperty(key);
- if (!property.empty())
- {
- lua_pushstring(s, property.c_str());
- return 1;
- }
- else
- {
- // scripts can check for nil
- return 0;
- }
+ lua_pushstring(s, property.c_str());
+ return 1;
}
else
{
- raiseScriptError(s, "map_object_get_property called with invalid"
- "object handle");
+ // scripts can check for nil
return 0;
}
}
@@ -2535,13 +2521,7 @@ static int map_object_get_property(lua_State *s)
*/
static int map_object_get_bounds(lua_State *s)
{
- if (!lua_islightuserdata(s, 1))
- {
- raiseScriptError(s, "map_object_get_bounds called with invalid"
- "object handle");
- return 0;
- }
- MapObject *obj = static_cast<MapObject *>(lua_touserdata(s, 1));
+ MapObject *obj = LuaMapObject::check(s, 1);
const Rectangle &bounds = obj->getBounds();
lua_pushinteger(s, bounds.x);
lua_pushinteger(s, bounds.y);
@@ -2556,13 +2536,7 @@ static int map_object_get_bounds(lua_State *s)
*/
static int map_object_get_name(lua_State *s)
{
- if (!lua_islightuserdata(s, 1))
- {
- raiseScriptError(s, "map_object_get_name called with invalid"
- "object handle");
- return 0;
- }
- MapObject *obj = static_cast<MapObject *>(lua_touserdata(s, 1));
+ MapObject *obj = LuaMapObject::check(s, 1);
lua_pushstring(s, obj->getName().c_str());
return 1;
}
@@ -2573,13 +2547,7 @@ static int map_object_get_name(lua_State *s)
*/
static int map_object_get_type(lua_State *s)
{
- if (!lua_islightuserdata(s, 1))
- {
- raiseScriptError(s, "map_object_get_type called with invalid"
- "object handle");
- return 0;
- }
- MapObject *obj = static_cast<MapObject *>(lua_touserdata(s, 1));
+ MapObject *obj = LuaMapObject::check(s, 1);
lua_pushstring(s, obj->getType().c_str());
return 1;
}
@@ -2718,16 +2686,22 @@ LuaScript::LuaScript():
{ "log", &log },
{ "get_distance", &get_distance },
{ "map_get_objects", &map_get_objects },
- { "map_object_get_property", &map_object_get_property },
- { "map_object_get_bounds", &map_object_get_bounds },
- { "map_object_get_name", &map_object_get_name },
- { "map_object_get_type", &map_object_get_type },
{ "announce", &announce },
{ NULL, NULL }
};
luaL_register(mState, "mana", callbacks);
lua_pop(mState, 1); // pop the 'mana' table
+ static luaL_Reg const members_MapObject[] = {
+ { "property", &map_object_get_property },
+ { "bounds", &map_object_get_bounds },
+ { "name", &map_object_get_name },
+ { "type", &map_object_get_type },
+ { NULL, NULL }
+ };
+
+ LuaMapObject::registerType(mState, "MapObject", members_MapObject);
+
// Make script object available to callback functions.
lua_pushlightuserdata(mState, (void *)&registryKey);
lua_pushlightuserdata(mState, this);
diff --git a/src/scripting/luautil.cpp b/src/scripting/luautil.cpp
index a7521426..b7680c6b 100644
--- a/src/scripting/luautil.cpp
+++ b/src/scripting/luautil.cpp
@@ -116,8 +116,3 @@ void push(lua_State *s, double val)
{
lua_pushnumber(s, val);
}
-
-void push(lua_State *s, MapObject *val)
-{
- lua_pushlightuserdata(s, val);
-}
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 <typename T>
+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<T**>(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<T**>(userData));
+ }
+
+private:
+ static const char *mTypeName;
+};
+
+template <typename T> const char * LuaUserData<T>::mTypeName;
+
+typedef LuaUserData<MapObject> 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 */