Jump to content
Romanze

Call, Spawn Trouble

Recommended Posts

I am having trouble getting a script to work. 

["script1.sqf", "BIS_fnc_execVM", true, false, true] call BIS_fnc_MP;

["script2.sqf", "BIS_fnc_execVM", true, false, true] call BIS_fnc_MP;

When script1 is called script 2 doesnt wait for it to finish, so they run at the same time. The code starts out in an initServer.sqf then ran with an execVM function. The way I understood it, is that since its spawned the sleeps and waitUntils should work. Also when a script is called, it has to finish running before the preceding code continues. I have read the wikis on scheduled environments, call, spawn, execVM. I have also googled this issue, but i'm afraid I may be misunderstanding this.

Share this post


Link to post
Share on other sites

When you use execVM the scripts run in the scheduled environment. This is an environment mean for longer running scripts. Here multiple scripts are active, partially finished, constantly getting paused and then later resumed. You have no guarantees for how long a script takes to complete, or in what order. In fact script2 may start and run to completion before script1 even gets started! Your fastest fix might be to try something like this

 

[{[] call compile preProcessFile "script1.sqf"; [] call compile preProcessFile "script2.sqf"}, "BIS_fnc_spawn", true, false, true] call BIS_fnc_MP;

Share this post


Link to post
Share on other sites

In my case, I do know when its going to finish. Non of my scripts are long, or able to be paused. For instance, script1 may be a music track with a sleep timer for the duration of the song. So in that case, I would want script1 to run then when finished script2 to run. I need script 2 to wait for 1 to be finished in order to proceed. I will try the BIS_fnc_spawn. Thank you.

Share this post


Link to post
Share on other sites
private _spawnHandle = [] spawn
{
	private _script1Handle = [] execVM "script1.sqf";
	waitUntil {scriptDone _script1Handle || isNull _script1Handle};
	private _script2Handle = [] execVM "script2.sqf";
};

Recommend you use remoteExec over BIS_fnc_MP as well.

Share this post


Link to post
Share on other sites
4 minutes ago, jshock said:

private _spawnHandle = [] spawn
{
	private _script1Handle = [] execVM "script1.sqf";
	waitUntil {scriptDone _script1Handle || isNull _script1Handle};
	private _script2Handle = [] execVM "script2.sqf";
};

 

Can I use this with ["script1", "BIS_fnc_execVM", true, false, true] call BIS_fnc_MP;? I need script1.sqf to be run on all clients and script 2 to be run on server only. Thats why I was hesitant to use scriptDone. The examples I saw were used with execVM, and unfortunately I have to use BIS_fnc_VM for MP purposes.

Share this post


Link to post
Share on other sites

Then you will probably need a flag at the top of script2 (some waitUntil condition) that will only be true if all the clients have completed script1. Which you could have each client send a message to the server and the server waitUntil messages from all clients have been received, then run script2. OR you could set a variable on each client's character with setVariable and have script2 waitUntil allPlayers have that variable defined/true.

Share this post


Link to post
Share on other sites
2 minutes ago, jshock said:

Then you will probably need a flag at the top of script2 (some waitUntil condition) that will only be true if all the clients have completed script1. Which you could have each client send a message to the server and the server waitUntil messages from all clients have been received, then run script2. OR you could set a variable on each client's character with setVariable and have script2 waitUntil allPlayers have that variable defined/true.

Great idea Thank you!

Share this post


Link to post
Share on other sites

That will work. But if you know how long script1 takes, then I would just wait that amount of time and then start script2 on the server. It avoids issues like having to handle disconnecting/timeout players, otherwise the server will wait forever.

Share this post


Link to post
Share on other sites
5 minutes ago, Muzzleflash said:

That will work. But if you know how long script1 takes, then I would just wait that amount of time and then start script2 on the server. It avoids issues like having to handle disconnecting/timeout players, otherwise the server will wait forever.

Ah okay point taken. Thank you.

Share this post


Link to post
Share on other sites
5 minutes ago, Muzzleflash said:

That will work. But if you know how long script1 takes, then I would just wait that amount of time and then start script2 on the server. It avoids issues like having to handle disconnecting/timeout players, otherwise the server will wait forever.

Fair point. That would be an issue with the first solution. But I don't think that would be the case with the second (setVariable solution):

 

//script1
_unit setVariable ["myVariable",true,true];

//script2
waitUntil {count (allPlayers select {_x getVariable ["myVariable",false]}) isEqualTo (count allPlayers)};

Since the allPlayers array would change on timeout/disconnected players, it should be fine.

Share this post


Link to post
Share on other sites
13 minutes ago, jshock said:

Fair point. That would be an issue with the first solution. But I don't think that would be the case with the second (setVariable solution):

 


//script1
_unit setVariable ["myVariable",true,true];

//script2
waitUntil {count (allPlayers select {_x getVariable ["myVariable",false]}) isEqualTo (count allPlayers)};

Since the allPlayers array would change on timeout/disconnected players, it should be fine.

These 2 scripts are repeated an infinite amount of times. Is there a way to clear the variables from the players?

Share this post


Link to post
Share on other sites

You could add a timeout feature to the waitUntil as well to make absolute sure it is executed no matter what.

Share this post


Link to post
Share on other sites

Saw your edit:

 

_unit setVariable ["myVariable",nil,true]

Share this post


Link to post
Share on other sites
12 minutes ago, jshock said:

Saw your edit:

 

 


_unit setVariable ["myVariable",nil,true]

 

Okay testing now. Thank you for your help. I will edit this post with an update.

 

Edit: 

It worked for the first iteration. There are rounds that are repeated. After the first iteration, the the waitUntils no longer work.

I have for the end of Script1:

player setVariable ["deciderDone",true,true];

and the beginning of Script2:

waitUntil {count (allPlayers select {_x getVariable ["deciderDone",false]}) isEqualTo (count allPlayers)};
player setVariable ["deciderDone",nil,true];

 

As I said seems to work the first time around, but after that its chaos ;-)

Share this post


Link to post
Share on other sites

You said script2 was only ran on the server right? You need to run the setVariable code on every player.

 

{_x setVariable ["deciderDone",nil,true];} forEach allPlayers;

Share this post


Link to post
Share on other sites
2 hours ago, jshock said:

You said script2 was only ran on the server right? You need to run the setVariable code on every player.

 

 


{_x setVariable ["deciderDone",nil,true];} forEach allPlayers;

 

<3<3<3jshock<3<3<3

Share this post


Link to post
Share on other sites
On 8/20/2017 at 5:59 PM, jshock said:

You could add a timeout feature to the waitUntil as well to make absolute sure it is executed no matter what.

So, looks like i'll need this. Tell me what you think. On the server side:

execVM "scripts\scriptpauseTimer.sqf";//all it is in here is sleep 30; forceNext = true; publicVariable "forceNext";
waitUntil {
    count (allPlayers select {_x getVariable ["resetDone",false]}) isEqualTo (count allPlayers) || forceNext;
};
{_x setVariable ["resetDone",nil,true];} forEach allPlayers;
forceNext = false;
publicVariable "forceNext";

 

or maybe:

_timeOut = 0;

waitUntil {

    (while {_timeout <= 30} do {
         _timeout = _timeout + 1;
         sleep 1;
     };  exitWith {

               forceNext = true;

          };

)
    count (allPlayers select {_x getVariable ["resetDone",false]}) isEqualTo (count allPlayers) || forceNext;
};

 

Would that suffice? Just trying here, i'm a newb.

Share this post


Link to post
Share on other sites

private _start = diag_tickTime;

private _convert =

{

    params ["_num"];

    _num/1000;

};

private _dif =

{

    params ["_num1","_num2"];

    abs(_num1 - _num2);

};

private _timeout = 30; //in seconds	waitUntil 	{	    private _thing = [diag_TickTime] call _convert;	    private _thing2 = [_start,_thing] call _dif;	 	    (count (allPlayers select {_x getVariable ["resetDone",false]}) isEqualTo (count allPlayers)) || _thing2 >= _timeout	};

Share this post


Link to post
Share on other sites

Ok, sorry for the double post. But in regards to the above...I did this on my phone, so it's untested and I'm pretty sure of my conversion on tickTime, but not completely sure.

Share this post


Link to post
Share on other sites
5 hours ago, jshock said:

 


private _start = diag_tickTime;

private _convert =

{

    params ["_num"];

    _num/1000;

};

private _dif =

{

    params ["_num1","_num2"];

    abs(_num1 - _num2);

};

private _timeout = 30; //in seconds	waitUntil 	{	    private _thing = [diag_TickTime] call _convert;	    private _thing2 = [_start,_thing] call _dif;	 	    (count (allPlayers select {_x getVariable ["resetDone",false]}) isEqualTo (count allPlayers)) || _thing2 >= _timeout	};

 

I'm not sure diag_TickTime will work because it's the time since the game started. Seeing that these Scripts are used over and over, it will always be true after 30 seconds.

Share this post


Link to post
Share on other sites

Unless I misunderstand it, yes it does take the time since the game started, but the time difference between the time it saves it into the _start variable will be different from each iteration of the waitUntil loop. Therefore, since diag_tickTime is called and saved again in the _thing variable, making it possible to calculate a difference between the two times.

 

Again, I may be mistaken, someone can correct me otherwise. Unless you're saying it's not currently working.

 

EDIT: Actually just realized an error on my part. Move the _convert function to the top of the script and the _start variable below that. Then change it to [diag_tickTime] call _convert instead of just diag_tickTime.

 

 

EDIT 2: And yes, your scripts are called over and over, but these variables are local to the script and therefore, each new call to the script means a new start time saved.

Share this post


Link to post
Share on other sites

Like this?

private _convert = {
     params ["_num"];
     _num / 1000;
};
private _start = [diag_tickTime] call _convert;
private _dif = {
     params ["_num1", "_num2"];
     abs (_num1 - _num2);
};
private _timeOut = 30;
waitUntil {
     _thing = [diag_tickTime] call _convert;
     _thing2 = [_start, _thing] call _dif;
     (count allPlayers select {_x getVariable ["resetDone", false]}) isEqualTo (count allPlayers)) || _thing2 >= _timeOut;
};
I guess before it wasn't converting the _start from milliseconds to seconds right?

Share this post


Link to post
Share on other sites

Correct on all fronts. I was getting ahead of myself when typing it out on my phone :P.

Share this post


Link to post
Share on other sites
2 hours ago, jshock said:

Correct on all fronts. I was getting ahead of myself when typing it out on my phone :P.

If you have an Android, I use the app "920 Text Editor". It's great for writing code on your phone. I will try this code out in a few minutes and get back to you. Thank you for your help.

Share this post


Link to post
Share on other sites

Just to update you, I could not get it to work. After going through the code again I realized one " ( " was missing. At this point, I found another way to handle my JIP players so I removed that timeout code. I want to say thank you very much for helping me out. I start to lose hope when I cant figure things out and you reestablished hope for me, so Thank you. I'll PM you what I am creating when i'm done.

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

×