LuaItemStack: Add __tostring metamethod (#8785)
authorPaul Ouellette <oue.paul18@gmail.com>
Tue, 9 Jun 2020 17:37:25 +0000 (13:37 -0400)
committerGitHub <noreply@github.com>
Tue, 9 Jun 2020 17:37:25 +0000 (19:37 +0200)
* LuaItemStack: Add __tostring metamethod

* Clean up LuaItemStack::checkobject

builtin/common/misc_helpers.lua
src/inventory.cpp
src/inventory.h
src/script/lua_api/l_item.cpp
src/script/lua_api/l_item.h

index a88adf96de5a2f4d6a21a4b4c5d10ad89877e218..e29a9f4222c74afbced8d8e938c16ad47d1e3d6a 100644 (file)
@@ -20,6 +20,8 @@ local function basic_dump(o)
        -- dump's output is intended for humans.
        --elseif tp == "function" then
        --      return string.format("loadstring(%q)", string.dump(o))
+       elseif tp == "userdata" then
+               return tostring(o)
        else
                return string.format("<%s>", tp)
        end
index 77ecf5876bf36500206ba8b7eb5697c0e7a2c033..349ee503d1ceab3a61a16b6593f10df90303e698 100644 (file)
@@ -56,28 +56,31 @@ ItemStack::ItemStack(const std::string &name_, u16 count_,
                count = 1;
 }
 
-void ItemStack::serialize(std::ostream &os) const
+void ItemStack::serialize(std::ostream &os, bool serialize_meta) const
 {
        if (empty())
                return;
 
        // Check how many parts of the itemstring are needed
        int parts = 1;
-       if(count != 1)
-               parts = 2;
-       if(wear != 0)
-               parts = 3;
        if (!metadata.empty())
                parts = 4;
+       else if (wear != 0)
+               parts = 3;
+       else if (count != 1)
+               parts = 2;
 
-       os<<serializeJsonStringIfNeeded(name);
-       if(parts >= 2)
-               os<<" "<<count;
-       if(parts >= 3)
-               os<<" "<<wear;
+       os << serializeJsonStringIfNeeded(name);
+       if (parts >= 2)
+               os << " " << count;
+       if (parts >= 3)
+               os << " " << wear;
        if (parts >= 4) {
                os << " ";
-               metadata.serialize(os);
+               if (serialize_meta)
+                       metadata.serialize(os);
+               else
+                       os << "<metadata size=" << metadata.size() << ">";
        }
 }
 
@@ -240,10 +243,10 @@ void ItemStack::deSerialize(const std::string &str, IItemDefManager *itemdef)
        deSerialize(is, itemdef);
 }
 
-std::string ItemStack::getItemString() const
+std::string ItemStack::getItemString(bool include_meta) const
 {
        std::ostringstream os(std::ios::binary);
-       serialize(os);
+       serialize(os, include_meta);
        return os.str();
 }
 
index 2828d3e5ad935dd6dc1338afd32975854f920e7e..67a7859ed14dafc9baa35913d27766f79f6ce1d2 100644 (file)
@@ -40,13 +40,13 @@ struct ItemStack
        ~ItemStack() = default;
 
        // Serialization
-       void serialize(std::ostream &os) const;
+       void serialize(std::ostream &os, bool serialize_meta = true) const;
        // Deserialization. Pass itemdef unless you don't want aliases resolved.
        void deSerialize(std::istream &is, IItemDefManager *itemdef = NULL);
        void deSerialize(const std::string &s, IItemDefManager *itemdef = NULL);
 
        // Returns the string used for inventory
-       std::string getItemString() const;
+       std::string getItemString(bool include_meta = true) const;
        // Returns the tooltip
        std::string getDescription(IItemDefManager *itemdef) const;
 
index 0a403acbd7b8ceb625c750e0193162c1ad170167..d67cab76f101bb3d57a4ba40beda11864b1ead28 100644 (file)
@@ -37,6 +37,15 @@ int LuaItemStack::gc_object(lua_State *L)
        return 0;
 }
 
+// __tostring metamethod
+int LuaItemStack::mt_tostring(lua_State *L)
+{
+       LuaItemStack *o = checkobject(L, 1);
+       std::string itemstring = o->m_stack.getItemString(false);
+       lua_pushfstring(L, "ItemStack(\"%s\")", itemstring.c_str());
+       return 1;
+}
+
 // is_empty(self) -> true/false
 int LuaItemStack::l_is_empty(lua_State *L)
 {
@@ -433,12 +442,9 @@ int LuaItemStack::create(lua_State *L, const ItemStack &item)
        return 1;
 }
 
-LuaItemStackLuaItemStack::checkobject(lua_State *L, int narg)
+LuaItemStack *LuaItemStack::checkobject(lua_State *L, int narg)
 {
-       luaL_checktype(L, narg, LUA_TUSERDATA);
-       void *ud = luaL_checkudata(L, narg, className);
-       if(!ud) luaL_typerror(L, narg, className);
-       return *(LuaItemStack**)ud;  // unbox pointer
+       return *(LuaItemStack **)luaL_checkudata(L, narg, className);
 }
 
 void LuaItemStack::Register(lua_State *L)
@@ -448,9 +454,10 @@ void LuaItemStack::Register(lua_State *L)
        luaL_newmetatable(L, className);
        int metatable = lua_gettop(L);
 
+       // hide metatable from Lua getmetatable()
        lua_pushliteral(L, "__metatable");
        lua_pushvalue(L, methodtable);
-       lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
+       lua_settable(L, metatable);
 
        lua_pushliteral(L, "__index");
        lua_pushvalue(L, methodtable);
@@ -460,12 +467,16 @@ void LuaItemStack::Register(lua_State *L)
        lua_pushcfunction(L, gc_object);
        lua_settable(L, metatable);
 
+       lua_pushliteral(L, "__tostring");
+       lua_pushcfunction(L, mt_tostring);
+       lua_settable(L, metatable);
+
        lua_pop(L, 1);  // drop metatable
 
        luaL_openlib(L, 0, methods, 0);  // fill methodtable
        lua_pop(L, 1);  // drop methodtable
 
-       // Can be created from Lua (LuaItemStack(itemstack or itemstring or table or nil))
+       // Can be created from Lua (ItemStack(itemstack or itemstring or table or nil))
        lua_register(L, className, create_object);
 }
 
index 6fab58045774b6de9d4189ad2e9fbaf86889b049..98744c07162daae4f78ccb6acb9545df07a1cf00 100644 (file)
@@ -34,6 +34,9 @@ private:
        // garbage collector
        static int gc_object(lua_State *L);
 
+       // __tostring metamethod
+       static int mt_tostring(lua_State *L);
+
        // is_empty(self) -> true/false
        static int l_is_empty(lua_State *L);