Jump to content
Sign in to follow this  
Muzzleflash

Remote execution order and initialisation

Recommended Posts

I have two questions about remote execution using remoteExec and remoteExecCall.

 

1. Are the invocations ordered with respect to the same sender. For example, if the server performs remoteExecCall A followed by remoteExecCall B, will A run on receivers before B?

2. When are the JIP invocations performed, and are those also ordered - if so - then how? If I define custom function "MyFunction" and during the game do  [myArg1, ...] remoteExecCall ["MyFunction", 0, "MyJipId"];  at what point will "MyFunction" have to be defined (unless of course RE waits for the function to be defined which I doubt)? How can I ensure that it is defined when the remote execution framework runs the JIP calls. Do I have any choice other than putting it in CfgFunctions?

 

Thanks

Share this post


Link to post
Share on other sites

Requarding question 2 subquestion 2 -
"MyFunction" has to be defined before RE.
Requarding question 2 subquestion 3 -
If remote execution can be handled by server and needs to run on player JIP and decided to use some function other then type CfgFunctions with preinit then you can use initPlayerServer.sqf.
Execution of this script will be performed per player in que of JIP I believe.

_player = _this select 0;
_didJIP =  _this select 1;

if (_didJIP) then {
	waitUntil {!isNil "MyFunction"};
	[] remoteExec ["MyFunction", _player, false];
};

 

Share this post


Link to post
Share on other sites

Thanks for the answer. That code runs on the server in a scheduled environment, and only checks that the function is defined locally on the server: so you still need some way to ensure "MyFunction" is defined on the client (for _player) before you run it? And manually doing this seems to defeat the whole purpose of JIP IDs for remoteExec(Call), no?

Share this post


Link to post
Share on other sites

Using JIP parameter in remoteExec  in the context of initPlayerServer.sqf is redundant since initPlayerServer.sqf  already handles JIP. If  "MyFunction"  is defined or compiled from  init.sqf common to client and server wich runs at mission start before briefing screen then it would be safe to assume function is defined for client since initPlayerServer.sqf run in scheduled environment meaning time > 0 and mission has gone past briefing. This stuff gets tricky but is working for me this way.

Share this post


Link to post
Share on other sites

When the JIP-player joins the client will eventually run init.sqf and the server will eventually run initPlayerServer.sqf. Even if there execution was ordered somehow among the machines, both are  still scheduled which means either may be interrupted. So if somewhere during the run of init.sqf on the client "MyFunction" is defined, and somewhere during the run of initPlayerServer.sqf, the server calls remoteExec with no JIP, I don't see how I am guaranteed that the client finishes init.sqf before the server begins remoteExec of "MyFunction"? And, even then I still have to duplicate all my call to remoteExec in initPlayerServer.sqf?

 

Here is an example:

During game play the server does something like this: ["Yankee", 432.21] remoteExecCall ["MF_ConfigureRadio", 0, "RadioSettings"];  My intention is that then a client JIPs, the code should run automatically for the JIP. That however, requires that MF_ConfigureRadio is defined when Arma decides to run the JIP-calls to remoteExec and remoteExecCall.

Share this post


Link to post
Share on other sites

Question 1: No, the remarks at BIKI page applies also in case of 2 RE.

Question 2: I can't understand why you're making remote executed on all PC (0), JIP, a function which just could be placed in initPlayerLocal.sqf...

 

Share this post


Link to post
Share on other sites
8 minutes ago, pierremgi said:

Question 1: No, the remarks at BIKI page applies also in case of 2 RE.

Thanks. Can you give me a link or tell where those remarks are? I actually just found this which says they are ordered when using remoteExecCall (actually it is a bit ambiguous on what exactly is sequentially run - could be only the local runs) https://community.bistudio.com/wiki/Arma_3_Remote_Execution

 

8 minutes ago, pierremgi said:

Question 2: I can't understand why you're making remote executed on all PC (0), JIP, a function which just could be placed in initPlayerLocal.sqf...

 

It doesn't have to be 0. The point is not the particular values. I mean the point is not to duplicate code in both initPlayerLocal.sqf and the original call to remoteExec , when the very functionality is available and builtin. But regardless, say I do the call in initPlayerLocal.sqf,  I still need the client that I am remoteExec on to have the function defined. I am asking is there a way to do that without using CfgFunctions?

Share this post


Link to post
Share on other sites

Sorry, I don't understand what you intend to do. On my mind, you just have to place, in initPlayerLocal, your function like:

MF_configureRadio = { <some code>};

["Yankee", frequency] call MF_ConfigureRadio;

 

and just make a publicVariable on the server:

frequency = 432.21;

publicVariable "frequency";

 

then, publicVariable it for any change of this value. The JIP will run the code with the updated value.

Share this post


Link to post
Share on other sites

Yes publicVariable is the way to go for that.

Share this post


Link to post
Share on other sites

Yes you can do it like that, and then guard it on the JIP client, with: waitUntil {!isNil "frequency"};  before you use 'frequency' . And what works fine for such simple synchronization, but gets more complicated in more complex synchronization scenarios. But that means avoiding the new commands which can handle both simple and complex synchronization scenarios in one line. I am not asking for a workaround, I know how to do it 'old school'. I want to use the new commands. I am asking is there a way to ensure a function is defined before the game handles the isPersistent calls from remoteExec and remoteExecCall. It seems the init*.sqf scripts cannot guarantee that because they run in a scheduled environment.

Share this post


Link to post
Share on other sites

I understand you have to cope with initialization order. So, you can add in initPlayerLocal (the best sqf to have a player ready, JIP or not)

waitUntil {!isnil "frequency"}; That's all. As soon as the server will run and broadcast this variable (public of course!) , your initPlayerLocal can continue.

 

Sorry Muzzleflash, didn't read your comment while writing. You don't have to "check" if your function is already defined because you load it on each client you want!  Then call it locally when the server is ready, if needed. What else?

 

Ah yes! It's far better to publicVariable a little variable, rather than remoteExec any function, especially in "complex synchronization scenario".

 

Share this post


Link to post
Share on other sites
18 minutes ago, pierremgi said:

You don't have to "check" if your function is already defined because you load it on each client you want!  Then call it locally when the server is ready, if needed. What else?

Suppose the game is running. On some machine, does not have to be the server, I use remoteExecCall to synchronize something among all current machines, let's say by using "MyFunction". I also use the JIP/isPersistent flags to ensure all future machines that JIP also gets synchronized.

 

Now, machine X JIPs afterwards. X begins executing the initialization order you linked, which means running scripts, etc, and "Persistent functions are called"  (the JIP queue), which I believe refers to the function calls made using the JIP/isPersistent flags to remoteExecCall. At some point X will process the earlier call to "MyFunction" (before X joined), but that means X must have "MyFunction" ready to be executed (already loaded). I am guessing if I put it in CfgFunction it will be ready. And everything will work fine. But if I don't put it in CfgFunctions I need some other way to ensure "MyFunction" is loaded on X before the game process the function call.

Share this post


Link to post
Share on other sites

Sure. When you call a "persistent function" (initialization order speaking, remoteExecuted or BIS_fnc_MP), this function must be defined locally. You can waitUntil {!isnil "myfunction"};

 

IMHO, if you: [<params,some code as function here] remoteExec ["call" (or "spawn",0,true], then you're remote Executing a defined command (call or spawn) with a passed string of code. So, it's clear.

On the other hand, if you [params] remoteExec ["myfunction",0, true]; you need to define myfunction on each client. It's OK as far as you know it and place it in onPlayerLocal.sqf. Probably better in term of network usage as your broadcast string is shorter.

 

Share this post


Link to post
Share on other sites

Yes I only want to do the latter, and not the former to avoid "red chains" and general waste of bandwidth. But my main worry is that from the Initialization Order it appears that initPlayerLocal.sqf is run after the persistant call is made.

Share this post


Link to post
Share on other sites

  I gave up on remote JIP parameter along time ago before remoteexec was available. In bis_fnc_mp jip parameter the network traffic was compounded for each JIP and became shit after a while. I don't know if its better with remoteexec JIP now, I doubt it so I still avoid it like the plague. Still you have even newer alternative such as missionnamespace public and player can retrieve variable at any time you see fit. This will also be handy if you change radio frequency mid mission. I like to use publicVariable for some things by server before time > 0. because it has no noticeable traffic or chains before simulation when many players are in mission at start. If your function does not have scheduling then why not just use cfgfunctions preinit if your hard set on remote jip. Other wise you must be using scheduling somewhere if your function and remoteexec is not Cfg.You can schedule everything then.

Share this post


Link to post
Share on other sites
1 hour ago, Jigsor said:

  I gave up on remote JIP parameter along time ago before remoteexec was available. In bis_fnc_mp jip parameter the network traffic was compounded for each JIP and became shit after a while. I don't know if its better with remoteexec JIP now, I doubt it so I still avoid it like the plague. Still you have even newer alternative such as missionnamespace public and player can retrieve variable at any time you see fit. This will also be handy if you change radio frequency mid mission. I like to use publicVariable for some things by server before time > 0. because it has no noticeable traffic or chains before simulation when many players are in mission at start. If your function does not have scheduling then why not just use cfgfunctions preinit if your hard set on remote jip. Other wise you must be using scheduling somewhere if your function and remoteexec is not Cfg.You can schedule everything then.

 

you just have to be careful to overwrite instead of keep adding to it.

 

also there is a lot of other stuff in the jip queue, such as synchronizing the alive state of all the terrain objects.

  • Like 1

Share this post


Link to post
Share on other sites

Interesting. So, if I'm right (not sure):

- each time you create a function to be remoteExecuted for any reason, you should declare them in description.ext because you can't bat with initialization order of the event scripts (init, initServer..., initPlayer.. sqf).

- if declared (description.ext) these functions will be recompiled very soon and ready to be called (if JIP broadcast), even if player is just joining and not ready.

- there is no alternative for that, except if you can run these functions, locally, independently, just waiting for some public variable(s) as JIP process.

Share this post


Link to post
Share on other sites

Jigsor, as fn_Quiksilver says, I would overwrite the entry in the JIP queue, in my examples the JIP-string ensures that there is at most one entry in the JIP-queue. So even if gameplay has lasted many hours, and the remote execution was done multiple times for the participants, any joining player would only get a single call from the JIP-queue to that function.

 

Yes, pierremgi, that is my understanding. All of the init*.sqf scripts run after the JIP queue has been processed, and even then they are scheduled. The only accessible code that runs before is object initialization lines, and preInit functions (and "regular" functions being defined) from CfgFunctions.

 

So, it seems there is no way to ensure function loading before processing of isPersistent calls without using CfgFunctions. Perhaps the least intrusive way to do it, would be to define a single preInit function in CfgFunction that gets run early and ensures everything is loaded. Maybe I will make a wrapper around publicVariable with similar API, which basically performs the publicVariable/waitUntil method  discussed here, but also includes the concept of a JIP-queue, which I find useful.

 

Alright, thank for your answers and participation guys.

 

  • Like 1

Share this post


Link to post
Share on other sites

Thanks for this topic and for JIP "advanced" considerations.

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  

×