LuaItemStack: Add __tostring metamethod (#8785)

* LuaItemStack: Add __tostring metamethod

* Clean up LuaItemStack::checkobject
This commit is contained in:
Paul Ouellette 2020-06-09 13:37:25 -04:00 committed by GitHub
parent 09e285f38c
commit b16f841756
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 41 additions and 22 deletions

@ -20,6 +20,8 @@ local function basic_dump(o)
-- dump's output is intended for humans. -- dump's output is intended for humans.
--elseif tp == "function" then --elseif tp == "function" then
-- return string.format("loadstring(%q)", string.dump(o)) -- return string.format("loadstring(%q)", string.dump(o))
elseif tp == "userdata" then
return tostring(o)
else else
return string.format("<%s>", tp) return string.format("<%s>", tp)
end end

@ -56,28 +56,31 @@ ItemStack::ItemStack(const std::string &name_, u16 count_,
count = 1; count = 1;
} }
void ItemStack::serialize(std::ostream &os) const void ItemStack::serialize(std::ostream &os, bool serialize_meta) const
{ {
if (empty()) if (empty())
return; return;
// Check how many parts of the itemstring are needed // Check how many parts of the itemstring are needed
int parts = 1; int parts = 1;
if(count != 1)
parts = 2;
if(wear != 0)
parts = 3;
if (!metadata.empty()) if (!metadata.empty())
parts = 4; parts = 4;
else if (wear != 0)
parts = 3;
else if (count != 1)
parts = 2;
os<<serializeJsonStringIfNeeded(name); os << serializeJsonStringIfNeeded(name);
if(parts >= 2) if (parts >= 2)
os<<" "<<count; os << " " << count;
if(parts >= 3) if (parts >= 3)
os<<" "<<wear; os << " " << wear;
if (parts >= 4) { if (parts >= 4) {
os << " "; 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); deSerialize(is, itemdef);
} }
std::string ItemStack::getItemString() const std::string ItemStack::getItemString(bool include_meta) const
{ {
std::ostringstream os(std::ios::binary); std::ostringstream os(std::ios::binary);
serialize(os); serialize(os, include_meta);
return os.str(); return os.str();
} }

@ -40,13 +40,13 @@ struct ItemStack
~ItemStack() = default; ~ItemStack() = default;
// Serialization // 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. // Deserialization. Pass itemdef unless you don't want aliases resolved.
void deSerialize(std::istream &is, IItemDefManager *itemdef = NULL); void deSerialize(std::istream &is, IItemDefManager *itemdef = NULL);
void deSerialize(const std::string &s, IItemDefManager *itemdef = NULL); void deSerialize(const std::string &s, IItemDefManager *itemdef = NULL);
// Returns the string used for inventory // Returns the string used for inventory
std::string getItemString() const; std::string getItemString(bool include_meta = true) const;
// Returns the tooltip // Returns the tooltip
std::string getDescription(IItemDefManager *itemdef) const; std::string getDescription(IItemDefManager *itemdef) const;

@ -37,6 +37,15 @@ int LuaItemStack::gc_object(lua_State *L)
return 0; 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 // is_empty(self) -> true/false
int LuaItemStack::l_is_empty(lua_State *L) int LuaItemStack::l_is_empty(lua_State *L)
{ {
@ -433,12 +442,9 @@ int LuaItemStack::create(lua_State *L, const ItemStack &item)
return 1; return 1;
} }
LuaItemStack* LuaItemStack::checkobject(lua_State *L, int narg) LuaItemStack *LuaItemStack::checkobject(lua_State *L, int narg)
{ {
luaL_checktype(L, narg, LUA_TUSERDATA); return *(LuaItemStack **)luaL_checkudata(L, narg, className);
void *ud = luaL_checkudata(L, narg, className);
if(!ud) luaL_typerror(L, narg, className);
return *(LuaItemStack**)ud; // unbox pointer
} }
void LuaItemStack::Register(lua_State *L) void LuaItemStack::Register(lua_State *L)
@ -448,9 +454,10 @@ void LuaItemStack::Register(lua_State *L)
luaL_newmetatable(L, className); luaL_newmetatable(L, className);
int metatable = lua_gettop(L); int metatable = lua_gettop(L);
// hide metatable from Lua getmetatable()
lua_pushliteral(L, "__metatable"); lua_pushliteral(L, "__metatable");
lua_pushvalue(L, methodtable); lua_pushvalue(L, methodtable);
lua_settable(L, metatable); // hide metatable from Lua getmetatable() lua_settable(L, metatable);
lua_pushliteral(L, "__index"); lua_pushliteral(L, "__index");
lua_pushvalue(L, methodtable); lua_pushvalue(L, methodtable);
@ -460,12 +467,16 @@ void LuaItemStack::Register(lua_State *L)
lua_pushcfunction(L, gc_object); lua_pushcfunction(L, gc_object);
lua_settable(L, metatable); lua_settable(L, metatable);
lua_pushliteral(L, "__tostring");
lua_pushcfunction(L, mt_tostring);
lua_settable(L, metatable);
lua_pop(L, 1); // drop metatable lua_pop(L, 1); // drop metatable
luaL_openlib(L, 0, methods, 0); // fill methodtable luaL_openlib(L, 0, methods, 0); // fill methodtable
lua_pop(L, 1); // drop 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); lua_register(L, className, create_object);
} }

@ -34,6 +34,9 @@ private:
// garbage collector // garbage collector
static int gc_object(lua_State *L); static int gc_object(lua_State *L);
// __tostring metamethod
static int mt_tostring(lua_State *L);
// is_empty(self) -> true/false // is_empty(self) -> true/false
static int l_is_empty(lua_State *L); static int l_is_empty(lua_State *L);