Item Affordance


Single items for placing multiple related items; the quality life mod that fundamentally changes some item interactions.

Tweaks
14 hours ago
2.0
5
Manufacturing Cheats

i Pipette override

11 hours ago
(updated 11 hours ago)

I had an idea for a mod like this which would condense the logistic chests into one, but I never figured out how to handle the subgroup ordering like you did.

Anyway, I came up with a prototype for how you could use runtime scripting to override the pipette behaviour for the entities which need it.


First, define this overlay keybind in data.lua:

data:extend{
{
    type = "custom-input",
    name = "item_affordance-pipette",
    key_sequence = "",
    order = "a",
    linked_game_control = "pipette",
},
}

Then here is the runtime scripting in control.lua:

-- Maps entity name -> item name
-- Maybe replace this list with a mod-data prototype
local pipetteOverrides = {
    ["splitter"] = "splitter",
    ["underground-belt"] = "underground-belt",
}

local function delayedPipette(player, name, quality)
    local proto = prototypes.item[name]
    if proto and player.valid and player.connected then
        local success = player.clear_cursor()
        if success then
            player.pipette(proto, quality, true)
        end
    end
end

local function getTaskQueue()
    return storage.taskQueue
end

local function enqueueTask(task, delay, data)
    local tick = delay + game.tick
    local entry = {
        task = task,
        data = data,
    }

    local queue = getTaskQueue()
    if queue[tick] then
        table.insert(queue[tick], entry)
    else
        queue[tick] = {entry}
    end
end

local function handleTick()
    local queue = getTaskQueue()
    local tasks = queue[game.tick]
    if tasks then
        for _, entry in pairs(tasks) do
            if entry.task == "iaPipette" then
                delayedPipette(entry.data.player,
                    entry.data.name,
                    entry.data.quality)
            end
        end
        queue[game.tick] = nil
    end
end
script.on_event(defines.events.on_tick, handleTick)

script.on_event("item_affordance-pipette", function(e)
    local player = game.get_player(e.player_index)
    if not player.is_cursor_empty() then return end

    local entity = player.selected
    if entity and pipetteOverrides[entity.name] then
        enqueueTask("iaPipette", 1, {
            player = player,
            name = pipetteOverrides[entity.name],
            quality = entity.quality,
        })
    end
end)

-- Ensure the queue exists before on_tick touches it
local function setupStorage()
    storage.taskQueue = storage.taskQueue or {}
end
script.on_init(setupStorage)
script.on_configuration_changed(setupStorage)

The most important things to understand are the overrides table at the very top, and that the custom pipette behaviour needs to run on a 1-tick delay, because mod events are processed before native keybind behaviour.

I realise comments are a little sparse because I didn't want to make the post too long, if you have any questions just ask.

11 hours ago

Thanks! It might be a while before I try to implement this. I don't have the free time like I used to, but when I get the chance I'll see if I can get this added. It really is the missing piece to this.

New response