Compare against canonical item name on pickup

This commit is contained in:
Wuzzy 2023-04-16 04:07:48 +02:00
parent 13be3b747a
commit e686c40c55
7 changed files with 69 additions and 7 deletions

View File

@ -17,7 +17,7 @@ Features:
the item entity will be instantly deleted
* If `_rp_canonical_item` is set in the item definition, this item (itemname) will
be used for the entity instead when it spawns. Useful when an item has multiple
variants ike a compass
variants like a compass
## Licensing
Credits: Originally by Minetest developers (from the `builtin` part of Minetest)

View File

@ -257,8 +257,9 @@ minetest.register_entity(":__builtin:item", {
end
if closest_player ~= nil and lua.item_magnet_timer <= 0 and len < ITEM_MAGNET_ACTIVE_DISTANCE then
local inv = closest_player:get_inventory()
local luastack = ItemStack(lua.itemstring)
-- Activate item magnet
if inv and inv:room_for_item("main", ItemStack(lua.itemstring)) then
if inv and inv:room_for_item("main", luastack) then
if len >= ITEM_MAGNET_COLLECT_DISTANCE then
-- Attract item to player
vec = vector.divide(vec, len) -- It's a normalize but we have len yet (vector.normalize(vec))
@ -273,13 +274,13 @@ minetest.register_entity(":__builtin:item", {
return
else
-- Player collects item if close enough
if inv:room_for_item("main", ItemStack(lua.itemstring)) then
if inv:room_for_item("main", luastack) then
if minetest.is_creative_enabled(closest_player:get_player_name()) then
if not inv:contains_item("main", ItemStack(lua.itemstring), true) then
inv:add_item("main", ItemStack(lua.itemstring))
if not inv:contains_item("main", luastack, true) and not util.contains_item_canonical(inv, "main", luastack) then
inv:add_item("main", luastack)
end
else
inv:add_item("main", ItemStack(lua.itemstring))
inv:add_item("main", luastack)
end
if lua.itemstring ~= "" then

View File

@ -1 +1,2 @@
name = rp_builtin_item
depends = rp_util

View File

@ -100,7 +100,8 @@ function minetest.handle_node_drops(pos, drops, digger)
local inv = digger:get_inventory()
if inv then
for _,item in ipairs(drops) do
if not inv:contains_item("main", item, true) then
item = ItemStack(item)
if not inv:contains_item("main", item, true) and not util.contains_item_canonical(inv, "main", item) then
inv:add_item("main", item)
end
end

View File

@ -1 +1,2 @@
name = rp_item_drop
depends = rp_util

View File

@ -172,3 +172,22 @@ Always returns `false` for non-nodes.
Returns `true` if node at given pos is water AND either a source or a "waterfall"
(water flowing downwards)
## ` util.contains_item_canonical(inv, list, stack)`
Checks if the inventory contains `stack` with the same metadata.
Unlike `inv:contains_item`, it will treat two item names as equal
if the *canonical name* of each item is equal.
The canonical name of an item is specified by the item definition field
`_rp_canonical_item`. If this is nil, the canonical item name is
same the item name.
Parameters:
* `inv`: InvRef of inventory to check
* `list`: Inventory list name
* `stack`: ItemStack to compare to
Returns `true` if a matching item was found, `false` otherwise.

View File

@ -285,3 +285,42 @@ function util.is_water_source_or_waterfall(pos)
end
return false
end
function util.contains_item_canonical(inv, list, stack)
stack = ItemStack(stack)
if stack:is_empty() then
return false
end
-- Set count and wear of stack and comparison stack
-- to identical value because we don't care about
-- those
stack:set_count(1)
stack:set_wear(0)
local def = stack:get_definition()
if not def then
return false
end
if def._rp_canonical_item then
stack:set_name(def._rp_canonical_item)
else
-- If no canonical item, just use the regular contains_item check instead
return inv:contains_item(list, stack, true)
end
-- Iterate through all items in the list and check if the item
-- is equal
for i=1, inv:get_size(list) do
local cstack = inv:get_stack(list, i)
if not cstack:is_empty() then
cstack:set_count(1)
cstack:set_wear(0)
local cdef = cstack:get_definition()
if cdef and cdef._rp_canonical_item then
cstack:set_name(cdef._rp_canonical_item)
end
if stack:equals(cstack) then
return true
end
end
end
return false
end