Lou Montana/Sandbox – User

From Bohemia Interactive Community
Jump to navigation Jump to search
m (Change player == player to not isNull player)
m (Update w/ links)
 
(99 intermediate revisions by 5 users not shown)
Line 1: Line 1:
{{SideTOC|0.9}}
[[Category: Sandbox]]
{{Stub}}
{{Feature|informative|To go on [[Initialisation Order]].}}


This page aims to explain notions and specificities of [[Multiplayer Scripting]] and its differences with Singleplayer Scripting.<br />
{| class="wikitable sortable align-center align-left-col-1"
It features three parts:
|+ Order of Initialisation (use column sorting for respective machine order)
# [[#Notions and general knowledge|Notions and general knowledge]]
! rowspan="2" class="unsortable" style="text-align: center" | Task
# [[#Structuring Multiplayer code|Structuring Multiplayer code]]
! rowspan="2" | Exec Environment
# [[#Testing locally|Testing locally]]
! rowspan="1" colspan="5" class="unsortable" | Machine
|-
! Single Player
! Dedicated Server
! Hosted Server
! Multiplayer Client
! [[Multiplayer Scripting#Join In Progress|JIP]] MP Client


|-
| [[Arma 3: Functions Library|Functions]] with <syntaxhighlight lang="cpp" inline>recompile</syntaxhighlight> {{Link|Arma 3: Functions Library#Attributes 3|attribute}} are recompiled
| {{n/a}}
| 1 <!-- Single Player -->
| 1 <!-- Dedicated Server -->
| 1 <!-- Hosted Server -->
| 1 <!-- Multiplayer Client -->
| 1 <!-- JIP MP Client -->


= Notions and general knowledge =
== The basics ==
* In Multiplayer, players are connected to a '''server'''.
** The server is a machine that distributes information among clients, such as unit positions, vehicle speeds, etc.
** The server can be either a dedicated machine, or hosted by a player; in the latter it means the server can have a [[player]] unit.
* A machine connected to a server is called a '''client'''.
** Clients can join a mission ''after'' it started: they are considered "[[Join In Progress|JIP]]" and scripting should be adapted to them. See the [[#Join In Progress|Join In Progress]] chapter for more information.
{{Informative|In Singleplayer, the game acts as a player-hosted server ({{Inline code|[[isServer]]}} returns {{Inline code|[[true]]}}).}}
{{Warning|Some Multiplayer commands do '''not''' work in Singleplayer, such as {{Inline code|[[netId]]}} !<br />
The other way around, some Singleplayer commands do not work in Multiplayer (e.g  {{Inline code|[[setAccTime]]}}).}}
== Locality ==
=== Definitions ===
* '''LOCAL''' is an attribute for the machine where the command/script/function is executed.
** to check if an argument is local, use the [[local]] command
* '''REMOTE''' means '''non local'''. All player-controlled soldiers are remote units to a dedicated server, for example.
** to check if an argument is remote, simply use {{Inline code|[[not]] [[local]] ''myObject''}}
* [[:Category:Scripting_Commands|commands]] arguments and effects can be either '''local''' or '''global''':
{|
|style="padding-right: 0.5em;"|{{EffArg|cmd|arg|local}}
|a '''local''' argument means an argument that is processed on the machine where the command is executed
|-
|{{EffArg|cmd|arg|global}}
|a '''global''' argument means any argument, even a remote one
|-
|{{EffArg|cmd|eff|local}}
|a '''local''' effect means that the effect will only happen on the machine where the command is executed
|-
|-
|{{EffArg|cmd|eff|global}}
| [[Arma 3: Functions Library|Functions]] with <syntaxhighlight lang="cpp" inline>preInit</syntaxhighlight> {{Link|Arma 3: Functions Library#Attributes 3|attribute}} are called
|a '''global''' effect means that all the computers will receive it
| [[Scheduler#Unscheduled Environment|Unscheduled]]
|}
| 2 <!-- Single Player -->
See [[Locality in Multiplayer]] for more information.
| 2 <!-- Dedicated Server -->
| 2 <!-- Hosted Server -->
| 2 <!-- Multiplayer Client -->
| 2 <!-- JIP MP Client -->


=== Different machines and how to target them ===
{|class="bikitable"
|+ Valid for {{arma3}}
!Machine
!Conditions
|-
|-
|Dedicated Server
| Object Init Event Handlers are called
|{{Inline code|[[isDedicated]]}}
| [[Scheduler#Unscheduled Environment|Unscheduled]]
|-
| 3 <!-- Single Player -->
|Player Server
| 3 <!-- Dedicated Server -->
|{{Inline code|[[hasInterface]] && [[isServer]]}}
| 3 <!-- Hosted Server -->
|-
| 3 <!-- Multiplayer Client -->
|Player Client
| {{Icon|unchecked}} <!-- JIP MP Client -->
|{{Inline code|[[hasInterface]] && not [[isServer]]}}
|-
|[[Join In Progress|JIP]] Player Client
|{{Inline code|[[hasInterface]] && [[didJIP]]}}
|-
|[[Arma 3 Headless Client|Headless Client]]
|{{Inline code|not [[hasInterface]] && not [[isServer]]}}
|}
{{Feature arma3|Since {{arma3}}, a server-only init file is available: '''initServer.sqf''' (see [[Event Scripts]])}}
* If you want to know if the current machine is a server (Dedicated Server or Player Server), use {{Inline code|[[isServer]]}}.
* If you want to know if the current machine has a player (Player Server included), use {{Inline code|[[hasInterface]]}}.


'''For an extended version for all games, click "Show text"'''
<spoiler>
{|class="bikitable" style="line-height: normal; text-align: center"
!Targeted machine
!{{ofp}}
!{{arma}}
!{{arma2}}
!{{arma3}}
|-
!'''Dedicated Server'''<br />
<small>A server without a human player behind it</small>
|[[local]] myLogic && [[isNull]] [[player]]
|[[isServer]] && [[player]] != [[player]]
|[[isDedicated]]
|[[isDedicated]]
|-
|-
!'''Player Server'''<br />
| Expressions of [[Eden Editor: Configuring Attributes|Eden Editor entity attributes]] are called<ref name="isPlayer"><sqf inline>isPlayer _entity</sqf> does not return [[true]] immediately. Once the entity has become a [[player]], it is transferred to the client.</ref>
<small>A server hosted by a player</small>
| [[Scheduler#Unscheduled Environment|Unscheduled]]
|[[local]] myLogic && [[not]] [[isNull]] [[player]]
| 4 <!-- Single Player -->
|[[isServer]] && [[not]] [[isDedicated]]
| 4 <!-- Dedicated Server -->
|[[isServer]] && [[not]] [[isDedicated]]
| 4 <!-- Hosted Server -->
|[[hasInterface]] && [[isServer]]
| {{Icon|unchecked}} <!-- Multiplayer Client -->
|-
| {{Icon|unchecked}} <!-- JIP MP Client -->
!'''Server'''<br />
<small>Any server, dedicated or hosted</small>
|[[local]] myLogic
|[[isServer]]
|[[isServer]]
|[[isServer]]
|-
<!--
!'''Player-controller machine'''<br />
<small>Any machine controlled '''with''' a human player behind it</small>
|[[not]] [[isNull]] [[player]]
|[[not]] [[isNull]] [[player]]
|[[not]] [[isNull]] [[player]]
|[[hasInterface]]
|-
-->
!'''Player Client'''<br />
<small>A player connected since the lobby</small>
|[[not]] [[local]] myLogic && [[not]] [[isNull]] [[player]]
|[[not]] [[isServer]] && [[not]] [[isNull]] [[player]]
|[[not]] [[isServer]] && [[not]] [[isNull]] [[player]]
|[[hasInterface]] && [[not]] [[isServer]]
|-
!'''JIP Client'''<br />
<small>A player connected in the middle of a mission</small>
|''N/A''
|[[not]] [[isServer]] && [[isNull]] [[player]]
|[[not]] [[isServer]] && [[isNull]] [[player]]
|[[hasInterface]] && [[didJIP]]
|-
!'''Headless Client'''<br />
<small>A client without a human player behind it<br />
(used to offload server calculations)</small>
|colspan="3"|''N/A''
|[[not]] [[hasInterface]] && [[not]] [[isServer]]
|}


{|class="bikitable" style="text-align: center"
!Machine
!is server
!has human player
!is JIP
|-
!Dedicated Server
|{{task/}}
|{{task}}
|{{task}}
|-
!Player Server
|{{task/}}
|{{task/}}
|{{task}}
|-
|-
!Player Client
| Object initialisation fields are called
|{{task}}
| [[Scheduler#Unscheduled Environment|Unscheduled]]
|{{task/}}
| 5 <!-- Single Player -->
|{{task}}
| 5 <!-- Dedicated Server -->
|-
| 5 <!-- Hosted Server -->
!JIP Player Client
| 4 <!-- Multiplayer Client -->
|{{task}}
| 3 <!-- JIP MP Client -->
|{{task/}}
|{{task/}}
|-
!Headless Client
|{{task}}
|{{task}}
|{{task}}
|-
!JIP Headless Client
|{{task}}
|{{task}}
|{{task/}}
|}
</spoiler>
{{Warning|A [[Arma 3 Headless Client|Headless Client]] '''can''' be [[Join In Progress|JIP]]!}}


=== General information about locality ===
|- style="background-color: #95F0AD"
* about [[player]]:
| [[Event Scripts#init.sqs|init.sqs]] is executed
** a [[player]]'s unit is '''always''' local to the (human) player's machine
|
** a dedicated server doesn't have a [[player]] unit ({{Inline code|[[isNull]] [[player]]}} returns [[true]])
| 6 <!-- Single Player -->
** to know if a certain unit is ''a'' player, use [[isPlayer]]
| <!-- Dedicated Server -->
* groups and AI:
| <!-- Hosted Server -->
** an AI group with a player-leader will be local to the player's computer
| <!-- Multiplayer Client -->
** a subordinate player being in a player-lead group will remain local to its computer (see bulletpoint #1)
| <!-- JIP MP Client -->
* objects:
** a driven vehicle is always local to the machine of its driver (not the commander's, not the gunner's)
** terrain objects (buildings, vegetation, roads etc.) are local everywhere ({{Inline code|[[local]] [[nearestBuilding]] [[player]]}} returns [[true]] on every client)
** editor-placed objects and empty vehicles are local to the server
** editor-placed '''triggers''' are created on every machine unless specified otherwise ("Server Only" [[Eden Editor]] option ticked)
** units created with [[createUnit]] will be local to the computer that issued the command
** objects and vehicles created with [[createVehicle]] will be local to the computer that issued the command


=== Locality changes ===
|- style="background-color: #95F0AD"
* if the player-leader dies, the AI is transferred to the machine where the new leader is local (server in case of AI, client in case of another player)
| [[Event Scripts#init.sqf|init.sqf]] is executed
* [[join|joining]] AI units will change locality to the new leader's computer
| [[Scheduler#Scheduled Environment|Scheduled]]<ref name="enginewaits">Note '''in single player''' that while the environment is [[Scheduler#Scheduled Environment|Scheduled]] ([[canSuspend]] returns true), the engine seems to wait until the script is done executing, essentially behaving similarly to an [[Scheduler#Unscheduled Environment|Unscheduled environment]] - infinite loops will freeze the game, [[uiSleep]] may pause the game for up to ~20s (postInit), [[waitUntil]] can cause catastrophic issues, etc.</ref>
* locality will change from server to client when a player gets in an empty vehicle
| <!-- Single Player -->
* locality can also change in the event of a [[Team Switch]] or usage of [[selectPlayer]]
| <!-- Dedicated Server -->
{{Informative|Since {{arma3}} the [[Arma 3: Event Handlers#Local|"Local" Event Handler]] triggers when an object's locality is changed.}}
| <!-- Hosted Server -->
| <!-- Multiplayer Client -->
| <!-- JIP MP Client -->


=== Code examples ===
{|class="bikitable"
!Code
!Argu-ments
!Effect
!Description
|-
|{{Inline code|remoteUnit [[setDamage]] 1;}}
|align="center"|{{EffArg|cmd|arg|global}}
|align="center"|{{EffArg|cmd|eff|global}}
|Any unit (local or remote) will die, and all the computers will know
|-
|-
|{{Inline code|localUnit [[addMagazine]] "30Rnd_556x45_STANAG";}}
| Expressions of [[Eden Editor: Configuring Attributes|Eden Editor scenario attributes]] are called<ref name="playerCommandNotAvailable">[[player]] is not available immediately.</ref>
|align="center"|{{EffArg|cmd|arg|local}}
| [[Scheduler#Unscheduled Environment|Unscheduled]]
|align="center"|{{EffArg|cmd|eff|global}}
| <!-- Single Player -->
|Only a local unit can have its inventory edited with this command, but all the machines will be notified: if a player looks into the ''localUnit'' inventory, the added magazine will be there
| <!-- Dedicated Server -->
|-
| <!-- Hosted Server -->
|{{Inline code|remoteUnit [[setFace]] "Miller";}}
| <!-- Multiplayer Client -->
|align="center"|{{EffArg|cmd|arg|global}}
| <!-- JIP MP Client -->
|align="center"|{{EffArg|cmd|eff|local}}
|Any unit (local or remote) can get its face changed, but the new face will not be propagated through the network. Only the local machine's player will see the effect of the command
{{Informative|This command should ideally be '''executed on every machine''', for example with:
[remoteUnit, "Miller"] [[remoteExec]] ["setFace", 0, true];
See [[#Remote Execution|Remote Execution]] paragraph for more information.}}
|-
|<code>localCamera [[cameraEffect]] ["Internal", "Back"];</code>
|align="center"|{{EffArg|cmd|arg|local}}
|align="center"|{{EffArg|cmd|eff|local}}
|Only a local camera can be entered, and of course only the local machine will see through this camera
|}


|- style="background-color: #95DEF0"
| Persistent functions are called
|
| <!-- Single Player -->
| <!-- Dedicated Server -->
| <!-- Hosted Server -->
| <!-- Multiplayer Client -->
| <!-- JIP MP Client -->


== Network ID ==
|-
| [[Modules]] are initialised
|
| <!-- Single Player -->
| <!-- Dedicated Server -->
| <!-- Hosted Server -->
| <!-- Multiplayer Client -->
| {{Icon|unchecked}} <!-- JIP MP Client -->


Network IDs identify machines and network objects. They can be used to target proper machines with remote execution; see [[#Remote Execution|Remote Execution]] chapter for more information.
|- style="background-color: #DEF0AD"
{{Warning|'''A machine ID''' ([[owner|ownerID]]) is not to be confused with '''an object's network ID''' ([[netId]]).}}
| [[Event Scripts#initServer.sqf|initServer.sqf]] is executed
| [[Scheduler#Scheduled Environment|Scheduled]]
| <!-- Single Player -->
| <!-- Dedicated Server -->
| <!-- Hosted Server -->
| {{n/a}} <!-- Multiplayer Client -->
| {{n/a}} <!-- JIP MP Client -->


=== Machine network ID ===
|- style="background-color: #DEF0AD"
Every machine, including the server, has a '''network ID'''.<br />
| [[Event Scripts#initPlayerLocal.sqf|initPlayerLocal.sqf]] is executed
A server has an ID of '''2''', every new client has the next number (the first client will be number '''3''', second client number '''4''', etc.)
| [[Scheduler#Scheduled Environment|Scheduled]]
* To get the current machine's ID, use [[clientOwner]].
| <!-- Single Player -->
* To get the machine's ID of an object's owner, use [[owner]] ''object''  (MP only).
| {{n/a}} <!-- Dedicated Server -->
* To get the machine's ID of a group's owner, use [[groupOwner]] ''object'' (MP only).
| <!-- Hosted Server -->
<!--
| <!-- Multiplayer Client -->
TODO: confirm this information
| <!-- JIP MP Client -->
{{Important|A client disconnecting and reconnecting to the same server will keep its network ID, even if other clients connected in the meantime!}}
-->


=== Object network ID ===
|- style="background-color: #DEF0AD"
Every object synchronised through the network has a network ID, shortened to '''netId'''.
| [[Event Scripts#initPlayerServer.sqf|initPlayerServer.sqf]] is executed on the server
* To get an object's netId, use [[netId]] (MP only). '''SP &amp; MP variant:''' [[BIS_fnc_netId]]
| [[Scheduler#Scheduled Environment|Scheduled]]
* To get an object from a netId, use [[objectFromNetId]] (MP only). '''SP &amp; MP variant:''' [[BIS_fnc_objectFromNetId]]
| <!-- Single Player -->
* To get a group from a netId, use [[groupFromNetId]] (MP only). '''SP &amp; MP variant:''' [[BIS_fnc_groupFromNetId]]
| {{n/a}} <!-- Dedicated Server -->
| ?? <!-- Hosted Server -->
| <!-- Multiplayer Client -->
| <!-- JIP MP Client -->


|-
| [[Arma 3: Functions Library|Functions]] with <syntaxhighlight lang="cpp" inline>postInit</syntaxhighlight> {{Link|Arma 3: Functions Library#Attributes 3|attribute}} are called
| [[Scheduler#Scheduled Environment|Scheduled]]<ref name="enginewaits"/>
| <!-- Single Player -->
| <!-- Dedicated Server -->
| <!-- Hosted Server -->
| <!-- Multiplayer Client -->
| <!-- JIP MP Client -->


== Sending information across network ==
|- style="background-color: #95DEF0"
| [[Event Scripts#init.sqs|init.sqs]] is executed
| [[Scheduler#Scheduled Environment|Scheduled]]
| <!-- Single Player -->
| <!-- Dedicated Server -->
| <!-- Hosted Server -->
| <!-- Multiplayer Client -->
| <!-- JIP MP Client -->


=== Remote Execution ===
|- style="background-color: #95DEF0"
| [[Event Scripts#init.sqf|init.sqf]] is executed
| [[Scheduler#Scheduled Environment|Scheduled]]
| <!-- Single Player -->
| <!-- Dedicated Server -->
| <!-- Hosted Server -->
| <!-- Multiplayer Client -->
| <!-- JIP MP Client -->


Since {{arma3}} v1.50, [[remoteExec]] and [[remoteExecCall]] efficient engine network commands are available:
|-
["Message to everyone, including JIP players!", 0, true] [[remoteExec]] ["hint"];
| [[remoteExec]]'s [[Multiplayer Scripting#Join In Progress|JIP]] queue
See [[Arma 3 Remote Execution]] for more information.
| {{n/a}}
| {{n/a}} <!-- Single Player -->
| {{n/a}} <!-- Dedicated Server -->
| {{n/a}} <!-- Hosted Server -->
| {{n/a}} <!-- Multiplayer Client -->
| 42 <!-- JIP MP Client -->


{{Important|The two methods below are considered '''OBSOLETE''' since {{arma3}} v1.50!}}
|- style="background-color: #EEE"
| ''Scenario going''
| {{n/a}}
| <!-- Single Player -->
| <!-- Dedicated Server -->
| <!-- Hosted Server -->
| <!-- Multiplayer Client -->
| <!-- JIP MP Client -->


{{arma3}} alpha introduced [[BIS_fnc_MP]]:
|-
["Message to everyone, including JIP players!", "hint", true, true] call BIS_fnc_MP;
| [[Event Scripts#exit.sqf|exit.sqf]]
|
| <!-- Single Player -->
| <!-- Dedicated Server -->
| <!-- Hosted Server -->
| <!-- Multiplayer Client -->
| <!-- JIP MP Client -->


{{arma2}} introduced the (obsolete in {{arma3}}) [[Multiplayer framework]]:
|-
waitUntil { not isNil "BIS_MPF_InitDone"; };
| [[Event Scripts#exit.sqs|exit.sqs]]
[nil, nil, rHINT, "Message to everyone!"] call RE;
|
| <!-- Single Player -->
| <!-- Dedicated Server -->
| <!-- Hosted Server -->
| <!-- Multiplayer Client -->
| <!-- JIP MP Client -->


=== PublicVariable commands ===
PublicVariable commands allow to send '''global''' variables to specified machines.
* Network reception is guaranteed
* Short variable names should be used for network performance
* These commands shouldn't be used intensely for the same reason
{|class="bikitable"
!Command
!Effect
![[Join In Progress|JIP]] synchronised
|-
|[[publicVariable]]
|Set/update a variable value from the local machine to all the other machines (including server)
|align="center"|{{task/}}
|-
|[[publicVariableServer]]
|Set/update a variable value '''from a client to the server'''
|align="center"|{{task}}
|-
|-
|[[publicVariableClient]]
| {{Link|Arma 3: Mission Event Handlers#Ended|"Ended" Mission Event Handler}}
|Set/update a variable value '''from the local machine''' (not necessarily the server) '''to a specific client'''
|
|align="center"|{{task}}
| <!-- Single Player -->
|}
| <!-- Dedicated Server -->
 
| <!-- Hosted Server -->
==== How it works ====
| <!-- Multiplayer Client -->
The server has the variable {{Inline code|ABC_Score}} to broadcast:
| <!-- JIP MP Client -->
ABC_Score = 5; {{codecomment|// sets the value}}
[[publicVariable]] "ABC_Score" {{codecomment|// publishes the variable (do not forget the quotes!)}}
This sends the variable name and value to the clients.
* If the variable is not yet declared on their machine, it will declare it as well.
* If the variable already exists, '''the value is overridden''' by the server's value.
* If the variable changes again on the server, it has to be manually [[publicVariable]]'d once again!
* A [[Join In Progress|JIP]] player will synchronise '''server's''' [[publicVariable]]'d variables '''before''' executing '''init.sqf'''. See [[Initialization Order]] for more information.
** A JIP player will '''not''' synchronise [[publicVariableClient]]-received variables after he disconnects/reconnects. Only server-known public variables sent with [[publicVariable]] will be synchronised.
 
=== setVariable command ===
Available since {{arma2}} the '''public''' version of the [[setVariable]] command allows you to store a variable into an object and spread this variable across the network.
{{Feature arma3|In {{arma3}} it is possible to broadcast the [[nil]] value, thus deleting the variable from the target.}}


== Player connection events ==
The following commands will execute given code when a player is connecting or disconnecting. This code will run for players connecting in the lobby '''and''' for [[Join In Progress|JIP]] players!
* [[Arma 3: Event Handlers/addMissionEventHandler#PlayerConnected|"PlayerConnected" mission Event Handler]]
* [[Arma 3: Event Handlers/addMissionEventHandler#PlayerDisconnected|"PlayerDisconnected" mission Event Handler]]
{{Informative|Before {{arma3}} v1.57, use [[BIS_fnc_addStackedEventHandler]] for [[onPlayerConnected]]/[[onPlayerDisconnected]].}}
== Client state ==
A client state is the client's connection state. It can be obtained with [[getClientState]] and [[getClientStateNumber]] commands on both server and clients.
{|class="bikitable"
![[getClientStateNumber]]
![[getClientState]]
!Description
|-
|0
|"NONE"
|No client (or singleplayer)
|-
|1
|"CREATED"
|Client is created
|-
|2
|"CONNECTED"
|Client is connected to server, message formats are registered
|-
|3
|"LOGGED IN"
|Identity is created
|-
|4
|"MISSION SELECTED"
|Mission is selected
|-
|5
|"MISSION ASKED"
|Server was asked to send / not send mission
|-
|6
|"ROLE ASSIGNED"
|Role was assigned (and confirmed)
|-
|7
|"MISSION RECEIVED"
|Mission received
|-
|8
|"GAME LOADED"
|Island loaded, vehicles received
|-
|9
|"BRIEFING SHOWN"
|Briefing was displayed
|-
|10
|"BRIEFING READ"
|Ready to play mission
|-
|11
|"GAME FINISHED"
|Game was finished
|-
|-
|12
| {{Link|Arma 3: Mission Event Handlers#MPEnded|"MPEnded" Mission Event Handler}}
|"DEBRIEFING READ"
|
|Debriefing read, ready to continue with next mission
| <!-- Single Player -->
|}
| <!-- Dedicated Server -->
 
| <!-- Hosted Server -->
 
| <!-- Multiplayer Client -->
== Join In Progress ==
| <!-- JIP MP Client -->


A [[Join In Progress|JIP]] player will have many information synchronised by the game before accessing the mission itself. JIP was introduced in [[{{arma}}]].
{|class="bikitable"
!Information
!Arma 1
!{{arma2}}
!{{arma3}}
|-
|date/time
|align="center"|{{task/}}
|align="center"|{{task/}}
|align="center"|{{task/}}
|-
|date/time + [[setDate]]/[[skipTime]]
|align="center"|{{task}}
|align="center"|{{task}}
|align="center"|{{task/}}
|-
|weather ([[overcast]], [[fog]])
|align="center"|{{task}}
|align="center"|{{task/}}
|align="center"|{{task/}}
|-
|weather + [[setOvercast]]/[[setFog]]/[[setRain]]/[[setLightnings]]
|align="center"|{{task}}
|align="center"|{{task}}
|align="center"|{{task/}}
|-
|time passed since mission start ([[time]] command)
|align="center"|''unknown''
|align="center"|''unknown''
|align="center"|{{task/}}
|-
|[[publicVariable]]-sent variables ([[Number]], [[String]], [[Text]], [[Array]], [[Code]])
|align="center"|{{task/}}
|align="center"|{{task/}}
|align="center"|{{task/}}
|-
|[[publicVariable]]-sent variables ([[nil]])
|align="center"|{{task}}
|align="center"|{{task}}
|align="center"|{{task/}}
|-
|[[setVariable]]-assigned variables (when alternative syntax's ''public'' parameter is set to true)
|align="center"|''N/A''
|align="center"|{{task/}}
|align="center"|{{task/}}
|-
|[[remoteExec]]- and [[remoteExecCall]]-executed code if ''JIP'' prerequisites are met
|align="center"|''N/A''
|align="center"|''N/A''
|align="center"|{{task/}}
|}
|}
See [[Join In Progress]] for more information.




== See also ==
== See Also ==
 
* [[Arma 3 Headless Client|Headless Client]]
* [[Locality in Multiplayer]]
* [[:Category:Commands by effects and arguments locality|Commands by effects and arguments locality]]
** [[:Category:Commands requiring server side execution|Server-only commands]]
* [[Initialization Order]]
* [[Arma 3 Remote Execution]]
 
 
= Structuring Multiplayer code =
 
== Responsibilities ==
 
=== Server ===
The '''Server''' must be considered as the one ruler of the mission. He is the game's referee and all the decisions should come from it. All the values on the server should be considered as '''true'''.<br />
Consider the server as a powerful machine where you can put all the mission conditions and heavy scripting on.
In case of a very heavy mission, the server can be assisted by [[Arma 3 Headless Client|Headless Clients]] (this involves a per-mission specific design).
 
Server-side code must gather or wait all the variables (potentially from client-side scripts and [[publicVariableServer]]) and take and broadcast its decisions accordingly using [[publicVariable]].
 
=== Client ===
The '''Client''' must be considered as an average machine that can leave the game at any moment.
'''No mission-vital code must be executed on its side''' and '''no decisions must be taken client-side'''.<br />
Again, '''one must expect that any client can disconnect at any moment'''.
 
The client executes all the (local) UI code ([[Post process effects]], [[Dialog Control|Dialogs]], etc.)
 
 
== Mission design ==
 
=== Code diagram ===
* The '''server''' initialises and works with '''variables'''
* A connecting or connected '''player-client''' gets the mission data from the server
* Once an objective is reached, '''the server tells the players''' ''via'' [[remoteExec]]/[[remoteExecCall]] or [[publicVariable]]
* Players can get their client-side UI code triggered by the server
 
=== Code writing ===
The usual four steps of coding are the following:
* Think it well
** If you cannot figure out how to write your code, say what you want to do out loud or write it down in your language, then replace it by code little by little.
* Make it work
** use the [[Arma 3 Startup Parameters#Developer Options|-showScriptErrors]] startup parameter to see your code errors.
* Make it readable
** name your variables properly, as if you had to give it to someone that should get it without the need of explaining
* Optimise then
** use more performance-friendly commands, reduce your search radius and loop frequencies once everything works.
 
See [[Code Optimisation#Rules|Code Optimisations - Rules]] for advices and more information.
 
=== Code splitting ===
See [[#Different machines and how to target them|earlier chapter]] about how to target specific machines.
 
==== Server-side code ====
Server-side code should ideally '''not''' make any reference to a [[player]] variable considering a server can potentially be '''dedicated''', unless you want to force this mission to be player-hosted (such as {{arma2}}'s campaign).
{{Informative|Use [[allPlayers]], [[BIS_fnc_listPlayers]], [[playableUnits]] to refer to players.}}
 
==== Player-side code ====
The player's machine should not deal with a great piece of code.
{{Important|Do not forget that a server '''can''' be a player, and therefore should execute player code in that case.}}
The proper way to check for player-side condition is
[[if]] ([[hasInterface]]) [[then]] { (…) };
Note that the following example is '''incorrect''':
[[if]] ([[isServer]]) [[then]]
{
{{codecomment|// Server code goes here}}
}
  else {{codecomment|//'''WRONG:''' a server CAN be a player}}
{
(…)
};
 
==== [[Join In Progress|JIP]] Player-side code ====
As [[#Join In Progress|stated earlier]], a JIP player will automatically retrieve [[publicVariable]]'d variables from the server '''before''' executing '''init.sqf'''.
[[if]] ([[didJIP]]) [[then]]
{
(…)
[[waitUntil]] { [[not]] [[isNull]] [[player]] }; {{codecomment|// a JIP player's unit is not yet ready at this stage}}
(…)
};
 
==== [[Arma 3 Headless Client|Headless Client]] ====
{{wip}}
 
 
== See also ==


* [[Arma 3: Functions Library]]<!--
* [[Arma 2: Functions Library]] -->
* [[Arma 3: Remote Execution]], [[BIS_fnc_MP]] <!-- keep? -->
* [[Eden Editor: Configuring Attributes|Eden Editor: Configuring Attributes]]
* [[Event Scripts]]
* [[Event Scripts]]
* [[Code Optimisation]]
* [[Scheduler]]
 
 
= Testing locally =
 
To properly test MP scripting locality issues, it is recommended to run a '''dedicated server''' and connect with '''two''' clients. In order to do so:
* In your arma3server.exe's [[server.cfg]]:
<syntaxhighlight lang="cpp">
loopback = true; // force LAN-only server
kickDuplicate = 0; // disable duplicate Arma kick
 
// needed in case of Headless Client test only
headlessClients[] = { "127.0.0.1" };
localClient[] = { "127.0.0.1" };
</syntaxhighlight>
* Run Arma 3 twice from Steam and connect each (with {{Inline code|-showScriptErrors}} flag)
** If you use one screen for the first client and the other screen for the second client, use {{Inline code|-noPause -window}} launcher options. This will not pause render if the window doesn't have focus.
* Try your mission and check for script errors:
** on client's screens and [[arma.RPT|RPT files]]
** in your server's [[arma.RPT|RPT files]]
* To ensure all cases, your mission should ideally work properly:
** in Singleplayer
** in Player-hosted Multiplayer
** in a Dedicated Server-hosted game
 
{{Informative|Of course, nothing prevents you to invite friends to play your mission and report bugs!}}
 
 
== See Also ==
 
* [[Arma 3 Dedicated Server]]
* [[server.cfg]]
 
 
[[Category: Scripting Topics]]
 
 
[[Category:Sandbox]]

Latest revision as of 01:29, 18 March 2024

Order of Initialisation (use column sorting for respective machine order)
Task Exec Environment Machine
Single Player Dedicated Server Hosted Server Multiplayer Client JIP MP Client
Functions with recompile attribute are recompiled N/A 1 1 1 1 1
Functions with preInit attribute are called Unscheduled 2 2 2 2 2
Object Init Event Handlers are called Unscheduled 3 3 3 3 Unchecked
Expressions of Eden Editor entity attributes are called[1] Unscheduled 4 4 4 Unchecked Unchecked
Object initialisation fields are called Unscheduled 5 5 5 4 3
init.sqs is executed 6
init.sqf is executed Scheduled[2]
Expressions of Eden Editor scenario attributes are called[3] Unscheduled
Persistent functions are called
Modules are initialised Unchecked
initServer.sqf is executed Scheduled N/A N/A
initPlayerLocal.sqf is executed Scheduled N/A
initPlayerServer.sqf is executed on the server Scheduled N/A ??
Functions with postInit attribute are called Scheduled[2]
init.sqs is executed Scheduled
init.sqf is executed Scheduled
remoteExec's JIP queue N/A N/A N/A N/A N/A 42
Scenario going N/A
exit.sqf
exit.sqs
"Ended" Mission Event Handler
"MPEnded" Mission Event Handler


See Also

  1. isPlayer _entity does not return true immediately. Once the entity has become a player, it is transferred to the client.
  2. 2.0 2.1 Note in single player that while the environment is Scheduled (canSuspend returns true), the engine seems to wait until the script is done executing, essentially behaving similarly to an Unscheduled environment - infinite loops will freeze the game, uiSleep may pause the game for up to ~20s (postInit), waitUntil can cause catastrophic issues, etc.
  3. player is not available immediately.