Inserter Fuel Leech


In addition to normal behaviour, all Inserters take fuel from entities containing a burner when they or their drop target have no fuel left.

Tweaks
a month ago
0.16 - 2.0
88.1K
Logistics

b MP desync

a month ago
(updated a month ago)

The mod desyncs like 5 minutes into multiplayer because inserterDiscovery.lua caches its discovery state in a module local, not in storage. The host's on_init path and the joining client's on_load path then write storage.inserterDiscoveryState asymmetrically (host: never writes, client: writes once).

Sadly the repro is best described as "kinda random" because it depends on hell knows what, but it does produce a consistent source of random desyncs.

The root cause:

inserterDiscovery.lua:46:
local state = makeInserterDiscoveryState() -- module-local

inserterDiscovery.lua:60-64:
local function initInserterDiscoveryIfNeeded(tick)
if not state or state.version ~= InserterDiscoveryStateVersion then
initInserterDiscovery(tick, nil) -- this writes storage.inserterDiscoveryState
end
end

inserterDiscovery.lua:67-69:
function inserterDiscoveryOnLoad()
state = storage.inserterDiscoveryState
end

The same module-local state stuff is in inserterRepo.lua, probably another desync source.

a month ago

That local variable is holding the same table instance as storage.inserterDiscoveryState.
When starting a new game, it gets set by initInserterDiscovery in the first tick via discoverUnknownInserters -> initInserterDiscoveryIfNeeded. That function also puts the very same table into storage.inserterDiscoveryState.
When loading or joining a game, inserterDiscoveryOnLoad is called before that can happen in the on load handler and puts the table instance from storage.inserterDiscoveryState into the local state.

I don't see how the desync would be random. If it's my mod, you should get the desync in the first tick on the host or in the first tick after joining the game.
The state table is written to every tick with discovery enabled (which is the default). Even if discovery is disabled, the state is still checked to be initialized every tick (I probably should change that to save a few CPU cycles in that case). And it is only put into storage.inserterDiscoveryState on init or in the first tick after loading the game on the host (if it malfunctions, it would also do that in the first tick after a join in the joining player's game).

I probably look into this further on the weekend.

a month ago
(updated a month ago)

I think, I found it and fixed it. It should only have happened when playing with mods which build inserters without raising the appropriate build event and only after joining a game which wasn't loaded (but ran since creation). The desync should have happened on first leeching of fuel for an inserter which was discovered in a different tick than on the host. I didn't reproduce this case.

The actual bug was that on creation of a game the inserter discovery state wasn't saved to storage because the dummy in local had the correct version. So joining players got nil and therefore initialized the state on their own. Covertly spawned inserters were discovered in different ticks and therefore scheduled for processing and therefore leeching at different ticks on the host and client.
Desyncs only happen when the actual game state is out of sync (like when leeching fuel in one game instance but not the other). My assumption that different storage content immediately desyncs was false. The game only cares about actual game state.

Please test v1.0.3 and report whether (and if so, under which circumstances) desyncs still happen.

New response