aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/lua_api.txt17
-rw-r--r--games/devtest/mods/unittests/init.lua3
-rw-r--r--games/devtest/mods/unittests/itemstack_equals.lua74
-rw-r--r--src/script/lua_api/l_item.cpp34
-rw-r--r--src/script/lua_api/l_item.h3
5 files changed, 130 insertions, 1 deletions
diff --git a/doc/lua_api.txt b/doc/lua_api.txt
index 202f66262..46b4ed642 100644
--- a/doc/lua_api.txt
+++ b/doc/lua_api.txt
@@ -6811,6 +6811,23 @@ an itemstring, a table or `nil`.
* `peek_item(n)`: returns taken `ItemStack`
* Copy (don't remove) up to `n` items from this stack
* `n`: number, default: `1`
+* `equals(other)`:
+ * returns `true` if this stack is identical to `other`.
+ * Note: `stack1:to_string() == stack2:to_string()` is not reliable,
+ as stack metadata can be serialized in arbitrary order.
+ * Note: if `other` is an itemstring or table representation of an
+ ItemStack, this will always return false, even if it is
+ "equivalent".
+
+### Operators
+
+* `stack1 == stack2`:
+ * Returns whether `stack1` and `stack2` are identical.
+ * Note: `stack1:to_string() == stack2:to_string()` is not reliable,
+ as stack metadata can be serialized in arbitrary order.
+ * Note: if `stack2` is an itemstring or table representation of an
+ ItemStack, this will always return false, even if it is
+ "equivalent".
`ItemStackMetaRef`
------------------
diff --git a/games/devtest/mods/unittests/init.lua b/games/devtest/mods/unittests/init.lua
index 936f05c6d..d8237e767 100644
--- a/games/devtest/mods/unittests/init.lua
+++ b/games/devtest/mods/unittests/init.lua
@@ -91,7 +91,7 @@ function unittests.run_one(idx, counters, out_callback, player, pos)
done(status, err)
out_callback(true)
end
-
+
return true
end
@@ -178,6 +178,7 @@ dofile(modpath .. "/crafting.lua")
dofile(modpath .. "/itemdescription.lua")
dofile(modpath .. "/async_env.lua")
dofile(modpath .. "/entity.lua")
+dofile(modpath .. "/itemstack_equals.lua")
dofile(modpath .. "/content_ids.lua")
dofile(modpath .. "/metadata.lua")
diff --git a/games/devtest/mods/unittests/itemstack_equals.lua b/games/devtest/mods/unittests/itemstack_equals.lua
new file mode 100644
index 000000000..561e612c4
--- /dev/null
+++ b/games/devtest/mods/unittests/itemstack_equals.lua
@@ -0,0 +1,74 @@
+local function test_itemstack_equals_non_stack()
+ local i1 = ItemStack("basenodes:stone")
+ local i2 = { foo = "bar" }
+
+ assert(not i1:equals(i2))
+ assert(i1 ~= i2)
+ assert(i2 ~= i1)
+end
+
+unittests.register("test_itemstack_equals_non_stack", test_itemstack_equals_non_stack)
+
+local function test_itemstack_equals_name()
+ local i1 = ItemStack("basenodes:stone")
+ local i2 = ItemStack("basenodes:desert_stone")
+
+ assert(not i1:equals(i2))
+ assert(i1 ~= i2)
+end
+
+unittests.register("test_itemstack_equals_name", test_itemstack_equals_name)
+
+local function test_itemstack_equals_count()
+ local i1 = ItemStack("basenodes:stone")
+ local i2 = ItemStack("basenodes:stone 2")
+
+ assert(not i1:equals(i2))
+ assert(i1 ~= i2)
+end
+
+unittests.register("test_itemstack_equals_count", test_itemstack_equals_count)
+
+local function test_itemstack_equals_wear()
+ local i1 = ItemStack("basetools:axe_stone")
+ local i2 = ItemStack("basetools:axe_stone")
+
+ i2:add_wear(1)
+
+ assert(not i1:equals(i2))
+ assert(i1 ~= i2)
+end
+
+unittests.register("test_itemstack_equals_wear", test_itemstack_equals_wear)
+
+local function test_itemstack_equals_metadata()
+ local i1 = ItemStack("basenodes:stone")
+ local i2 = ItemStack("basenodes:stone")
+ local i3 = ItemStack("basenodes:stone")
+
+ local m1 = i1:get_meta()
+ local m2 = i2:get_meta()
+ local m3 = i3:get_meta()
+
+ local keys = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p"}
+ local values = {}
+
+ for i, key in pairs(keys) do
+ m1:set_int(key, i)
+ m3:set_int(key, i)
+ values[key] = i
+ end
+
+ m3:set_int("a", 999)
+
+ for key, i in pairs(values) do
+ m2:set_int(key, i)
+ end
+
+ assert(i1:equals(i2))
+ assert(i1 == i2)
+ assert(not i1:equals(i3))
+ assert(i1 ~= i3)
+end
+
+unittests.register("test_itemstack_equals_metadata", test_itemstack_equals_metadata)
diff --git a/src/script/lua_api/l_item.cpp b/src/script/lua_api/l_item.cpp
index c555e90fd..f33dd1fef 100644
--- a/src/script/lua_api/l_item.cpp
+++ b/src/script/lua_api/l_item.cpp
@@ -433,6 +433,38 @@ int LuaItemStack::l_peek_item(lua_State *L)
return 1;
}
+// equals(self, other) -> bool
+int LuaItemStack::l_equals(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ LuaItemStack *o1 = checkObject<LuaItemStack>(L, 1);
+
+ // checks for non-userdata argument
+ if (!lua_isuserdata(L, 2)) {
+ lua_pushboolean(L, false);
+ return 1;
+ }
+
+ // check that the argument is an ItemStack
+ if (!lua_getmetatable(L, 2)) {
+ lua_pushboolean(L, false);
+ return 1;
+ }
+ lua_getfield(L, LUA_REGISTRYINDEX, className);
+ if (!lua_rawequal(L, -1, -2)) {
+ lua_pushboolean(L, false);
+ return 1;
+ }
+
+ LuaItemStack *o2 = checkObject<LuaItemStack>(L, 2);
+
+ ItemStack &item1 = o1->m_stack;
+ ItemStack &item2 = o2->m_stack;
+
+ lua_pushboolean(L, item1 == item2);
+ return 1;
+}
+
LuaItemStack::LuaItemStack(const ItemStack &item):
m_stack(item)
{
@@ -483,6 +515,7 @@ void LuaItemStack::Register(lua_State *L)
static const luaL_Reg metamethods[] = {
{"__tostring", mt_tostring},
{"__gc", gc_object},
+ {"__eq", l_equals},
{0, 0}
};
registerClass(L, className, methods, metamethods);
@@ -522,6 +555,7 @@ const luaL_Reg LuaItemStack::methods[] = {
luamethod(LuaItemStack, item_fits),
luamethod(LuaItemStack, take_item),
luamethod(LuaItemStack, peek_item),
+ luamethod(LuaItemStack, equals),
{0,0}
};
diff --git a/src/script/lua_api/l_item.h b/src/script/lua_api/l_item.h
index 8f4b25cf4..a4cc706d8 100644
--- a/src/script/lua_api/l_item.h
+++ b/src/script/lua_api/l_item.h
@@ -140,6 +140,9 @@ private:
// peek_item(self, peekcount=1) -> itemstack
static int l_peek_item(lua_State *L);
+ // equals(self, other) -> bool
+ static int l_equals(lua_State *L);
+
public:
DISABLE_CLASS_COPY(LuaItemStack)