Moon Logic deprecated

by mk-fg

Adds Lua-programmable circuit network combinator. Based on Sandboxed LuaCombinator and LuaCombinator2 mods. Probably won't work in multiplayer games.

Content
2 years ago
1.0 - 1.1
4.97K
Circuit network

i [wontfix] Multiplayer Support?

3 years ago

Hi,
Is multiplayer compatibility planned
If it is planned, is it something that could be contributed to?

3 years ago

No, I don't plan to play factorio (or any game, really) multiplayer, and so can't really test or support it there.
Mod might work there without any issues or desyncs, but that'd be an accident, and somewhat surprising, given relative complexity and player-local data used here (partly out of necessity, as factorio lua doesn't support saving lua code blobs in globals).

If there's some relatively simple tweak which can fix multiplayer, best place to submit it would probably be on github (via pull request), would be easy to merge that and remove the warning.
But I suspect that it'd require somewhat major changes and extensive multiplayer testing, which idk if anyone else can be bothered to do, so it's unlikely that multiplayer will be supported and work here, sorry.

1 year, 6 months ago
(updated 1 year, 6 months ago)

Hi,
I know this is kinda old, but I saw that it still is not implemented. Can you point out specific points in your source code where de-syncs could potentially emerge? If fixing this problem does not require a full rewrite of the mod, I would be happy to take a look at it.

I tried running it on my server, but after 1 day it broke the server. I think the issue come up when no one plays on the server and after some time someone tries to join the game and download the map.

The logs show this message.

"
160.200 Info ClientMultiplayerManager.cpp:610: UpdateTick(13595328) changing state from(ConnectedLoadingMap) to(TryingToCatchUp)
160.283 Error GameActionHandler.cpp:3606: Multiplayer desynchronisation: crc test (heuristic) failed for crcTick(13595331) serverCRC(1942282302) localCRC(2445160384)
160.283 Info ClientMultiplayerManager.cpp:610: UpdateTick(13595332) changing state from(TryingToCatchUp) to(DesyncedWaitingForMap)
160.490 Info ClientMultiplayerManager.cpp:741: updateTick(13595333) received player (4) desynced
166.706 Info ClientMultiplayerManager.cpp:747: Received mapReadyForDownload
166.706 Info ClientMultiplayerManager.cpp:610: UpdateTick(13595333) changing state from(DesyncedWaitingForMap) to(DesyncedCatchingUpWithMapReadyForDownload)
166.711 Error GameActionHandler.cpp:3606: Multiplayer desynchronisation: crc test (heuristic) failed for crcTick(13595333) serverCRC(3478103215) localCRC(3521365917)
166.715 Error GameActionHandler.cpp:3606: Multiplayer desynchronisation: crc test (heuristic) failed for crcTick(13595334) serverCRC(1291193003) localCRC(67860196)
..."

at the end it shows

"
174.769 Info ClientMultiplayerManager.cpp:610: UpdateTick(4294967295) changing state from(DesyncedCatchingUpWithMapReadyForDownload) to(DesyncedSavingLocalVariantOfMap)
191.677 Downloading file D:\Games\Factorio_x64_1.1.81\Factorio_1.1.81\temp\mp-download.zip (122493063 B, auxiliary 208 B, 243526 blocks)
191.710 Info ClientMultiplayerManager.cpp:610: UpdateTick(4294967295) changing state from(DesyncedSavingLocalVariantOfMap) to(DesyncedDownloadingMap)
200.087 Finished download (8 s, 122 MB, 14.6 MB/s)
201.452 Info ClientMultiplayerManager.cpp:727: updateTick(4294967295) map download finished creating scenario
201.452 Info ClientMultiplayerManager.cpp:610: UpdateTick(4294967295) changing state from(DesyncedDownloadingMap) to(DesyncedCreatingReport)
"
and then stops the server.

If this does not help with solving the problem, I can also provide the Client logs which I did not include for readability reasons.
I think a slight direction where the problem is likely to come from would make solving the issue far easier.
It's sad to see a mod like this not working in multiplayer.

1 year, 6 months ago
(updated 1 year, 6 months ago)

Everything in these variables (as declared at the top of control.lua) is probably the issue:

-- Stores code and built environments as {code=..., ro=..., vars=...}
-- This stuff can't be global, built locally, might be cause for desyncs
local Combinators = {}
local CombinatorEnv = {} -- to avoid self-recursive tables

Afaik factorio multiplayer runs in "lockstep", i.e. every single machine (and dedicated server, if any) runs full game simulation on their own, and have to assume that they have exactly same state - see e.g. https://www.factorio.com/blog/post/fff-76 for more info.
More on desyncs - https://wiki.factorio.com/Desynchronization
And common causes for these in mods - https://wiki.factorio.com/Tutorial:Modding_tutorial/Gangsir#Multiplayer_and_desyncs

So here you can see Cause #1 for desyncs - e.g. "local Combinators" - which will be initialized in e.g. player-1's game, and then player-2 joins, it will be immediately different for them.
I don't know if game detects this local-mismatch in Lua env immediately via some env-hash though - maybe not immediately, or maybe not at all, and the issue is only raised when something in the game world gets altered differently.

One of the things stored there is "code" objects, produced by Lua's load(...).
Afaik, and unless this changed in the last couple years, factorio does not save these objects into savegames, and iirc raises error when trying to put those into globals, or puts nil in there instead (don't remember which), i.e. does not know how to serialize those.
These "code objects" are the code being run on the combinators, and maybe simple MP-fix would be to load() them every time from string before every run?
I dunno how significant performance hit will be, but if the goal is to get at least something running with this mod, that'd be where I'd start, see if there are any other issues after this.

And once you remove code objects from there, you can replace these two local-db vars with keys in factorio "globals", which are different from lua-locals in that they get synced to other people when they join the game, so if all state is in those, everyone has same code and same data, and there will be no obvious desync-issue there.

1 year, 6 months ago
(updated 1 year, 6 months ago)

Also, given how all this simulation stuff works, if you can only reproduce issue after game runs for some time, one good trick can probably be setting game speed via server-admin console command to something silly like 100x, which would make game unplayable ofc, but afaik all simulation should run 100% faithfully, just without delays for rendering results, until it runs into same desync.
And presumably without graphics or clients to worry about, powerful-enough dedicated server CPU should be able to simulate stuff quite fast.

New response