Handle item drops more carefully

Do not ignore itemstrings which contain more than just the name; fixes missing clay drops
Support dropped items with toolwear and/or metadata
This commit is contained in:
HybridDog 2019-07-01 15:37:04 +02:00
parent 871be4048e
commit 682a345495
1 changed files with 56 additions and 22 deletions

View File

@ -330,28 +330,32 @@ end
if legacy_setting_getbool("item_drop.enable_item_drop", "enable_item_drop", true) if legacy_setting_getbool("item_drop.enable_item_drop", "enable_item_drop", true)
and not minetest.settings:get_bool("creative_mode") then and not minetest.settings:get_bool("creative_mode") then
function minetest.handle_node_drops(pos, drops) -- Workaround to test if an item metadata (ItemStackMetaRef) is empty
for i = 1,#drops do local function itemmeta_is_empty(meta)
local item = drops[i] local t = meta:to_table()
local count, name for k, v in pairs(t) do
if type(item) == "string" then if k ~= "fields" then
count = 1 return false
name = item end
else assert(type(v) == "table")
count = item:get_count() if next(v) ~= nil then
name = item:get_name() return false
end
end
return true
end end
-- Sometimes nothing should be dropped -- Tests if the item has special information such as metadata
if name == "" local function can_split_item(item)
or not minetest.registered_items[name] then return item:get_wear() == 0 and itemmeta_is_empty(item:get_meta())
count = 0
end end
for _ = 1,count do local function spawn_items(pos, items_to_spawn)
local obj = minetest.add_item(pos, name) for i = 1,#items_to_spawn do
local obj = minetest.add_item(pos, items_to_spawn[i])
if not obj then if not obj then
error("Couldn't spawn item " .. name .. ", drops: " .. dump(drops)) error("Couldn't spawn item " .. name .. ", drops: "
.. dump(drops))
end end
local vel = obj:get_velocity() local vel = obj:get_velocity()
@ -368,6 +372,36 @@ and not minetest.settings:get_bool("creative_mode") then
obj:set_velocity(vel) obj:set_velocity(vel)
end end
end end
function minetest.handle_node_drops(pos, drops)
for i = 1,#drops do
local item = drops[i]
if type(item) == "string" then
-- The string is not necessarily only the item name,
-- so always convert it to ItemStack
item = ItemStack(item)
end
local count = item:get_count()
local name = item:get_name()
-- Sometimes nothing should be dropped
if name == ""
or not minetest.registered_items[name] then
count = 0
end
if count > 0 then
-- Split items if possible
local items_to_spawn = {item}
if can_split_item(item) then
for i = 1,count do
items_to_spawn[i] = name
end
end
spawn_items(pos, items_to_spawn)
end
end
end end
end end