ModNetMessage?

Baldyr

"Hit It"
Joined
Dec 5, 2009
Messages
5,530
Location
Sweden
I recently realized there was a ModNetMessage event coming from the C++ code to the Python event interface. There is also a CyMessageControl.sendModNetMessage() method in the API. So you can basically create your own "event callback" with Python, then? :confused:

I can see how data is being transferred (even if it seem a bit silly to have five "slots" for data when its easy enough to put as many individual values you like into an array of some sort and pass that as the argument) from the method invocation to the event manager. But what is it good for?

What I've gathered by searching the boards is that these net messages are useful for multiplayer integrity, or something. So basically all calls should be funneled through a "Net Message" then to avoid out-of-sync issues? :confused:

How does this work? What is it good for? Should I even bother with it? :p Or should all Python work in fact be based on these net messages? :eek:

If someone could fill in the blanks here, preferable in some detail, that would be swell. Preferably starting by explaining what a net message is and perhaps even what the CyMessageControl class is for.
 
What I've gathered by searching the boards is that these net messages are useful for multiplayer integrity, or something. So basically all calls should be funneled through a "Net Message" then to avoid out-of-sync issues? :confused:

Right, AFAIK.
But it's only needed for code which is attached to non standard functions, e.g. when you have a python button.
(but i do not really know enough about that stuff here)
 
This description will probably have mistakes, but this is what I know (remember that you asked for some detail):

When playing Multiplayer, the AI acts the same across all clients. Even when random factors are involved - since the seed is shared, the random result will be the same.
The problem is the human player: the game needs to verify that when a player interacts with the game (moves a unit, selects a building for a production etc.), this information will reach to all the clients.
The system which does that is the net messages.

An example will probably be the best (this is a partial process, I'm skipping some boring details):
In the city screen, the buttons for building orders in the bottom are of type WIDGET_CONSTRUCT.
When pressed, CvMessageControl::sendPushOrder is called with the relevant parameters (city id, building type, order type=construct), which in turn creates an instance of CvNetPushOrder (which inherits from the basic CvMessageData). This instance holds the given parameters and the active player as the 'player' parameter.

The actual messages system is implemented in the exe, and the DLL calls sendMessageData() to send the message it created.

The exe handles the actual sending of the message to all clients - including the original client which created the message. In single player mode - only the client which created the message will receive it (obviously).

Each message implements writing it to a buffer (so it can be sent), reading it from a buffer (so it can be received), and executing it.

For CvNetPushOrder - the execution finds the city object according to the player id and city id and calls CvCity:: pushOrder with the appropriate parameters.

And that completes the cycle.

The ModNetMessage (actual C++ class is CvNetModNetMessage) also inherits from the basic CvMessageData, and is meant to send information between python scripts of different clients.
When it is executed, all it does is to raise the python event 'ModNetMessage' with the given parameters.
 
Thanks for the info, but when do I use it the method/callback? What is it good for? What would it add to my Python script?
 
Thanks for the info, but when do I use it the method/callback? What is it good for? What would it add to my Python script?

I'm not sure, but I guess that whenever you change any game state as a response to a UI action (e.g. pressing a button), you should send a message, and only do the action when you receive the event of this message.

There might be other scenarios but this is the only one I could think of...
 
Aha, I see. So if I somehow prompt the human player to take some action, then that data should pass through the messaging system in order not to cause OOS issues in multiplayer.
 
Aha, I see. So if I somehow prompt the human player to take some action, then that data should pass through the messaging system in order not to cause OOS issues in multiplayer.

:yup:
 
most of this message system is something of the past and not needed in Patch 3.19 anymore, but do not ask me details.

Things like Selectiongroup Missions or City Tasks are already passed via the message system, so in general my advice is to create a new mission or a new task in case you want to add a new action. To add a new mission or task you need to modify the dll though, but you don't have to worry about the message system atleast.
 
most of this message system is something of the past and not needed in Patch 3.19 anymore, but do not ask me details.

Is there another way to sync clients with regards to human actions? (or does that fall under 'details'?)
 
You should all really read the multiplayer tutorial by gerikes from 2006 at this link. Multiplayer is not really hard, but it involves thinking in a certain way. Most modders have not taken this into account, so the mods do not work in multiplayer.

Basically, any time one user interacts with a dialog to make some choice, the other clients need to know the effect. This is done by broadcasting a mod message on the net, thus the name. Vanilla random event dialogs, for example, use this mechanism underneath. If you present the user with a dialog to choose something, and you don't use modnetmessage, then congratulations your mod is broken for multiplayer.

I learned about modnetmessage by tearing apart the Gods Of Old mod, which is mostly python, and has user dialogs for things like the tsunami and meteor strikes. These require modnetmessage to avoid oos.
 
Basically, any time one user interacts with a dialog to make some choice, the other clients need to know the effect. This is done by broadcasting a mod message on the net, thus the name. Vanilla random event dialogs, for example, use this mechanism underneath. If you present the user with a dialog to choose something, and you don't use modnetmessage, then congratulations your mod is broken for multiplayer.

So this hasn't changed in 3.19. (?)
 
gods of old seems like a good example (python/CvEventmanager.py).

first you send your message, for example
Code:
CyMessageControl( ).sendModNetMessage( iMessageID, iAttackingOwner, iAttackingUnitID, iDefendingOwner, iDefendingUnitID )
then the eventcallback onModNetMessage(self, argsList): is called on every computer, not just the currentactiveone.
 
Very good info, folks! :goodjob:
 
first you send your message [...] then the eventcallback onModNetMessage(self, argsList): is called on every computer, not just the currentactiveone.

Yes, you have captured the critical point. Modders who do not realize this will simply change the database after the user makes some dialog-based choice. The other clients never know this and OOS occurs. The right way (multiplayer-friendly) is that the user interface should call modnetmessage instead of doing anything, and then the receiving callback should change the database. That way all clients instead of just the user's one, do the same change.

I suppose that many mods based on revdcm have never bothered with this, because revdcm itself has been broken for multiplayer for forever.
 
Top Bottom