Upgrading 2+ units in MP causes OOS. Is mod net message the solution?

Herostratus

Grim Harbinger of Things to Come
Joined
Jul 24, 2009
Messages
116
As has been established elsewhere, when you upgrade any more than a single unit at a time in a multiplayer game, the game will (sometimes immediately, often many many turns later) invariably go out of sync. This has been observed in various mods so it's probably a vanilla BTS issue... and unless I am misremembering, I tested the phenomenon in vanilla BTS some time ago and found it to be true there too.

Now that I know what mod net messages are, I wonder if (A) the reason this happens is because Firaxis didn't include one to account for mass-upgrading, and (B) if someone out there is willing to generate (or has already generated) the proper Python code to remedy it.

I myself do not know nearly enough Python to make this happen, but I saw a need and an opportunity to address it, so I thought I'd put this out there.
 
As far as I know upgrading is handled in the dll not Python.

However the call to the dll to do the upgrade would most likely be in the Python as it handles much of the interaction with the screen.

I suppose I am saying that this problem may be a mixture of dll and Python work, it all depends on how the call to the dll to "update all" is done.
 
There is something spooky going on here. An upgrade is performed when CvUnit::doCommand is called with COMMAND_UPGRADE as argument. However neither python or the DLL has code to send such a command. In fact the only time COMMAND_UPGRADE is for anything other than comparing with an argument is here:
CvXMLLoadUtilitySet.cpp::1074 said:
GC.getUnitInfo((UnitTypes)piIndexList[piOrderedIndex]).setCommandType(FindInInfoClass("COMMAND_UPGRADE"));

This brings up an interesting question: how is an upgrade triggered and why does it appear to only use network transmitted data if only a single unit is selected?

I know how to get network games to work in sync and should be able to spot issues if I read potentially broken code. However that will not help me at all if I can't find the code in question :( Do anybody know which code is triggered by clicking the upgrade button?

Right now all I can think of rewriting the upgrade trigger code, but it would presumably be somewhat simpler if somebody can locate the existing code.
 
Perhaps you could look in CvSelectionGroup::canDoCommand and CvSelectionGroup::setupActionCache.
 
The game exe is able to call CvGame::setupActionCache (confirmed with hex editor), which in turn calls CvSelectionGroup::setupActionCache and it doesn't look like it is called from anywhere else. In other words, it appears that the upgrade trigger code is hidden inside the game exe. Looks like it's one of those issues where you go: why place that in the exe?

It looks to me the only way to control what goes on when activating unit upgrade is to remove the button from python and then add it again, except the new one triggers code in the DLL, not the exe. In other words, the trigger code has to be rewritten.
 
Unit upgrades are handled in the DLL by the function CvUnit::upgrade(UnitTypes eUnit)
The issue is not the code for the upgrade is placed, but rather where the calling code is placed.

Correct approach:
CvMessageControl::sendDoCommand -> CvUnit::doCommand -> CvUnit::upgrade

sendDoCommand sends the command across the network and ensures that the same action takes place everywhere. I'm 99% sure the desync is due to calling CvUnit::* directly, which will skip the network sync step. Speaking from experience, that's the concept I used when fixing every single desync issue I ever encountered. Well except for the one time I learned the hard way that you can't send network traffic from within doTurn, but that's likely not the issue here.

The code responsible for starting the network sync part is the code, which triggers when the upgrade button is pressed. However I can't find any code at all related to that button.
 
This thread has already lost me :lol: (I know *nothing* about the SDK), BUT...

...yesterday I discovered that, if you try to put a unit into a group *while it's being attacked*, an OOS error occurs immediately.

So maybe the root of the issue has something to do with unit grouping, and not so much with upgrading per se. :dunno:
 
...yesterday I discovered that, if you try to put a unit into a group *while it's being attacked*, an OOS error occurs immediately.
That makes sense. If the owner upgrades unit A from warriors to axemen and this is not spread across the network, then when the combat takes place, Unit A has the stats of warriors on one computer and axemen on another. Most likely the result will be different and possibly also the number of combat rounds (which messes up the random number seed sync). This will cause the out of sync issue to be detected right away, while the type of the unit might not be enough to trigger the desync detection code.

It looks to me like the code for the upgrade button is still the culprit.

You could test this btw. Place units in a place both of you can see, talk together to agree which units are on the plot, then upgrade and talk to verify that you are still seeing the same units. If one or more units upgraded only for the owner, then it is verified that the problem is the upgrade button.
 
Back
Top Bottom