Comment 10 for bug 1800364

Notabilis (notabilis27) wrote :

I was able to figure out what is going wrong in replay_1.zip in #8. I haven't looked at the other replay files yet, but my findings are able to explain the previous observations as well as it can explain (some? all?) network desyncs.

And the problem is ... drum roll ... a global variable. Guess they are considered evil for a reason after all. ;-)
In Widelands, all economies have a unique ID. So each separated building (i.e., no connecting street) is an own economy with an own, unique, ID. To generate these IDs a simple global variable is increased each time a new economy is created (e.g., remove a street so the street network becomes split). Unfortunately, the global variable is never reset to zero. So for the first game (since restarting Widelands) the economy IDs start with zero, for the second game (without restarting Widelands) they might start at 1422 (depending on the number of economies in the first game).
When the game that is recorded in replay_1.zip has been played the economy IDs were around 170 (maybe there has already a multiplayer game been played before?). However, when watching the replay the economies within the replayed game start with ID 0 (or whatever, but most likely not at 170). So when the replay file contains the command to change the economy settings of economy 176 shortly before the time 9:06 the command is ignored since there is no economy with this number. In that case, it was a restriction for wood planks that was reduced from 40 to ~28. By itself, this failed reduction doesn't matter at first. Later on the sawmill checks whether it should work. In the original game, it decided against working since the economy limit was at 28 and there already were 30 planks. In the replayed game however it decides to work since the reduction of the economy target was never executed, resulting in the observed desync.

This can be reproduced by:
1) Start a game and abort it
2) Start a second game
3) Increase the economy target for planks to 50
4) Build a sawmill. It should start working since the economy target is high enough
5) [Optional] Restart the game
6) Watch the replay. It should desync when the sawmill is finished building

A similar sequence is possible for multiplayer games, when one player starts a (singleplayer) game before playing multiplayer, and then the economy settings are modified. By doing so I was able to enforce a multiplayer desync.

To fix this problem we have to reset the economy ID counter before each game. Either we reset the global variable when starting a game or replay, or make the ID counter a member variable of the game class. I would prefer the second, even though it is the bigger code change. I can provide the change myself, but would like a second opinion about how to fix it. It might be required to store this counter in savegames and replays, I am not sure about that one yet.