From ea095d3f69e7aadbcdbe5294e5dfc42ba2fe93bf Mon Sep 17 00:00:00 2001 From: DS Date: Mon, 27 Mar 2023 20:02:23 +0200 Subject: [PATCH] Fix core.item_eat for same-item replace_with_item and split stacks before dropping (#13286) The replace_with_item can be added to the slot of the wield item, which is afterwards overwritten. This causes item loss. --- builtin/game/item.lua | 26 ++++++++++++-------------- doc/lua_api.txt | 4 ++-- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/builtin/game/item.lua b/builtin/game/item.lua index 71126b0a7..17d081f3d 100644 --- a/builtin/game/item.lua +++ b/builtin/game/item.lua @@ -390,22 +390,20 @@ function core.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed -- Changing hp might kill the player causing mods to do who-knows-what to the -- inventory, so do this before set_hp(). - if replace_with_item then - if itemstack:is_empty() then - itemstack:add_item(replace_with_item) - else - local inv = user:get_inventory() - -- Check if inv is null, since non-players don't have one - if inv and inv:room_for_item("main", {name=replace_with_item}) then - inv:add_item("main", replace_with_item) - else - local pos = user:get_pos() - pos.y = math.floor(pos.y + 0.5) - core.add_item(pos, replace_with_item) - end + replace_with_item = itemstack:add_item(replace_with_item) + user:set_wielded_item(itemstack) + if not replace_with_item:is_empty() then + local inv = user:get_inventory() + -- Check if inv is null, since non-players don't have one + if inv then + replace_with_item = inv:add_item("main", replace_with_item) end end - user:set_wielded_item(itemstack) + if not replace_with_item:is_empty() then + local pos = user:get_pos() + pos.y = math.floor(pos.y + 0.5) + core.add_item(pos, replace_with_item) + end user:set_hp(user:get_hp() + hp_change) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index fdc8e77d8..2179f44b5 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -6082,8 +6082,8 @@ Defaults for the `on_place` and `on_drop` item definition functions * Returns `function(itemstack, user, pointed_thing)` as a function wrapper for `minetest.do_item_eat`. * `replace_with_item` is the itemstring which is added to the inventory. - If the player is eating a stack, then replace_with_item goes to a - different spot. + If the player is eating a stack and `replace_with_item` doesn't fit onto + the eaten stack, then the remainings go to a different spot, or are dropped. Defaults for the `on_punch` and `on_dig` node definition callbacks ------------------------------------------------------------------