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.