remoteExec: Difference between revisions
Jump to navigation
Jump to search
Lou Montana (talk | contribs) m (Text replacement - "<tt>([^ ]*\=[^ ]*)<\/tt>" to "{{hl|c= $1}}") |
Lou Montana (talk | contribs) m (Some wiki formatting) |
||
Line 91: | Line 91: | ||
|x2= send an order to specific machines: | |x2= send an order to specific machines: | ||
< | <sqf> | ||
"message" | "message" remoteExec ["hint", 0]; // sends a hint message to everyone, identical to "message" remoteExec ["hint"] | ||
"message" | "message" remoteExec ["hint", -2]; // sends a hint message to everybody but the server | ||
"message" | "message" remoteExec ["hint", myCar]; // sends a hint message where myCar is local | ||
</ | "message" remoteExec ["hint", -clientOwner]; // sends a hint message to everybody but the current machine | ||
</sqf> | |||
|x3= <!-- This example is referenced in the Syntax section. --> | |x3= <!-- This example is referenced in the Syntax section. --> | ||
Add statements to the JIP queue: | Add statements to the JIP queue: | ||
< | <sqf> | ||
private _jipId = ["mission state: the car is broken"] remoteExec ["systemChat", 0, true]; // adds the hint to the JIP queue and returns the JIP queue order id | |||
waitUntil { canMove _car }; | |||
</ | remoteExec ["", _jipId]; // the systemChat order is removed from the JIP queue | ||
</sqf> | |||
< | <sqf> | ||
["mission state: the car is broken"] remoteExec ["systemChat", 0, _queueObject]; | |||
// ... | |||
remoteExec ["", _queueObject]; // the order attached to _queueObject is removed | |||
</sqf> | |||
< | <sqf> | ||
private _jipId = ["mission state: the car is broken"] remoteExec ["systemChat", 0, "MY_JIP_ID"]; // _jipId is actually "MY_JIP_ID" now | |||
["mission state: the car is repaired"] | waitUntil { canMove _car }; | ||
["mission state: the car is repaired"] remoteExec ["systemChat", 0, "MY_JIP_ID"]; // this order replaces the previous one | |||
// ... | |||
remoteExec ["", "MY_JIP_ID"]; // the "MY_JIP_ID" order is removed from the JIP queue | |||
</sqf> | |||
|x4= Some more complex examples: | |x4= Some more complex examples: | ||
< | <sqf> | ||
[MyCurator, [[MyObject1, MyObject2], | ["Open", true] remoteExec ["BIS_fnc_arsenal", MyTargetPlayer]; | ||
[MyCurator, [[MyObject1, MyObject2], false]] remoteExec ["addCuratorEditableObjects", 2]; | |||
</sqf> | |||
|x5= A tricky example: executing {{ic|[[player]] [[setAmmo]] [<nowiki/>[[primaryWeapon]] [[player]], 1];}} (on machines where the player is in MyGroup): | |x5= A tricky example: executing {{ic|[[player]] [[setAmmo]] [<nowiki/>[[primaryWeapon]] [[player]], 1];}} (on machines where the player is in MyGroup): | ||
< | <sqf> | ||
{ | [player, [primaryWeapon player, 1]] remoteExec ["setAmmo", MyGroup]; // WRONG: the local player object is used here! | ||
</ | { player setAmmo [primaryWeapon player, 1]; } remoteExec ["call", MyGroup]; // CORRECT: the remote player object is used here | ||
</sqf> | |||
|x6= '''[[Multiplayer Scripting]] "performance trick"'''<br> | |x6= '''[[Multiplayer Scripting]] "performance trick"'''<br> | ||
This {{ic| [0, -2] [[select]] [[isDedicated]]}} check is worth to avoid '''function''' server-side calculations only: | This {{ic| [0, -2] [[select]] [[isDedicated]]}} check is worth to avoid '''function''' server-side calculations only: | ||
< | <sqf> | ||
["message"] | ["message"] remoteExec ["BIS_fnc_infoText"]; // not ideal - the function will still run on the dedicated server for nothing | ||
["message"] remoteExec ["BIS_fnc_infoText", [0, -2] select isDedicated]; // ideal - the dedicated server will not run the code, a player-hosted server will | |||
"message" | "message" remoteExec ["hint", [0, -2] select isDedicated]; // the check is too costy to be worthy | ||
"message" | "message" remoteExec ["hint"]; // the (dedicated) server will automatically ditch hint usage due to it not having an interface | ||
</ | </sqf> | ||
|x7= <!-- This example is referenced in the Description section. --> | |x7= <!-- This example is referenced in the Description section. --> | ||
As said in the description: '''commands''' will be executed in an [[Scheduler#Unscheduled Environment|unscheduled environment]] | As said in the description: '''commands''' will be executed in an [[Scheduler#Unscheduled Environment|unscheduled environment]] | ||
< | <sqf>[{ sleep 1 }] remoteExec ["call"]; // will throw an error: it is forbidden to use sleep (or waitUntil, etc) in unscheduled environment</sqf> | ||
|x8= <!-- This example is referenced in the Description section. --> | |x8= <!-- This example is referenced in the Description section. --> | ||
< | <sqf> | ||
"Message 2" | "Message 1" remoteExec ["systemChat"]; | ||
"Message 2" remoteExec ["systemChat"]; | |||
// will result in | |||
// "Message 1" | |||
// "Message 2" | |||
</ | // in this exact order on clients | ||
</sqf> | |||
|seealso= [[remoteExecCall]] [[remoteExecutedOwner]] [[isRemoteExecuted]] [[isRemoteExecutedJIP]] [[Arma 3: Remote Execution]] [[canSuspend]] [[BIS_fnc_MP]] | |seealso= [[remoteExecCall]] [[remoteExecutedOwner]] [[isRemoteExecuted]] [[isRemoteExecutedJIP]] [[Arma 3: Remote Execution]] [[canSuspend]] [[BIS_fnc_MP]] | ||
Line 168: | Line 179: | ||
will fail, as you can't use JIP and remoteExec on server only | will fail, as you can't use JIP and remoteExec on server only | ||
<code>[some params] [[remoteExec]] ['some command',2]; {{cc|works}}</code> | <code>[some params] [[remoteExec]] ['some command',2]; {{cc|works}}</code> | ||
}} | }} | ||
Line 183: | Line 185: | ||
|timestamp= 20210305004800 | |timestamp= 20210305004800 | ||
|text= The [[remoteExec]]'ed function only has to exist on the target machine. For example: | |text= The [[remoteExec]]'ed function only has to exist on the target machine. For example: | ||
< | <sqf> | ||
// initPlayerLocal.sqf | |||
TAG_fnc_testRemote = { | TAG_fnc_testRemote = { | ||
[[hint]] "Remote Exec Received"; | [[hint]] "Remote Exec Received"; | ||
};</ | }; | ||
< | </sqf> | ||
[] [[remoteExec]] ["TAG_fnc_testRemote", -2];</ | <sqf> | ||
// execute on DEDICATED server: | |||
[] [[remoteExec]] ["TAG_fnc_testRemote", -2]; | |||
</sqf> | |||
Will display a hint for every client. This is especially useful for when the server is running a mod that is not required by clients. | Will display a hint for every client. This is especially useful for when the server is running a mod that is not required by clients. | ||
}} | }} |
Revision as of 13:42, 22 March 2022
Description
- Description:
- Asks the server to execute the given function or script command on the given target machine(s).
- Functions are executed in the scheduled environment; suspension is allowed.
- Script commands are executed in the unscheduled environment; suspension is not allowed (see Example 7).
- Multiplayer:
- Remote executions are queued and are therefore executed in the same order on remote clients (see Example 8).
- Groups:
- Multiplayer
Syntax
- Syntax:
- params remoteExec [order, targets, JIP]
- Parameters:
- params: Anything - order's parameter
- order: String - Function or command name; while any function or command can be used here, only those allowed by CfgRemoteExec will actually be executed
- targets (Optional, default: 0):
- Number (See also Machine network ID):
- 0: the order will be executed globally, i.e. on the server and every connected client, including the machine where remoteExec originated
- 2: the order will only be executed on the server
- Other number: the order will be executed on the machine where clientOwner matches the given number
- Negative number: the effect is inverted: -2 means every client but not the server, -12 means the server and every client, except for the client where clientOwner returns 12
- Object - The order will be executed where the given object is local
- String - Interpreted as an Identifier (variable name). The function / command will be executed where the object or group identified by the variable with the provided name is local
- Side - The order will be executed on machines where the player is on the specified side
- Group - The order will be executed on machines where the player is in the specified group
- Array - Array of any combination of the types listed above
- Number (See also Machine network ID):
- JIP (Optional, default: false):
- Boolean - If true, a unique JIP ID is generated and the remoteExec statement is added to the JIP queue from which it will be executed for every JIP
- String:
- If the string is empty, it is interpreted as false
- If the string is in format "Number:Number" (e.g. "0:0"), it is interpreted as a netId (see below)
- Else the string is treated as a custom JIP ID and the remoteExec statement is added to the JIP queue, replacing statements that have the same JIP ID
- Object, Group or netId - The persistent execution of the remoteExec statement is attached to the given object or group.
When the object / group is deleted, the remoteExec statement is automatically removed from the JIP queue
See also Example 3 on how to remove statements from the JIP queue. - Return Value:
Alternative Syntax
- Syntax:
- remoteExec [functionName, targets, JIP]
- Parameters:
- functionName: String - See the main syntax above for more details.
- targets (Optional, default: 0): Number, Object, String, Side, Group or Array - See the main syntax above for more details.
- JIP (Optional, default: false): Boolean, String, Object, Group or netId - See the main syntax above for more details.
- Return Value:
- nil or String - See the main syntax above for more details.
Examples
- Example 1:
- How to write remoteExec/remoteExecCall:
hint "Hello"; // becomes ["Hello"] remoteExec ["hint"]; "Hello" remoteExec ["hint"]; // alternatively
unit1 setFace "Miller"; // becomes [unit1, "Miller"] remoteExec ["setFace"];
cutRsc ["", "BLACK OUT"]; // becomes [["", "BLACK OUT"]] remoteExec ["cutRsc"]; // double brackets are needed as the unary command takes an array
// functions, however, do not need double squared brackets ["line 1", "line 2"] spawn BIS_fnc_infoText; // becomes ["line 1", "line 2"] remoteExec ["BIS_fnc_infoText"];
- Example 2:
- send an order to specific machines:
"message" remoteExec ["hint", 0]; // sends a hint message to everyone, identical to "message" remoteExec ["hint"] "message" remoteExec ["hint", -2]; // sends a hint message to everybody but the server "message" remoteExec ["hint", myCar]; // sends a hint message where myCar is local "message" remoteExec ["hint", -clientOwner]; // sends a hint message to everybody but the current machine
- Example 3:
- Add statements to the JIP queue:
["mission state: the car is broken"] remoteExec ["systemChat", 0, _queueObject]; // ... remoteExec ["", _queueObject]; // the order attached to _queueObject is removedprivate _jipId = ["mission state: the car is broken"] remoteExec ["systemChat", 0, "MY_JIP_ID"]; // _jipId is actually "MY_JIP_ID" now waitUntil { canMove _car }; ["mission state: the car is repaired"] remoteExec ["systemChat", 0, "MY_JIP_ID"]; // this order replaces the previous one // ... remoteExec ["", "MY_JIP_ID"]; // the "MY_JIP_ID" order is removed from the JIP queue
- Example 4:
- Some more complex examples:
- Example 5:
- A tricky example: executing
player setAmmo [primaryWeapon player, 1];
(on machines where the player is in MyGroup):[player, [primaryWeapon player, 1]] remoteExec ["setAmmo", MyGroup]; // WRONG: the local player object is used here! { player setAmmo [primaryWeapon player, 1]; } remoteExec ["call", MyGroup]; // CORRECT: the remote player object is used here - Example 6:
- Multiplayer Scripting "performance trick"
This[0, -2] select isDedicated
check is worth to avoid function server-side calculations only:["message"] remoteExec ["BIS_fnc_infoText"]; // not ideal - the function will still run on the dedicated server for nothing ["message"] remoteExec ["BIS_fnc_infoText", [0, -2] select isDedicated]; // ideal - the dedicated server will not run the code, a player-hosted server will "message" remoteExec ["hint", [0, -2] select isDedicated]; // the check is too costy to be worthy "message" remoteExec ["hint"]; // the (dedicated) server will automatically ditch hint usage due to it not having an interface - Example 7:
- As said in the description: commands will be executed in an unscheduled environment
[{ sleep 1 }] remoteExec ["call"]; // will throw an error: it is forbidden to use sleep (or waitUntil, etc) in unscheduled environment
- Example 8:
- "Message 1" remoteExec ["systemChat"]; "Message 2" remoteExec ["systemChat"]; // will result in // "Message 1" // "Message 2" // in this exact order on clients
Additional Information
- See also:
- remoteExecCall remoteExecutedOwner isRemoteExecuted isRemoteExecutedJIP Arma 3: Remote Execution canSuspend BIS_fnc_MP
Notes
-
Report bugs on the Feedback Tracker and/or discuss them on the Arma Discord or on the Forums.
Only post proven facts here! Add Note
- Posted on Dec 29, 2015 - 20:28 (UTC)
-
remoteExec and remoteExecCall are currently filtered by BattlEye's remoteexec.txt, the string analyzed by BE is formatted the same way as the following example's output:
format ["%1 %2", functionName, str params]
If CfgRemoteExec class Functions is set to mode = 1;, the following remoteexec.txt exclusion can be used to safely allow all whitelisted *_fnc_* functions taking an array as parameter to go through:!="\w+?_fnc_\w+? \[[\S\s]*\]"
Any attempt to exploit this exclusion using other RE methods like createUnit will run into "Error Missing ;" without any malicious code being executed. Mod makers should refrain from remote-executing raw commands from clients, as they require individual exclusions, and instead use *_fnc_* functions taking an array as parameter, which are covered by the above exclusion.
- Posted on Jan 30, 2017 - 18:35 (UTC)
-
[some params] remoteExec ['some command',2,true];
will fail, as you can't use JIP and remoteExec on server only[some params] remoteExec ['some command',2]; // works
- Posted on Mar 05, 2021 - 00:48 (UTC)
-
The remoteExec'ed function only has to exist on the target machine. For example:
Will display a hint for every client. This is especially useful for when the server is running a mod that is not required by clients.// execute on DEDICATED server: [] [[remoteExec]] ["TAG_fnc_testRemote", -2];