

function aom_util.register_on_wield(param)
    local overrides = {
        _on_select = function(wieldstack, player)
            return param.on_change_to_item and param.on_change_to_item(player, wieldstack) or nil
        end,
        _on_deselect = function(wieldstack, player)
            return param.on_change_from_item and param.on_change_from_item(player, wieldstack) or nil
        end,
        _on_step = function(wieldstack, player, dtime)
            return param.on_step and param.on_step(player, dtime, wieldstack) or nil
        end,
    }
    local ndef = core.registered_items[param.name]
    if not ndef then error("[aom_util.register_on_wield] no item found: \"" .. tostring(param.name) .. "\"") end
    if param.on_secondary_use then
        local old_func = rawget(ndef, "on_secondary_use") or aom_util.try_rightclick
        overrides.on_secondary_use = function(itemstack, user, pointed_thing)
            itemstack = param.on_secondary_use(ItemStack(itemstack), user, pointed_thing) or itemstack
            if old_func then return old_func(ItemStack(itemstack), user, pointed_thing) or itemstack end
        end
    end
    if param.on_place then
        local old_func = rawget(ndef, "on_place") or aom_util.try_rightclick
        overrides.on_place = function(itemstack, user, pointed_thing)
            local new_stack, pos = param.on_place(ItemStack(itemstack), user, pointed_thing)
            if new_stack then
                return new_stack, pos
            end
            if old_func then return old_func(ItemStack(itemstack), user, pointed_thing) end
        end
    end
    core.override_item(param.name, overrides)
end


local has_aom_playerapi = (core.get_modpath("aom_playerapi") ~= nil)
local wield_use_delay_pl = {}
function aom_util.register_wield_use_delay(item_name, def)
    local old_def = table.copy(core.registered_items[item_name])
    local old_on_place = old_def.on_place or core.item_place_node
    local old_on_secondary_use = old_def.on_secondary_use
    core.override_item(item_name, {
        _on_deselect = function(wieldstack, player)
            wieldstack:get_meta():set_string("a", "")
            return wieldstack
        end,
        _on_select = function(wieldstack, player)
            wieldstack:get_meta():set_string("a", "")
            return wieldstack
        end,
        on_place = function(itemstack, user, pointed_thing)
            local ret = aom_util.try_rightclick(itemstack, user, pointed_thing, false)
            if ret then
                return ret
            end
            local newstack, pos = old_on_place(itemstack, user, pointed_thing)
            if pos or (newstack and not newstack:equals(itemstack)) then
                wield_use_delay_pl[user] = {blocked = true}
                return newstack
            end
            if wield_use_delay_pl[user] ~= nil then return end
            wield_use_delay_pl[user] = {}
            wield_use_delay_pl[user].last_t = 99
            wield_use_delay_pl[user].total_time = 0
        end,
        on_secondary_use = function(itemstack, user, pointed_thing)
            wield_use_delay_pl[user] = {}
            wield_use_delay_pl[user].last_t = 99
            wield_use_delay_pl[user].total_time = 0
            if old_on_secondary_use then
                return old_on_secondary_use(itemstack, user, pointed_thing)
            end
        end,
        _on_step = function(wieldstack, player, dtime)
            if not has_aom_playerapi then core.log("need aom_playerapi mod for aom_util.register_wield_use_delay") return nil end
            local aom_playerapi = rawget(_G, "aom_playerapi")
            local ctrl = aom_playerapi.controls.get_player_control(player)
            if not ctrl then return end
            local changes_made = false

            local ret = aom_util.try_rightclick(wieldstack, player, nil, true)
            if ret then
                return ret
            end

            if ctrl.just_released.place then
                wield_use_delay_pl[player] = nil
                wieldstack:get_meta():set_string("a", "")
                changes_made = true
            end
            if ctrl.pressed.place and wield_use_delay_pl[player] and not wield_use_delay_pl[player].blocked then
                wield_use_delay_pl[player].total_time = (wield_use_delay_pl[player].total_time or 0) + dtime
                local t = math.ceil(wield_use_delay_pl[player].total_time * 4 * (def.sound_per_sec or 4))
                local last_t = (wield_use_delay_pl[player] and wield_use_delay_pl[player].last_t) or 0
                if def.sound and t ~= last_t and t % 2 == 0 then
                    local soundspec = table.copy(def.sound)
                    soundspec.object = player
                    core.sound_play(soundspec.name, soundspec, true)
                    wieldstack:get_meta():set_string("a", tostring(math.random(100)))
                    changes_made = true
                end

                wield_use_delay_pl[player].last_t = t

                if wield_use_delay_pl[player].total_time > def.windup then
                    wield_use_delay_pl[player] = {blocked = true}
                    wieldstack:get_meta():set_string("a", "")
                    wieldstack = def.on_use(wieldstack, player, nil) or wieldstack
                    changes_made = true
                end
            end
            if changes_made then
                return wieldstack
            end
        end,
    })
end
