From 39f03b2da8a2be3048fc6d31465701ebb41626f0 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Fri, 27 Mar 2015 21:54:41 +1100 Subject: [PATCH] meta-meta table is functioning correctly --- rsc/scripts/setup_server.lua | 10 ++++- server/userdata.cpp | 71 +++++++++++++++++++++++++++++++++++- 2 files changed, 78 insertions(+), 3 deletions(-) diff --git a/rsc/scripts/setup_server.lua b/rsc/scripts/setup_server.lua index 741a239..52566ae 100644 --- a/rsc/scripts/setup_server.lua +++ b/rsc/scripts/setup_server.lua @@ -37,7 +37,13 @@ roomAPI.Initialize(underworld, mapSaver.Load, mapSaver.Save, mapMaker.DebugGrass doorUtility.createDoorPair("pair 1", overworld, 0, -64, underworld, 0, 0) --testing the metatables -local meta = getmetatable(underworld) -print("", "userdata metatable: ", meta) +print("debug") +overworld["key"] = "value" +local key = overworld["key"] +print("", "result: ", key) + +local key = underworld["key"] +print("", "result: ", key) +--end test print("Finished the lua script") diff --git a/server/userdata.cpp b/server/userdata.cpp index 69d2e52..94029fd 100644 --- a/server/userdata.cpp +++ b/server/userdata.cpp @@ -23,13 +23,71 @@ #include +#define METAMETA "__metameta" + static int index(lua_State* L) { - std::cout << "WARNING: userdataIndex called" << std::endl; + std::cout << "debug: index" << std::endl; + + //get __metameta + lua_getmetatable(L, 1); //get the userdata metatable + lua_pushstring(L, METAMETA); //push the __metameta name + lua_gettable(L, -2); //get the __metameta field from the metatable + + //get __metameta[userdata] + lua_pushvalue(L, 1); //copy of the userdata + lua_gettable(L, -2); //get the table at __metameta[userdata] + + //table doesn't exist yet + if (lua_isnil(L, -1)) { + std::cout << "debug: index (no table)" << std::endl; + return 1; + } + + //get the value at __metameta[userdata][key] + lua_pushvalue(L, 2); //copy the key + lua_gettable(L, -2); //get value from the deepest table + + //return + return 1; +} + +static int newindex(lua_State* L) { + std::cout << "debug: newindex" << std::endl; + + //get __metameta + lua_getmetatable(L, 1); //get the userdata metatable + lua_pushstring(L, METAMETA); //push the __metameta name + lua_gettable(L, -2); //get the __metameta field from the metatable + + //get __metameta[userdata] + lua_pushvalue(L, 1); //copy of the userdata + lua_gettable(L, -2); //get the table at __metameta[userdata] + + //if this table doesn't exist yet + if (lua_isnil(L, -1)) { + std::cout << "debug: newindex (new table)" << std::endl; + lua_pop(L, 1); //pop nil + + lua_pushvalue(L, 1); //copy userdata (key) + lua_createtable(L, 0, 0); //new table (value) + lua_settable(L, -3); //create the new table in __metameta + + lua_pushvalue(L, 1); //copy userdata (key) + lua_gettable(L, -2); //get the newly created table + } + + //set the value at __metameta[userdata][key] = value + lua_pushvalue(L, 2); //copy the key + lua_pushvalue(L, 3); //copy the value + lua_settable(L, -3); //set value in the deepest table + + //return return 0; } static luaL_Reg metatable[] = { {"__index", index}, + {"__newindex", newindex}, {nullptr, nullptr} }; @@ -38,6 +96,17 @@ int createUserdataMetatable(lua_State* L) { lua_pushlightuserdata(L, nullptr); //anon userdata lua_createtable(L, 0, 0); //table + //insert meta-metatable + lua_pushstring(L, METAMETA); + lua_createtable(L, 0, 0); + lua_settable(L, -3); + + //insert metatable blocker + lua_pushstring(L, "__metatable"); + lua_createtable(L, 0, 0); + lua_settable(L, -3); + + //insert metamethods for (luaL_Reg* it = metatable; it->name; it++) { lua_pushstring(L, it->name); lua_pushcfunction(L, it->func);