

function aom_item_entity.try_merge_with(self, object)
    if self.object == object then return end
    local ent = object:get_luaentity()
    if not ent then return end
    if ent.name ~= "__builtin:item" then return end
    local mystack = ItemStack(self.itemstring)
    if mystack:is_empty() then return end
    local thatstack = ItemStack(ent.itemstring)
    if thatstack:is_empty() then return end
    if thatstack:get_name() ~= mystack:get_name() then return end
    if thatstack:get_wear() ~= mystack:get_wear() then return end
    local thatcount = thatstack:get_count()
    local mycount = mystack:get_count()
    local thatmax = thatstack:get_stack_max()
    if thatcount + mycount > thatmax then return end

    thatstack:set_count(mycount + thatcount)
    self.itemstring = ""
    self.object:remove()
    ent:set_item(thatstack)
    aom_item_entity.SIGNAL("on_merged_with", ent, object)
    return true
end

aom_item_entity.LISTEN("on_step", function(self, dtime, moveresult, ...)
    self._merge_timer = (self._merge_timer or 0.5) - dtime
    if self._merge_timer > 0 then return else self._merge_timer = 0.5 end
    local pos = self.object:get_pos()
    local d = aom_item_entity.get(nil, "item_merge_dist", 0.3)
    local objects = minetest.get_objects_in_area(
        vector.offset(pos, -d,-d,-d), vector.offset(pos, d, d, d))
    for i, object in ipairs(objects) do
        if aom_item_entity.try_merge_with(self, object) then return "_cancel" end
    end
end)
