OFPEC Forum
Editors Depot - Mission Editing and Scripting => OFP - Editing/Scripting Multiplayer => Topic started by: Rubble_Maker on 22 Jun 2003, 20:48:09
-
Hi
when writing the network code for brrseb's RAH-66 Comanche, I noticed that the "publicVariable" command is very unreliable. If many variables are broadcast simultaneously, ofp usually drops several packs. So the problem is: There are no reliable packets really - even the reliable packets are unreliable!
I though that maybe calling "publicVariable" several times could help a bit, but I'm not sue because it will make traffic even worse.
Any suggestions highly appreciated.
Rubble_Maker
-
bn880, in developing CoC_NS, came up with some details that might be of use:
when you PV lots of variables at approximately the same time, they get loaded on the same datagram, which actually improves bandwidth utilization. So I do, for example {publicvariable _x} foreach ["PV1", "PV2", "PV3"]. So open up your max frame size. Andf or best bandwidth usage, the variable names should be as short as possible. Still, if you dump a ton of PVs, you're going to get throttled.
As for "guaranteed packets" being throttled by the (directplay-based) MP engine-- yes, that's true, and I don't know what to say, but to lament it.
For UA, which at initialization fires a ton of PVs, I space the PVs out, doing say five at a time. Still, if someone's bandwidth is insufficient, it's not going to work. The goal is to get that "low-bandwidth failure" point to occur at the same time as the "impossible desync" level.
Bn880 may talk about this in his CoC_NS documentation.
-
I've had publicVariable problems making a MP map as well. I dunno if it'll help you or not, but it seems to me that the client sometimes can't get the public variable if it's broadcasted straight away. So I wait for a while, normally 0.5 or 1 second before I run any script that requires publicVariable.
-
So I wait for a while, normally 0.5 or 1 second before I run any script that requires publicVariable.
You can also tell the script to wait for the variable to change. Then change it back to something null when it's received (changing it back to null is not public, so it works just dandy).
-
Tactician, what do you mean by waiting for the publicVariable?
OK, if I define a public variable like so:
"randomTime = random 24; publicVariable randomTime"
do you mean that I should do a
"@randomTime" in the script that I want to use it?
-
Yeah, the other side of it is that, in an MP game, scripts at mission start run during debriefing. "Receiving Data" includes synchronizing game states. If you fire off a bunch of PVs at initialization (without waiting for mission start), then you'll extend the "Receiving data" period. If you hack something up for guaranteed reception (like negotiation scripts), the noise wll build so that narrowbanders are caught in RD forever.
So MP initializaiton of PVs should, for the most part, take place _after_ mission start.
-
Just another problem with these variables made public, which I have noticed:
1 - I make all variables in the same spot change to something:
var1=9
var2=24
etc
2 - I add one string variable after it (plr2mode="easy")
3 - I publicize all the variables immediatly after (there is no wait)
4 - I then display the variables which were publicized sometime after (displayed anywhere from 1 second to 20 seconds after publication)
Now the odd thing is that all the variables work perfectly fine, but the string variable just won't publicize ... I change postions, delays, etc and it never shows ... I don't understand ...
-
thx for the replies!
@PointBlank: You cannot broadcast strings in OFP! If you really need to do so, use the COC network services.
-
@PointBlank: You cannot broadcast strings in OFP! If you really need to do so, use the COC network services.
Or, if possible you could use pre-defined string arrays
e.g: string_array = ["string1","string2","string3"]
and then you transmit only a numeric array selector:
string_selector = 2
publicvariable "string_selector"
my_string = string_array select string_selector
would mean that my_string = "string3" on every client now.
This off course only makes sense, if you already know the
possible strings when defining the array.
~S~ CD
-
OK.
Thx Rubble_Maker & Chris Death
That fixes my problem ... (If only people knew what the hell to do with the bis_weaponpack!)
I'm using that idea Chris Death, thx again (my map is awesome! I'm going to publish it soon once I fix my dialog colours ...)
-
Tactician, what do you mean by waiting for the publicVariable?
OK, if I define a public variable like so:
"randomTime = random 24; publicVariable randomTime"
do you mean that I should do a
"@randomTime" in the script that I want to use it?
Try this:
;; make a game logic named server first
randomTime = 0
?(local server): randomTime = random 24; publicVariable "randomTime"
@randomTime != 0
So first it declares randomTime = 0. All clients run this line, so randomTime is 0 across the board. Then, if server is local (only true on one client), randomTime is randomized and PVed. When it is detected that randomTime has been PVed, the script continues.
You could also add the condition _time > 10 to the @ statement to timeout if the variable is not received.. but if a timeout is needed then you're already in trouble.
-
I doubt this will work Tactician. Since on the machine where this code executes, randomTime is nohing but a global variable, it WILL change when the line
randomLine=random 24
is executed. So the @-statement will never wait, since the variable changes instantly. The problem is, it does NOT change instantly on all machines. The only solution I see is to make some sort of acknowledgement handling in the scripts, i.e. each client must send some ACK message so the server knows it has received the variable. But then again, even the broadcasting of the ACK message would not be reliable, so this is not really a solution either :(
-
I doubt this will work Tactician. Since on the machine where this code executes, randomTime is nohing but a global variable, it WILL change when the line
randomLine=random 24
is executed. So the @-statement will never wait, since the variable changes instantly. The problem is, it does NOT change instantly on all machines. The only solution I see is to make some sort of acknowledgement handling in the scripts, i.e. each client must send some ACK message so the server knows it has received the variable. But then again, even the broadcasting of the ACK message would not be reliable, so this is not really a solution either
hmm - i don't get what you mean Rubble_Maker
;; make a game logic named server first
randomTime = 0
** until here the script does the same on all machines **
?(local server): randomTime = random 24;
publicVariable "randomTime"
** the line above will only be executed, where gamelogic **
** server is local = the server **
@randomTime != 0
** the clients will wait unitl publicVariable "randomTime" **
** has been updated to them **
** once the previous line on the server has been **
** finished, @randomTime != 0 is true on all machines **
randomTime = the samve randome value on all machines now
~S~ CD
-
What we're doing:
~ will wait a certain amount of time, but it also will defer a script until after mission start.
by starting with ~, and then spacing out the PV registration process (always PV the "activator" variable last), we get good performance.
to be precise, I use:
~CocIFMPDelay
and in the init scripts, I have:
?CoCIFMPDelay == CoCIFMPDelay:Goto "MPDefined"
CoCIFMPDelay = 1
#MPDefined
I also have a modded gamelogic with an init EH that sets CoCIFMPDelay to 0.
This way, I stretch out registration and initialization across the beginning of the mission. I also make it possible to test delay settings for optimal performance, and give the mission editor a simple "patch" object that optimizes it for single player.
-
Sorry Tactician, Chris, forget what I said I didn't see that server check line. The idea is okay, but still it won't work ;)
The @ will just wait forever. Once ofp has dropped the packet, it will never attampt to send it again. So there needs to be some sort of acknowledgement. If the server does not receive it within a certain time from all clients, it will PV the variable again. The problem is, like I said before, that even the acknowledgement might get dropped along the way. So it looks like the only way is what Dinger suggests: spacing out the PV's to reduce traffic. Looks like there is really no way to have reliable packets in ofp.
-
Some sort of three-way-handshake would work, wouldn't it?
-
I've never seen a publicVariable "dropped" in any of my missions. Ever. If you have that problem, you're probably using too many public functions. Or your server needs more guaranteed packet allowance. Acknowledgements and handshakes are NOT necessary, they only multiply the problem.
And the above example was only intended to broadcast the variable. All it takes to make the script wait for the randomTime is another wait statement:
@time == randomTime
After the @randomTime != 0. But why would you want to broadcast the time and do it the long, discrepancy-likely way (time will vary on every client) when you can just have the server wait for the time to be reached then broadcast the event? Two scripts execed by all:
(first, init event = false)
;; begin serverEvent.sqs
?!(local Server): exit
_randTime = random (24)
~_randTime
event = true; publicVariable "event"
exit
;; end serverEvent.sqs
;; begin clientEvent.sqs
@event
(arbitrary code here)
;; end clientEvent.sqs
I promise it will work. publicVar on a bool should be more reliable than on a number, eh?
-
Thanks Tactician :). This would definitly solve my problem getting random time on every machine and someone didn't get it and got into an endless loop of time adjusting.