From f205f6f539189fdd01ba5f06e469e1b66dca105f Mon Sep 17 00:00:00 2001 From: cx384 Date: Sat, 11 Oct 2025 19:38:21 +0200 Subject: [PATCH] Fix meta tool capabilities regression (#16563) This also adds a unittest to avoid issues in the future. --- games/devtest/mods/unittests/metadata.lua | 39 +++++++++++++++++++++++ src/inventory.h | 20 ++++++++---- src/itemstackmetadata.h | 5 ++- 3 files changed, 54 insertions(+), 10 deletions(-) diff --git a/games/devtest/mods/unittests/metadata.lua b/games/devtest/mods/unittests/metadata.lua index 5c518d6270..c0dee85bb9 100644 --- a/games/devtest/mods/unittests/metadata.lua +++ b/games/devtest/mods/unittests/metadata.lua @@ -128,3 +128,42 @@ local function test_node_metadata(player, pos) test_metadata(core.get_meta(pos)) end unittests.register("test_node_metadata", test_node_metadata, {map=true}) + +local function get_cracky_cap(item) + local value = item:get_tool_capabilities() + assert(type(value) == "table") + value = value.groupcaps + assert(type(value) == "table") + value = value.cracky + assert(type(value) == "table") + value = value.times + assert(type(value) == "table") + value = value[1] + assert(type(value) == "number") + return value +end + +local function test_item_metadata_tool_capabilities() + local test_caps = { + groupcaps={ + cracky={times={123}}, + }, + } + + -- has no tool capabilities + local item = ItemStack("unittests:stick") + local item_meta = item:get_meta() + assert(dump(item:get_tool_capabilities()) == dump(ItemStack(""):get_tool_capabilities())) + item_meta:set_tool_capabilities(test_caps) + -- Can't directly compare the tables, because the pushback to Lua from get_tool_capabilities() + -- adds values to left out fields of the tool capabilities table. + assert(get_cracky_cap(item) == 123) + + -- has preexisting tool capabilities in its definition table + item = ItemStack("unittests:unrepairable_tool") + item_meta = item:get_meta() + assert(get_cracky_cap(item) == 3) + item_meta:set_tool_capabilities(test_caps) + assert(get_cracky_cap(item) == 123) +end +unittests.register("test_item_metadata_tool_capabilities", test_item_metadata_tool_capabilities) diff --git a/src/inventory.h b/src/inventory.h index a20d4bfc7e..290c5cf7de 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -106,18 +106,24 @@ struct ItemStack const ToolCapabilities& getToolCapabilities( const IItemDefManager *itemdef, const ItemStack *hand = nullptr) const { - const ToolCapabilities *item_cap = itemdef->get(name).tool_capabilities; + // Check for override + auto &meta_item_cap = metadata.getToolCapabilitiesOverride(); + if (meta_item_cap.has_value()) + return meta_item_cap.value(); - if (item_cap) { - return metadata.getToolCapabilities(*item_cap); // Check for override - } + const ToolCapabilities *item_cap = itemdef->get(name).tool_capabilities; + if (item_cap) + return *item_cap; // Fall back to the hand's tool capabilities if (hand) { + auto &hand_meta_item_cap = hand->metadata.getToolCapabilitiesOverride(); + if (hand_meta_item_cap.has_value()) + return hand_meta_item_cap.value(); + item_cap = itemdef->get(hand->name).tool_capabilities; - if (item_cap) { - return hand->metadata.getToolCapabilities(*item_cap); - } + if (item_cap) + return *item_cap; } item_cap = itemdef->get("").tool_capabilities; diff --git a/src/itemstackmetadata.h b/src/itemstackmetadata.h index 62a7a12a1b..0ca631ada6 100644 --- a/src/itemstackmetadata.h +++ b/src/itemstackmetadata.h @@ -23,10 +23,9 @@ public: void serialize(std::ostream &os) const; void deSerialize(std::istream &is); - const ToolCapabilities &getToolCapabilities( - const ToolCapabilities &default_caps) const + const std::optional &getToolCapabilitiesOverride() const { - return toolcaps_override.has_value() ? *toolcaps_override : default_caps; + return toolcaps_override; } void setToolCapabilities(const ToolCapabilities &caps);