diff --git a/builtin/game/item.lua b/builtin/game/item.lua index cc9be44af..5dd5312aa 100644 --- a/builtin/game/item.lua +++ b/builtin/game/item.lua @@ -360,13 +360,12 @@ end function core.item_drop(itemstack, dropper, pos) local dropper_is_player = dropper and dropper:is_player() local p = table.copy(pos) - local cnt = itemstack:get_count() if dropper_is_player then p.y = p.y + 1.2 end - local item = itemstack:take_item(cnt) - local obj = core.add_item(p, item) + local obj = core.add_item(p, ItemStack(itemstack)) if obj then + itemstack:clear() if dropper_is_player then local dir = dropper:get_look_dir() dir.x = dir.x * 2.9 @@ -375,7 +374,7 @@ function core.item_drop(itemstack, dropper, pos) obj:set_velocity(dir) obj:get_luaentity().dropped_by = dropper:get_player_name() end - return itemstack + return itemstack, obj end -- If we reach this, adding the object to the -- environment failed diff --git a/doc/lua_api.md b/doc/lua_api.md index 7f4d69021..facb20556 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -6937,8 +6937,13 @@ Defaults for the `on_place` and `on_drop` item definition functions * Parameters are the same as in `on_pickup`. * Returns the leftover itemstack. * `core.item_drop(itemstack, dropper, pos)` - * Drop the item - * returns the leftover itemstack + * Converts `itemstack` to an in-world Lua entity. + * `itemstack` (`ItemStack`) is modified (cleared) on success. + * In versions < 5.12.0, `itemstack` was cleared in all cases. + * `dropper` (`ObjectRef`) is optional. + * Returned values on success: + 1. leftover itemstack + 2. `ObjectRef` of the spawned object (provided since 5.12.0) * `core.item_eat(hp_change[, replace_with_item])` * Returns `function(itemstack, user, pointed_thing)` as a function wrapper for `core.do_item_eat`. diff --git a/games/devtest/mods/unittests/entity.lua b/games/devtest/mods/unittests/entity.lua index af91a2a94..fad7d52e9 100644 --- a/games/devtest/mods/unittests/entity.lua +++ b/games/devtest/mods/unittests/entity.lua @@ -234,3 +234,24 @@ local function test_get_bone_rot(_, pos) end end unittests.register("test_get_bone_rot", test_get_bone_rot, {map=true}) + +--------- + +-- Spawn an entity from an ItemStack +local function test_item_drop(_, pos) + local itemstack_src, itemstack_ret, obj + + -- Try to place something that does not exist (placement fails) + itemstack_src = ItemStack("n_np_solution 1") + itemstack_ret, obj = core.item_drop(itemstack_src, nil, pos) + assert(obj == nil) + assert(itemstack_ret == nil) + + -- Test known item (placement successful) + itemstack_src = ItemStack("testnodes:normal 69") + itemstack_ret, obj = core.item_drop(itemstack_src, nil, pos) + assert(obj:get_hp() ~= nil) + assert(itemstack_ret and itemstack_ret:is_empty()) + assert(itemstack_ret:equals(itemstack_src)) +end +unittests.register("test_item_drop", test_item_drop, {map=true})