setVariable – Talk

From Bohemia Interactive Community
Revision as of 09:21, 15 August 2006 by Suma (talk | contribs) (→‎setVariable local or global in Multiplayer: Automatic synchronization considerations.)
Jump to navigation Jump to search

setVariable local or global in Multiplayer

Is this variable space local or global in multiplayer environment? If it is local, is there any way to transmit it across to all client in MP environment?

--Feersum 16:11, 19 July 2006 (CEST)


From what I know it is local. Afaik there's no way to transmit it. But remember that this info may change, as ArmA is not yet done. Maybe we can get a statement of Suma here, he should know more...

--raedor 16:14, 19 July 2006 (CEST)

Ok, explicit synchronization would probably be best solution, both from scripting and bandwidth point of view. For purely AI or player-controlled objects this isn't much of a problem even if they cannot be synchronized because all objects are local for either server or client and scripts that are interested in such variables run mostly local to that vehicle. There are however some cases like pilot controlled jump lights in F-27 Fokker paratrooper plane in FDFMod, where pilot could enable red/yellow/green jump light, and other players in cargo would see appropriate jump light textures in cargo area via setObjectTexture. In OFP:R it would require fake animation and scripts that check status of that animation repeatedly, some way of making object variables global would make such cases a lot cleaner to implement (we never got it to work really right :). All it would need then is an EventHandler to catch when object variables are synced... --Feersum 02:57, 20 July 2006 (CEST)
It is local, and there is no automatic synchronization planned. The whole object synchronization on our engine should be viewed as unreliable and non-guaranteed, and synchronizing object variables this way would probably make a lot of confusion. I think we could add some explicit synchronization mechanism if desired, similar to publicVariable. --Suma 19:43, 19 July 2006 (CEST)
I think that a synchronization mechanism is definitely needed. As Feersum already stated, without such a mechanism we would still need some ugly hacks using magazines to set global object properties. And since Multiplayer and the scripting developments on the Multiplayer sector are what kept OFP alive for the longest time, this is of no minor importance.
From the scripter's point of view, there are several possibilities to implement this. One is to keep two different commands: setVariable to set a local property, setPublicVariable to set a public property. Only I guess that this version would be a problem for the engine, since it would require the engine to constantly synchronize public properties, which it seems it isn't made for.
So the second possibility is a synchronization mechanism à la publicVariable, which could handle the matter in two different ways. First, f.i. publicObject object could synchronize all object properties over the net. I think though that this is no perfect solution, since it would be impossible or very hard for the scripter to seperate public from local variables. So, one of the best solutions would IMO be f.i. to create an extended version of publicVariable of such a syntax: object publicVariables ["property1", "property2" <, ...>] which would synchronize the given object variables over the net. Since this doesn't seem to be much different from publicVariable, I hope that it wouldn't be as hard to implement in the engine . . . --hardrock 01:12, 21 July 2006 (CEST)
Yes, the object publicVariables xxxx is exactly along the lines of what I was suggesting. --Suma 17:15, 21 July 2006 (CEST)

In my opinion, they should be by default global or there should be function to sync object local variables across all the clients or we will never get rid of ugly hack like defining "fake" animations to have per-object global numeric variables. Of course that could get very interesting if you transmit unit/vehicle/object references and they are still local for each client...

--Feersum 16:24, 19 July 2006 (CEST)

@MP behaviour: Same here :)

--raedor 16:44, 19 July 2006 (CEST)

I have to correct myself here. This command better stays local. setVehicleInit can be used for global execution of this command (this saves bandwidth performance when you don't want to have the variables public). --raedor 19:18, 19 July 2006 (CEST)
Well, than you'll have a problem when a vehicle is "given" from one player to the other, because the new player doesn't have all the vehicle variables set. So either it should be global, or there should be a way to send all varaibles attached to the vehicle to someone else, like publicVariable but with more parameters. --TeRp 12:26, 20 July 2006 (CEST)
I have to admit a few other things here. First, there might be objectvariables which should be local to the vehicle and even objectvariables which should be global (e.g. like Feersum's light example). Even if setVehicleInit might be a solution to publicate some variables, there still might be variables which the author want's to stay local to the vehicles crew (e.g. the remaining smoke launcher ammo is only important to the crew of the vehicle) but have to be transfered to another client which enters a vehicle. In this case, you need a eventhandler thingy which transfers the valid local objectvariables to the new crewmember, which might be a problem too (how to determine, which of those local variables of the crew is valid?). Another problem with setVehicleInit is that players who have joined in progress (after the setVehicleInit command) do not have the variables set. So all in all, I highly recommend to use a kind of global / local objectvariables thingy which is in some way connected to the object/vehicle and not to a player. local objectvariables get transfered to new crewmembers when they enter the vehicle and can be unset when leaving the vehicle, global variables should be broadcasted to all players when set or when new players connect. --TeRp 13:48, 20 July 2006 (CEST).


I think the main problem we're discussing here is that there is no clean way of handling MP scripts. Over the years people have come up with several different methods to handle the syncronisation of MP scripts across the network, which all have their problems:

  • publicVariable command:
    • Doesn't work with strings or arrays.
    • Requires active waiting (polling) to check when publicVariable was used.
    • Hard to send structured data like values attached to an object. Requires the scripter to implement a whole protocol to get this done reliable.
  • Switches / fake animations:
    • Only works within a certain distance of the model
    • Needs to be setup in the model
    • Only works with numeric values
    • Requires active waiting (polling) to check when a switch was changed
    • Requires the object to be known. Either the object itself needs to start an init script or the script needs to allready know the object.
    • Can't be used to send objects as there is no way to dynamically assiciate new things to the predefined switches
  • Magazines / Weapons
    • Needs to be setup in the config
    • Very limited usage since only the predefined magazines / weapons from the config can be used
    • Requires active waiting (polling) to check when the magazines of an object were changed
    • Requires the object to be known. Either the object itself needs to start an init script or the script needs to allready know the object.
    • Can't be used to send objects as there is no way to dynamically assiciate new things to the predefined magazines / weapons
  • Fired eventhandler
    • Needs to be setup in the config
    • Very limited usage since only the predefined magazines / weapons from the config can be used
    • Can't be used to send objects as there is no way to dynamically assiciate new things to the predefined magazines / weapons that are fired.
  • (something else?)

All of those only work for some situations but not for others. Those problems even led to the development of CoC network services, which is complete overkill in my opinion if you just need to send some structured data across the net in MP.

SetVehicleInit also doesn't work for all cases since it takes a string and you can't send object references that way.

The easiest and cleanest solution I can see is to enhance the publicVariable command to also being able to send strings and arrays (like hardrock also suggested above). To get rid of the active waiting I would also suggest a publicVariable eventhandler that triggers when publicVariable was used (like Feersum mentioned). That way structured and associated data can be sent easily by sending arrays that contain the object and the associated data. The command was meant for MP syncronisation of scripts anyway so I think this would be the best candidate to do exactly that. Everything else would just be adding another workaround to the long list.

For the problem with setVariable , I think the cleanest way would be to require the command only to be executed where the object is local and automatically transfer the settings when the locality of the object changes. That way the settings would allways be consistent and getting or changing them locally wouldn't be a problem with the suggestions for the publicVariable command above. Have it return a boolean to see if it succeeded and you even have a failsave for the rare case when locality changes right between checking for locality and setting variables.

Locality changes aren't that common so net traffic would be kept low compared to syncronizing the data everytime it changes and if someone really needs to set or read the settings non-locally he could do that via publicVariable. --Romolus 14:52, 21 July 2006 (CEST)

A few notes:
SetVehicleInit contains an object reference -- namely this. If you can setVariable to an object, you should be able to SetVehicleInit to broadcast the value of those objects: just try MyObject setVehicleInit {this setVariable ["Barney", 666]}
I'll confess that 95% of the time, I use CoC_NS for its remoteCall function. That said, setVariable combined with setVehicleInit should take care of most of our problems -- but we'll need to test it.
The big question mark is still JIP and how that's going to affect variables. And well, have to wait and see on that one; then do some serious tests. Having done a lot of work with MP registration and synchronisation, it's clear to me that how JIP his implemented will have serious implications for MP scripting, and we can't really give any ArmA advice until we know how JIP works.
But for my opinion, MP scripting needs to be a little "stone-aged" to reduce the amount of abuse you see. using publicVariable to transmit arrays and strings can be dangerous. What happens when someone repeatedly PV's a string that over the course of the game grows to 4kb? Or an array of enormous dimensions? High-level MP scripting commands is not the way to go: the scripter must at least have the opportunity to think about bandwidth management, and as it stands, the few MP commands that are out there, such as CreateVehicle are routinely abused, even by experienced teams.Dinger 16:56, 14 August 2006 (CEST)
That sounds like a perfect argument for engine-level syncronization of properties. Properties should be tagged "syncronizable" if needed. The object's position and other wordly data is syncronized even if it is non-guaranteed. Tagging a custom property should be a possibility. Allow the author to dictate that a certain value should be consistantly updated with other data.
If I say that array [1,2,3,4,5] needs to exist on all machines, it should have, as Suma suggests, simply an explicit capability to be sent when requested. However, if object X has a property that requires constant updating, should it not be done by the engine along with the other data? At some point, the client will get the data and action will be taken appropriately if scripted properly. If the client never gets the data, then that is equivalent to seeing a unit running in place or warping all over. You have far more problems than syncronizing a single property if that happens. Sure you could have abuse of a "syncronizable" property.. but that will always happen with any command and it also provides a way to seperate the "men from the boys" so-to-speak.
Bandwidth should also be a concern at engine level. Why do I need to use low-level commands and write a 30 line function just to send data for every situation I need to send something? Especially when others might be doing something similar within their creations. How can you ever assume bandwidth when a mission is a culmination of unpredictable addons? If someone allows 4kb of data to be sent as a result of their addon/script, then that is their own fault. Why do I need to pay the price? Note: I do agree it would be nice to manage badwidth but the truth is you can only manage what you create and you are at the mercy of everyone else's product you use - let alone other factors like # of people playing in MP --CrashDome 06:56, 15 August 2006 (CEST)
Interesting idea, however things may be not as easy as they look. To avoid enourmous bandwidth usage, it is not possible to synchronize every change in every property. For internal properties like position or animation state error metrics are known by the engine, and as a result the engine is able to prioritize what to send based on those metrics and player position. If some automatic object synchronization is to be added into the scripting, there is no way engine could know this error metrics, and the script would need to provide it somehow. (Error metrics should be some function, which is given old and new values and camera position as an input, and it is responsible to estimate how important the change is). While this is possible, it could cause significant CPU load, which would grow with the number of values registered for synchronization and with number of clients (recipients) connected, as the error metrics needs to be caculated for each of them. --Suma 10:21, 15 August 2006 (CEST)

Meaning of setVariable

Is it a way to have local variable to an object, like a real Object Langage (C++, Java...) ? Example:

  Class Myclass
  {
     Attribute1 = ...
     Attirbute2 = ...
     Method1() {}
     Method2() {}
  }

I hope it is, allowed us to attach some special thing to an unique object on map, because the only solution we have today is boolean animation in p3d models.

Can you explain that BI and improve our dreams? :)

--SoldierIsNotHistory 16:49, 19 July 2006 (CEST)

I'm not BI, but with this command you can attach a certain variable with a certain value to a certain object. You can attach a variable with the same name to different objects and with different values. --raedor 19:18, 19 July 2006 (CEST)

Is it comparable with the function fGet- and fSetProperty by hardrock from the mapfact forums? --T_D 11:59, 20 July 2006 (CEST)

Yes. --hardrock 13:46, 20 July 2006 (CEST)