Jump to content
Sign in to follow this  
mr.peanut

Dedicated server, init.sqs and publicVariable

Recommended Posts

In my init.sqs I have called a script that randomises a variable on the server and then publicvariables it. The clients wait until they receive the updated variable and then use it to skiptime.

What I have noticed, in the transition from debugging locally, to debugging on a dedicated server, is that the script only works if it is removed from the init.sqs and placed in a trigger that fires at game start. Do publicVariables not broadcast properly until the game begins?

Share this post


Link to post
Share on other sites

:edit - i should better read twice before replying icon_rolleyes.gif

soz - been a hard day yesterday - look for CrashDome's

reply wink_o.gif

~S~ CD

Share this post


Link to post
Share on other sites

You want an easy way to sync time across the network?

Here is a little 'secret':

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">if (local server) then {_skip = random 1000;call Format[" ""logic"" createunit [[0,0,0],grpNull,""skipTime %1""] ",_skip]}

This is from memory, so mention if there are errors

whistle.gif

Share this post


Link to post
Share on other sites

Well what I had was a script to randomise mission weather and start time.

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">x3 = -99

if (local server) then {x1 = random 0.40; x2 = random 1; x3 = random 10;{publicVariable _x} forEach ["x1","x2","x3"]}    

@(x3 != -99)

0 setFog x1

0 setOverCast x2

skipTime x3

_x1_0 = x1

_x2_0 = x2

x2 = -99

if (local server) then {x1 = random 0.40; x2 = random 1;{publicVariable _x} forEach ["x1","x2"]}    

@(x2 != -99)

_x1 = (x1 - _x1_0)/360

_x2 = (x2 - _x2_0)/360

_i = 0

#loop

_i = _i + 1

10 setFog (_x1*_i + _x1_0)

10 setOverCast (_x2*_i + _x2_0)

~10.5

if (_i < 360) then {goto "loop"}

exit

All of the variables being made public were defined in my init.sqs. However, when I called the above script from my init.sqs it never worked.  The time and weather were always the same. It worked on my own computer as a non-ded server but not on a ded server.  When I called the code from a trigger that fired as soon as the mission began, it worked most of the time.  The dedicated server can be a bit network laggy, often causing sync problems for triggers etc.  This has made me paranoid about executing the publicVariable command from the init.sqs, especially when passing randomised mission parameters.

Share this post


Link to post
Share on other sites

Then why not eliminate publicvariable altogether? smile_o.gif

If you have seen my suggestion, I suggest trying and playing around with it. It takes advantage of a very powerful exploit and works great.

If you are into doing more with network variables I also suggest Chain of Command's Network Services Add-on or Script package.

Share this post


Link to post
Share on other sites
Well what I had was a script to randomise mission weather and start time.

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">x3 = -99

if (local server) then {x1 = random 0.40; x2 = random 1; x3 = random 10;{publicVariable _x} forEach ["x1","x2","x3"]}    

@(x3 != -99)

0 setFog x1

0 setOverCast x2

skipTime x3

_x1_0 = x1

_x2_0 = x2

x2 = -99

if (local server) then {x1 = random 0.40; x2 = random 1;{publicVariable _x} forEach ["x1","x2"]}    

@(x2 != -99)

_x1 = (x1 - _x1_0)/360

_x2 = (x2 - _x2_0)/360

_i = 0

#loop

_i = _i + 1

10 setFog (_x1*_i + _x1_0)

10 setOverCast (_x2*_i + _x2_0)

~10.5

if (_i < 360) then {goto "loop"}

exit

All of the variables being made public were defined in my init.sqs. However, when I called the above script from my init.sqs it never worked.  The time and weather were always the same. It worked on my own computer as a non-ded server but not on a ded server.  When I called the code from a trigger that fired as soon as the mission began, it worked most of the time.  The dedicated server can be a bit network laggy, often causing sync problems for triggers etc.  This has made me paranoid about executing the publicVariable command from the init.sqs, especially when passing randomised mission parameters.

Just a guess;

did you initialize the variables: x1, x2 and x3 or did you only define them in the server only line?

?(answer == yes):  wink_o.gif

~S~ CD

Share this post


Link to post
Share on other sites

As I said in my previous post, variables x1,x2,x3 were all defined in my init.sqs. I think this is probably an issue with server lag. If the server lags too much publicVariable commands issued before the game starts are either not properly broadcasted or received. The fact that the exact same code works from a trigger suggests this. My recommendation is not to use the publicVariable command until the mission has started. If you call a script from the init.sqs that uses publicVariable put a @time>0 in it.

Share this post


Link to post
Share on other sites
You want an easy way to sync time across the network?

Here is a little 'secret':

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">if (local server) then {_skip = random 1000;call Format[" ""logic"" createunit [[0,0,0],grpNull,""skipTime %1""] ",_skip]}

This is from memory, so mention if there are errors

whistle.gif

So even though the logic is created only on the server, the init code is executed on all clients? That is weird. I guess the same approach could be used for sync'ing weather etc. with the advantage that the script need only run on the server.

Any suggestions on how to sync a camera?

Share this post


Link to post
Share on other sites
Quote[/b] ]As I said in my previous post, variables x1,x2,x3 were all defined in my init.sqs. I think this is probably an issue with server lag.  If the server lags too much publicVariable commands issued before the game starts are either not properly broadcasted or received.

You know OFP launches init scripts in MP, using two stages?

The first stage is while you are waiting for everyone to Green up. The second is when the game starts for real.

During the first stage OFP executes all the commands in the init.sqs, until it either comes across a ~ or reaches the end of the script. If it does find a ~, then it waits until the game has started before executing the rest of the script.

There are also some issues with, when the Local command returns a valid result. If you execute the local command to soon, it may not return a correct value. But I'm not to sure about those.

You might find your script runs ok if you add a slight pause at the very start.

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">~1

x3 = -99

if (local server) then {x1 = random 0.40; x2 = random 1; x3 = random 10;{publicVariable _x} forEach ["x1","x2","x3"]}    

@(x3 != -99)

0 setFog x1

0 setOverCast x2

skipTime x3

_x1_0 = x1

_x2_0 = x2

x2 = -99

if (local server) then {x1 = random 0.40; x2 = random 1;{publicVariable _x} forEach ["x1","x2"]}    

@(x2 != -99)

_x1 = (x1 - _x1_0)/360

_x2 = (x2 - _x2_0)/360

_i = 0

#loop

_i = _i + 1

10 setFog (_x1*_i + _x1_0)

10 setOverCast (_x2*_i + _x2_0)

~10.5

if (_i < 360) then {goto "loop"}

exit  

This way it will only run the rest of init.sqs once the game has started.

Anyway, worth a try?

To debug the publicvariables you could always add side chats to the @ commands:

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">@Call {Player SideChat Format ["x3 %1",x3]; (x3 != -99)}

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">@Call {Player SideChat Format ["x2 %1",x2]; (x2 != -99)}

Share this post


Link to post
Share on other sites

@UNN  thumbs-up.gif

I was going to post that until I finally reached your post. Not many people know this and it can be used to a great advantage!!

For example, our SOW script packages loads data during the first 'stage' as you call it thus making it appear as if you are just waiting a bit longer for the mission to load even though it is actually our scripts running. wink_o.gif

Also, the ~ isn't the only thing that will trigger a halt. Calling another script from within the init.sqs will also. That is why I always use functions (call loadFile) to initializeother variables for a complex set of scripts.

@Mr Peanut

Yes! The init line is executed on all clients! Spinor discovered this one back in the late days of CoC. bn880 and he did some tests and found out that even strings could be passed using this method (< 4k worth)! Not many people realized the gravity of this at the time. Even BIS's own command 'publicVariable' which is supposed to do the same thing by design has limits this simple little init-line exploit hurdles over like nobody's business.

This all justs scratches the surface. You REALLY need to look at CoC's Network Services Add-on. It will make MP weather and time syncronization look like peanuts wink_o.gif You could use it to make the cameras do whatever you want to whomever you want. A big benefit to CoC_NS IMO is also that all clients and servers are stored in an array on all machines... Want to send a message to a specific client only if they are a specific unit? want to send a message to a guy whose name is "Bob"? Want to send a message to only the guys who joined up after the first four??? etc... etc...

Share this post


Link to post
Share on other sites

I guess you have tried publicvariable "x1";publicVariable "x2";publicVariable "x3"; instead of forEach.

Or "publicVariable _x" forEach ["x1","x2","x3"]; instead of {publicVariable _x} forEach ["x1","x2","x3"];

... I think that the forEach command will interpret this array ["x1","x2","x3"] as an array of strings instead of array of variables x1,x2,x3.

Share this post


Link to post
Share on other sites

Thanks everyone for your answers.  They confirm what I suspected.  The comment about the tilda ~ wrt init.sqs is especially interesting. I often call other scripts from the init.sqs to batch initialise units; now I see that these do not actually get executed until the game starts. Furthermore, they prevent the rest of the init.sqs from completing. I can see the advantage of using functions instead as they will have to complete sequentially and will not hang the init (if I understand correctly).

As for the CoC Net... For my purposes it is using a sledgehammer to drive a tack. I am making this mission for a server on which the addons are pretty static (LOL server).  A while back I suggested a pbo be made of the CoC Netcode and be made a mandatory addon on the server, but no one listened.  There are a real variety of pings and bandwidths on the server and desync is often an unpleasant reality that creates  unexpected bugs, especially with triggers.

Share this post


Link to post
Share on other sites
As for the CoC Net... For my purposes it is using a sledgehammer to drive a tack. I am making this mission for a server on which the addons are pretty static (LOL server).  A while back I suggested a pbo be made of the CoC Netcode and be made a mandatory addon on the server, but no one listened.  There are a real variety of pings and bandwidths on the server and desync is often an unpleasant reality that creates  unexpected bugs, especially with triggers.

I would disagree and I can think of a few others that would also disagree that CoC_NS is a sledgehammer.

Rather it is more like a toolbox. Would you go work on your car with only a screwdriver?  wink_o.gif {edit: even if it is just a loose screw - you might bring your whole toolbox out, right?}

Also, CoC_NS comes in script form where all you need to do is copy the folders/files to your mission folder. This effectively eliminates the need for it as an add-on. It will increase your mission about 200k or so, but you will find that once you start using NS for one thing... next it'll be another thing... then another... and so on until it becomes something you use for all MP missions (like myself).

Share this post


Link to post
Share on other sites

I wasn't criticizing CoC NS, I just meant I am too lazy too learn to use it for one small problem. Our server has a mission size limit of 800kb and 200kb is a good slice of this. Maybe for my next mission I'll use of it. What is a good example mission that illustrates its uses beyond player to player communication? Is there one on the CoC site?

Share this post


Link to post
Share on other sites

Well, call me stupid, but the example provided with CoC_NS is mind-numbing. Although the docs describe in detail the functions, there is no simple example of how to use them. I can see how to broadcast a variable, but can not see how they are received. The docs say the receive function is internal and called by PA/client.sqs, but there are no docs on what the hell this script is.

Share this post


Link to post
Share on other sites
Quote[/b] ]publicvariable takes a string as its argument

Yes I know but does it work when said strings (the variable names) are passed to it by forEach and not the script it self? I think that's the problem in the original script. Wouldn't you have to use call and format commands for it to work? Like "call {format ["publicvariable %1",_x]}" foreach ["x1","x2","x3"]; or something like that.

Share this post


Link to post
Share on other sites
Quote[/b] ]publicvariable takes a string as its argument

Yes I know but does it work when said strings (the variable names) are passed to it by forEach and not the script it self? I think that's the problem in the original script. Wouldn't you have to use call and format commands for it to work? Like "call {format ["publicvariable %1",_x]}" foreach ["x1","x2","x3"]; or something like that.

Trust me.. it does work. There is nothing wrong with the script itself. As I said, the script works well from a trigger, just not from the init.sqs .   I have read that by using forEach in this manner all the variables are sent in one packet, which makes it a more efficient use of bandwidth.

Share this post


Link to post
Share on other sites
Quote[/b] ]publicvariable takes a string as its argument

Yes I know but does it work when said strings (the variable names) are passed to it by forEach and not the script it self? I think that's the problem in the original script. Wouldn't you have to use call and format commands for it to work? Like "call {format ["publicvariable %1",_x]}" foreach ["x1","x2","x3"]; or something like that.

actually what you suggest would effectively make them NOT strings anymore.... so what your suggesting as a solution is actually creating the problem biggrin_o.gif

@Mr. Peanut

go here:

http://www.sinewsofwar.com/Downloads/tabid/77/Default.aspx

You will see an "Intro to NS" tutorial... it is very much unfinished and generally in need of major revision (only covers small chunk of NS). However, it might help you get started since there are a few code examples.

[EDIT] I was wrong about the file size... NS is in fact 40k in size when using script folders.

Also, within the document which was written awhile ago...I spoke about using PublicVariable instead of CoC_NS to sync time/weather. I have since changed this opinion to using the initline of a create'd logic. thus eliminating PublicVariable altogether.. just wanted to address that before you read this.

Share this post


Link to post
Share on other sites

Ok, I still don't get why it wouldn't work. Even if that quoted script was run as a separate script from init.sqs, it should get run once the game starts right?

Quote[/b] ]I have read that by using forEach in this manner all the variables are sent in one packet, which makes it a more efficient use of bandwidth.

I doubt there's any difference, you're not publishing the array but the elements in the array one by one with forEach. Besides, such a tiny amount of data is negligible anyway, maybe it would make a difference if you had like several kilobytes of stuff to send (and didn't have to care about hogging the connection, like in the start of the game or something).

Share this post


Link to post
Share on other sites

In theory the first script should work. In fact, in a non-ded server environment it does.

When publicVariable was first available, I used it to send large amounts of data to other clients. I sent three integers to every client about 100 times so that I could syncronize 100 [a,b,c] arrays. What I found when running on a ded server is that about 5-6 arrays woould be empty on the clients and it would be completely random... i.e. client 1 would have arrays 5,10,40 missing, but client 2 would have arrays 23,49,67 missing.. etc.. The more players there were, the more empty arrays due to values not getting broadcast. It literally broke my whole idea I had spent a year or more on. (Maybe that's why I am so bitter about pV!! biggrin_o.gif )

When CoC came out with NS, I replaced the publicVariable system and rewrote it to include even MORE data.

I never dropped an array since.

My point is that publicvariable is and always will be unreliable - even in situations where it should work.

Share this post


Link to post
Share on other sites
My point is that publicvariable is and always will be unreliable - even in situations where it should work.

Agreed. PV sucks, especially if you have a lot of clients with laggy connections.

ps. thanks for the CoC_NS docs link. I will peruse.

Share this post


Link to post
Share on other sites
Also, within the document which was written awhile ago...I spoke about using PublicVariable instead of CoC_NS to sync time/weather. I have since changed this opinion to using the initline of a create'd logic. thus eliminating PublicVariable altogether.. just wanted to address that before you read this.

CrashDome,

By the statement above are you saying to sync time/weather you use the createunit gamelogic trick you posted earlier?  Is this because you can include it in the init.sqs so it is executed immediately without a slight delay?

But what if you are syncing weather many times, hundreds of times? Won't you end up creating hundreds of game logics?

Share this post


Link to post
Share on other sites
Quote[/b] ]The more players there were, the more empty arrays due to values not getting broadcast.

I'd guess they are broadcast but not checked if the client actually received. The randomness would also sound like it's just the normal packet loss that happens on the internet.

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this  

×