R3vo/Sandbox – User

From Bohemia Interactive Community
Jump to navigation Jump to search
mNo edit summary
 
(108 intermediate revisions by 2 users not shown)
Line 1: Line 1:
Arma 3: Server Config File<br/>
{{TOC|side}}
The server configuration file can be used to configure various game server settings such as the difficulty level, how many votes are needed and welcome messages.
If you have ever wondered why you scenario is running so badly, performance profiling is the way to find it out. It allows you to find bottlenecks and slow code by capturing a "slow" frame.
The name of the file is determined by the <tt>[[:Category:Startup Parameters|-config]]</tt> command line option when launching the dedicated server. There is no default name - when you do not specify the filename, no server configuration file is loaded.
The captured data can then be viewed and analysed.


Guide:
== Getting the correct Version ==
:| Overview
Profiling is enabled in the following {{arma3}} versions
:- [[Arma 3: Dedicated Server]]
* arma3profiling_x64.exe - '''Part of the Performance Profiling Build'''
:|-- [[Arma 3: Dedicated Server (Chinese Simplified)]]
* arma3diag_x64.exe - '''Part of the Development Build'''
:|-- [[Arma 3: Dedicated Server (Chinese Traditional)]]
:| Important Files
:|-- [[server.cfg]]
:|-- [[basic.cfg]]
:|-- [[server.armaprofile]]
:| Other Topics
:|-- [[Multiplayer Server Commands]]
:|-- [[Arma 3: Mission voting]]
:|-- [[Arma 3: Headless Client]]


= Server Options =
Read [[Arma_3: Steam Branches]] for a guide on how to access these branches.
{| class="wikitable sortable" style="width: 100%"
 
! Parameter !! width="10%" | Default!! Description !! Since
{{Feature|informative|It is recommended to use the '''Performance Profiling Build''' (arma3profiling_x64.exe) for performance profiling because:
* Has tools that might not make it into development build
* Has all the profiling related commands that ''arma3diag_x64.exe'' has
* Its performance is closer to the default ''arma3_x64.exe''}}
 
== Frame Capturing ==
There are several commands that allow you to capture a frame.
* [[diag_captureFrame]]
* [[diag_captureSlowFrame]]
* [[diag_logSlowFrame]] - not available in Arma 3 :(
* [[diag_captureFrameToFile]]
In most cases you do not want to capture any or all frames, you just want to capture "slow" frames. A slow frame is a frame that takes longer than the average frame and slows down the game.
 
== How to Use ==
# Run a mission
# Execute a scripted command <sqf inline>diag_captureSlowFrame ["total", 0.3];</sqf> using any means ([[Arma 3: Debug Console|Debug Console]], mission radio trigger...)
# Once a slow frame is detected, a window will open
# In the window you will be able to browse a lot of performance-related data, which can be interesting
# To export the gathered information for sharing with others:
## Select Main Thread (if not selected yet)
## Press the Copy button
## Open an external text editor
## Paste the text into a new file
## Save the file
 
== Capture Frame UI ==
[[File: arma3-capture frame ui overview.png]]
 
# {{Wiki|TODO}}
# {{Wiki|TODO}}
# {{Wiki|TODO}}
# {{Wiki|TODO}}
# {{Wiki|TODO}}
# {{Wiki|TODO}}
# {{Wiki|TODO}}
# {{Wiki|TODO}}
# {{Wiki|TODO}}
 
== External Viewer ==
* chrome://tracing
* https://ui.perfetto.dev/
 
[[File:Performance_Profiling_04.png|thumb|diag_captureFrame sample output with custom subtree]]
== Creating Your Own Subtree ==
 
When Profiling Per-Frame Eventhandlers (PFH), [[diag_captureFrame]] only shows one blob called siFEH that contains all PFH's so you can't see what part of that is caused by your PFH.<br>
You can create your own subtree inside siFEH by wrapping your function call inside a [[isNil]] CODE statement like this:<br>
Turn your old call which may look like this:
<sqf>
addMissionEventHandler ["EachFrame", {
call myPFHFunction
}];
</sqf>
 
Into something like this:
<sqf>
addMissionEventHandler ["EachFrame", {
isNil { call myPFHFunction } // isNil creates the subtree
}];
</sqf>
 
Now when you run [[diag_captureFrame]] inside of siPFH you will have a subtree called gsEva and behind that you can see the first line of code inside the isNil statement.<br>
It will only show a part of the first line of that code so you should put something descriptive into the [[isNil]] statement.<br>
You can use the same to create a subtree for any function you like. This will also work inside [[Scheduler#Scheduled_Environment|Scheduled]] ([[spawn]]ed) scripts. <br>
But using this method to "subtree" a function with return values requires a little bit of trickery to get the return value out.
 
 
== Notes ==
 
* 0.3 is a time in second used to determine what duration of a frame you consider abnormal, and first such frame will be captured.
* 0.3 is definitely something you should not see in a normal game.
* If you do not capture any frames with 0.3, try lowering it to 0.2 or 0.1.
* If it triggers too early, before the main slowdown happens, increase it to a higher value, e.g. 1.0.
 
== Scopes ==
{| class="wikitable sortable"
|-
! Technical Name !! Descriptive Name !! Description
|-
| Main
|
|
|-
| total
|
|
|-
| fsPHa
|
|
|-
| winMs
|
|
|-
| dlcSim
|
|
|-
| steamCbk
|
|
|-
| input
|
|
|-
| wSimu
|
|
|-
| docSim
|
|
|-
| wSimDisp
|
|
|-
| MFDManager
|
|
|-
| wDisp
|
|
|-
| EventPrcs
|
|
|-
| gsEva
|
|
|-
| gbFrm
|
|
|-
| memLo
|
|
|-
| siScr
|
|
|-
| scrVM
|
|
|-
| wsSet
|
|
|-
| sLand
|
|
|-
|-
| <tt>passwordAdmin = "xyzxyz";</tt> || <tt>""</tt> || Password to protect admin access. || -
| simSW
|  
|  
|-
|-
| <tt>password = "xyz";</tt> || <tt>""</tt> || Password required to connect to server. || -
| cLWObj
|  
|  
|-
|-
| <tt>serverCommandPassword = "xyzxyz";</tt> || <tt>""</tt> || Password required by alternate syntax of [[serverCommand]] server-side scripting. || -
| oTemp
|  
|  
|-
|-
| <tt>hostname="My Server";</tt> || <tt>UNKNOWN</tt> || Servername visible in the game browser. || -
| FPres
|  
|  
|-
|-
| <tt>maxPlayers = 10;</tt> || <tt>64</tt>(DS) || The maximum number of players that can connect to server. The final number will be lesser between number given here and number of mission slots. || -
| waitSnd
|  
|  
|-
|-
| <tt>motd[]= {"Welcome to my server.", "Hosted in the net."};</tt> || <tt>{}</tt> || Two lines welcome message. Comma is the 'new line' separator. || -
| job
|  
|  
|-
|-
| <tt>admins[] = {"<UID>"};</tt> || <tt>{}</tt> || Whitelisted clients can use #login w/o password. See [[server.cfg#Logged_In_Admin|Logged In Admin]] || {{GVI|arma3|1.70}}
| sound
|  
|  
|-
|-
| <tt>headlessClients[] = {"<IP>"};</tt> || <tt>{}</tt> || Headless clients IPs. Multiple connections and addresses are allowed in the case of more than one Headless Client. See [[Arma 3: Headless Client]] || -
| ssAdv
|  
|  
|-
|-
| <tt>localClient[] = {"<IP>"};</tt> || <tt>{}</tt> || Indicates clients with ''unlimited'' bandwidth and ''nearly no latency''. See [[Arma 3: Headless Client]] || -
| snCmt
|  
|  
|-
|-
! colspan="4" | Server Behaviour
| play
|
|
|-
|-
| <tt>voteThreshold = 0.33;</tt> || <tt>UNKNOWN</tt> || Percentage of votes needed to confirm a vote. <tt>33%</tt> in this example. || -
| ARTCpl
|  
|  
|-
|-
| <tt>voteMissionPlayers = 3;</tt> || <tt>UNKNOWN</tt> || Start mission-voting when ''X'' numberOfPlayers connect. || -
| rendr
|  
|  
|-
|-
| <tt>allowedVoteCmds[] = { {"kick", false, false, 0.75} };</tt> || <tt>{}</tt> || See [[Arma 3: Mission voting]] || -
| drwVi
|  
|  
|-
|-
| <tt>allowedVotedAdminCmds[] = { { "mission", true, true } }; || <tt>{}</tt> || </tt> See [[Arma 3: Mission voting]] || -
| txHLi
|  
|  
|-
|-
| <tt>kickduplicate = 1;</tt> || <tt>UNKNOWN</tt> || Do not allow duplicate ''game IDs''. Second player with an existing ID will be kicked automatically. <tt>1</tt> means active, <tt>0</tt> disabled. || -
| txPMM
|  
|  
|-
|-
| <tt>loopback = true;</tt> || <tt>false</tt> || Adding this option will force server into LAN mode. This will allow multiple local instances of the game to connect to the server for testing purposes. At the same time it will prevent all non-local instances from connecting. || -
| dsr2t
|  
|  
|-
|-
| <tt>upnp = true;</tt> || <tt>false</tt> || Automatically creates port mapping on UPNP/IGD enabled router. This option allows you to create a server behind NAT (your router must have public IP and support UPNP/IGD protocol). Read more [https://en.wikipedia.org/wiki/Internet_Gateway_Device_Protocol Internet Gateway Device (IGD) Standardized Device Control Protocol]. {{Feature|warning|When enabled then this setting may delay server start-up by 600s (standard UDP timeout of 10 minutes) if blocked on firewall or bad routing etc. Thus in such case is recommended to disable it.}} || -
| wPrep
|  
|  
|-
|-
| <tt>allowedFilePatching = 0;</tt> || <tt>0</tt> || Prevent or allow file patching for the clients (including the HC)
| dPr
* 0 is no clients
|  
* 1 is Headless Clients only
|  
* 2 is all clients
| {{GVI|arma3|1.50}}
|-
|-
| <tt>allowedLoadFileExtensions[] = {"sqf","txt"};</tt> || <tt>UNKNOWN</tt> || Only allow files with listed extensions to be loaded via [[loadFile]] command. Not listing any extension means everything is allowed. Defining the setting as empty arrays means nothing is allowed. || {{GVI|arma3|1.20}}
| fmiRun
|  
|  
|-
|-
| <tt>allowedPreprocessFileExtensions[] = {"sqf","sqs"};</tt> || <tt>UNKNOWN</tt> || Only allow files with listed extensions to be loaded via [[preprocessFile]] / [[preprocessFileLineNumbers]] commands. Not listing any extension means everything is allowed. Defining the setting as empty arrays means nothing is allowed. || {{GVI|arma3|1.20}}
| fmiWait
|  
|  
|-
|-
| <tt>allowedHTMLLoadExtensions[] = {"htm","html"};</tt> || <tt>UNKNOWN</tt> || Only allow files and URLs with listed extensions to be loaded via [[htmlLoad]] command. Not listing any extension means everything is allowed. Defining the setting as empty arrays means nothing is allowed. || {{GVI|arma3|1.28}}
| fmiMDrw
|  
|  
|-
|-
| <tt>allowedHTMLLoadURIs[] = {"http://arma3.com"};</tt> || <tt>UNKNOWN</tt> || Only allow files from listed URIs and URLs to be loaded via [[htmlLoad]] command. Comment out if not used. Can use += to add to the existing list. Not listing any extension means everything is allowed. Defining the setting as empty arrays means nothing is allowed. || -
| fmiSIns
|  
|  
|-
|-
| <tt>filePatchingExceptions[] = {"123456789","987654321"};</tt> || <tt>{}</tt> || Whitelisted Steam IDs allowed filePatching || -
| wPrepFtr
|  
|  
|-
|-
| <tt>disconnectTimeout = 5;</tt> || <tt>90</tt> || Server wait time before disconnecting client after loss of active traffic connection, range 5 to 90 seconds. || {{GVI|arma3|1.56}}
| clPrp
|  
|  
|-
|-
| <tt>maxdesync = 150;</tt> || <tt>UNKNOWN</tt> || Max desync value until server kick the user || {{GVI|arma3|1.56}}
| oPrep
|  
|  
|-
|-
| <tt>maxping= 200;</tt> || <tt>UNKNOWN</tt> || Max ping value until server kick the user || {{GVI|arma3|1.56}}
| sceAC
|  
|  
|-
|-
| <tt>maxpacketloss= 50;</tt> || <tt>UNKNOWN</tt> || Max packetloss value until server kick the user || {{GVI|arma3|1.56}}
| oSplt
|  
|  
|-
|-
| <tt>kickClientsOnSlowNetwork[] = { 0, 0, 0, 0 };</tt> || <tt>UNKNOWN</tt> || Defines if <tt>{<MaxPing>, <MaxPacketLoss>, <MaxDesync>, <DisconnectTimeout>}</tt> will be logged (0) or kicked (1) || {{GVI|arma3|1.56}}
| sceACTA
|  
|  
|-
|-
| <tt>enablePlayerDiag = 1</tt> || <tt>0</tt> || Logs players' bandwidth and desync info every 60 seconds, as well as "network message is pending" owner identity. || -
| sceACPrx
|  
|  
|-
|-
| <tt>callExtReportLimit = 1000;</tt> || <tt>1000</tt> || If server initiated [[callExtension]] takes longer than specified limit in milliseconds, the warning will be logged into server <tt>.rpt</tt> file as well as reflected in the extension return result. || -
| lodUL
|  
|  
|-
|-
| <tt>kickTimeout[] = { {0, -1},{1, 180},{2, 180},{3, 180} };</tt> || <tt>UNKNOWN</tt> ||
| PrxObj
<tt>kickTimeout[] = { {kickID, timeout}, ... };</tt><br>
|  
kickID (type to determine from where the kick originated e.g. admin or votekick etc.)
|  
* 0 - manual kick (vote kick, admin kick, bruteforce detection etc.)
* 1 - connectivity kick (ping, timeout, packetloss, desync)
* 2 - BattlEye kick
* 3 - harmless kick (wrong addons, steam timeout or checks, signatures, content etc.)<br>
timeout = in seconds how long until kicked player can return
* >0 seconds
* -1 until missionEnd
* -2 until serverRestart<br>
| {{GVI|arma3|1.90}} Profil. Branch
|-
|-
| <tt>votingTimeOut = 60;</tt> || <tt>60</tt> || Voting timeout || -
| manAn
|  
|  
|-
|-
| <tt>votingTimeOut[] = {60, 90};</tt>  || <tt>{60, 90}</tt> || Voteing timeout {ready, notReady} || {{GVI|arma3|1.90}} Profil. Branch
| ppdOT
|  
|  
|-
|-
| <tt>roleTimeOut = 90;</tt> || <tt>90</tt> || Role seleciton timout || -
| flProx
|  
|  
|-
|-
| <tt>roleTimeOut[] = {90, 120};</tt> || <tt>{90, 120}</tt> || Role selection timeout <tt>{ready, notReady}</tt> || {{GVI|arma3|1.90}} Profil. Branch
| PrxObjTransport
|  
|  
|-
|-
| <tt>briefingTimeOut = 60;</tt> || <tt>60</tt> || Briefing timeout || -
| oSoSL
|  
|  
|-
|-
| <tt>briefingTimeOut[] = {60, 90};</tt> || <tt>{90, 120}</tt> || Briefing timeout <tt>{ready, notReady}</tt> || {{GVI|arma3|1.90}} Profil. Branch
| oSoJE
|  
|  
|-
|-
| <tt>debriefingTimeOut = 45;</tt> || <tt>45</tt> || Briefing timeout || -
| oSoJE1
|  
|  
|-
|-
| <tt>debriefingTimeOut [] = {60, 60};</tt> || <tt>{90, 120}</tt> || Debriefing timeout <tt>{ready, notReady}</tt> || {{GVI|arma3|1.90}} Profil. Branch
| oSoJE2
|  
|  
|-
|-
| <tt>lobbyIdleTimeout = 300;</tt> || <tt>300</tt> || Lobby idle timeout
| oSo1OFOv
Independent of set ''lobbyIdleTimeout'' in the config file, it will be at least<br>
|  
<tt>MAX(votingTimeout, lobbyTimeout, briefingTimeout, debriefingTimeout) + 5 seconds</tt>
|  
by default, this makes it 300 seconds of time for people in lobby and 95 in roleTimeout or briefing screen<br>
| {{GVI|arma3|1.90}} Profil. Branch
|-
|-
| <tt>missionsToServerRestart = 8;</tt> || <tt>UNKNOWN</tt> || Number of times missionEnd happens before server initiate process restart (uses actual session startup command-line parameters, not possible to combine with `missionsToShutdown` ) || -
| oSo1ON
|  
|  
|-
|-
| <tt>missionsToShutdown = 8;</tt> || <tt>UNKNOWN</tt> || Number of times missionEnd happens before server initiate process shutdown (has same behavior as setting named `missionsToHardRestart`) || -
| sceCLsHSH
|  
|  
|-
|-
| <tt>autoSelectMission = true;</tt> || <tt>false</tt> || When enabled, the server auto-starts next mission in mission cycle and waits for players in the role selection. This allows full mission information in server browser and then results in proper filtering of the servers. This is lesser-variant (trimmed) of server startup command-line parameter <tt>-autoInit</tt>. Might collide with campaign linked missions / need mission cycle etc. || -
| prpAMCt
|  
|  
|-
|-
| <tt>randomMissionOrder = true;</tt> || <tt>UNKNOWN</tt> || When enabled, the server random start / next selection with one of missions from mission rotation list. ( setting goes outside(before) Mission class {}; ) || -
| oSoJEw
|  
|  
|-
|-
| <tt>disableChannels[] = { {0,false,true} };</tt> || <tt>{}</tt> ||
| pDrwFNP
<tt>disableChannels[] = { {channelID, text, voice}, ... }>;</tt><br>
|  
* ''ChannelID'' : [[Number]] - use single digit of (0 to 6) to define channelID. Default: No restriction to any channels, with text/von chat set to false.<br>
|  
* ''text'' : [[Boolean]] - use [[true]] to disable usage of text-chat for defined channelID. Default: '''[[false]]'''<br>
* ''voice'' : [[Boolean]] - use [[true]] to disable usage of voice-chat (VON) for defined channelID. Default: '''[[false]]'''<br>
List of channels ID:
<div style="columns: 3">
* 0 = Global
* 1 = Side
* 2 = Command
* 3 = Group
* 4 = Vehicle
* 5 = Direct
* 6 = System
</div>
{{Feature|Informative|Missions which use [[Description.ext#disableChannels|Description.ext#disableChannels]] will override any setting of ''disableChannels[]'' in the '''server.cfg'''.}}
| -
|-
|-
! colspan="4" | Other Options
| oSoSLu
|
|
|-
|-
| <tt>verifySignatures = 2;</tt> || <tt>2</tt>|| Enables or disables the [[ArmA: Addon Signatures|signature verification]] for addons.
| lPGCl
* Verification disabled = <tt>0</tt>.
|  
*<tt>1</tt> Will default back to <tt>2</tt>
|  
| -
|-
|-
| <tt>drawingInMap = false;</tt> || <tt>true</tt> || Enables or disables the ability to place markers and draw lines in map. || {{GVI|arma3|1.64}}
| pdDrw
|  
|  
|-
|-
| <tt>disableVoN = 1;</tt> || <tt>0</tt> || Enables or disables the '''''V'''oice '''o'''ver '''N'''et''. || -
| lDGnd
|  
|  
|-
|-
| <tt>vonCodecQuality = 10;</tt> || <tt>3</tt> || Defines ''VoN'' codec quality. Value range is from <tt>1</tt> to <tt>20</tt>.
| lGSMM
* Since 1.62 supports range <tt>1-20</tt>
|  
* Since 1.64 will support range <tt>1-30</tt>
|  
* 8kHz is <tt>0-10</tt>, 16kHz is <tt>11-20</tt>, for <tt>21-30</tt> it is 32kHz for SPEEX codec and 48kHz for OPUS codec.
| -
|-
|-
| <tt>vonCodec = 1;</tt> || <tt>0</tt> || Defines ''VoN'' codec type. Value range is from <tt>0</tt> to <tt>1</tt>.
| recCB
* Since Arma 3 update 1.58 supports value <tt>1</tt>
|  
* Value <tt>0</tt> uses older [https://en.wikipedia.org/wiki/Speex SPEEX codec], while <tt>1</tt> switches to new IETF standard [https://en.wikipedia.org/wiki/Opus_(audio_format) OPUS codec].
|  
| -
|-
|-
| <tt>skipLobby = false;</tt> || <tt>false</tt> || If true, joining player will skip role selection. This is only used if no Mission, Campaign or Config setting <tt>skipLobby</tt> is defined (See [[Description.ext#skipLobby]]). || -
| mtPmj
|  
|  
|-
|-
| <tt>logFile = "server_console.log";</tt> || <tt>UNKNOWN</tt> || Enables output of dedicated server console into ''textfile''. Default location of log is same as ''crash dumps'' and other logs. (Local settings) Note that this does not change the location of the "''net.log''" file, which you enable with the <tt>-netlog</tt> command line option. || -
| cuDrw
|  
|  
|-
|-
| <tt>doubleIdDetected = "command";</tt> || <tt>""</tt> || rowspan="8" align="center" | See [[ArmA: Server Side Scripting|Server Side Scripting]]
| prepT
|  
|  
|-
|-
| <tt>onUserConnected = "command";</tt> || <tt>""</tt> || -
| drwCB
|  
|  
|-
|-
| <tt>onUserDisconnected = "command";</tt> || <tt>""</tt> || -
| oPasD
|  
|  
|-
|-
| <tt>onHackedData = "command";</tt> || <tt>""</tt> || -
| o1Drw
|  
|  
|-
|-
| <tt>onDifferentData = "command";</tt> || <tt>""</tt> || -
| lckDnBf
|  
|  
|-
|-
| <tt>onUnsignedData = "command";</tt> || <tt>""</tt> || -
| prpTx
|  
|  
|-
|-
| <tt>onUserKicked = "command";</tt> || <tt>""</tt> || -
| inst
|  
|  
|-
|-
| <tt>regularCheck = "command";</tt> || <tt>""</tt> || -
| stpSctnTL
|  
|  
|-
|-
| <tt>BattlEye = 1;</tt> || <tt>1</tt> || Enables or disables the [[BattlEye]] anti-cheat engine. Requires installed [[BattlEye]] on server and clients joining the server || -
| o1ShV
|  
|  
|-
|-
| <tt>timeStampFormat = "none";</tt> || <tt>""</tt> || Set the timestamp format used on each report line in server-side [[Crash Files|RPT file]]. Possible values are "none", "short", "full". || -
| scSVI
|  
|  
|-
|-
| <tt>forceRotorLibSimulation = 0;</tt> || <tt>0</tt> || Enforces the Advanced Flight Model on the server. <tt>0</tt> (up to the player). <tt>1</tt> - forced AFM, <tt>2</tt> - forced SFM. || ?
| oPas3
|  
|  
|-
|-
| <tt>persistent = 1;</tt> || <tt>0</tt> || Mission keeps running when all clients disconnect. Enabling the persistence option will make missions that have either ''base'' or ''instant'' respawn keep on running after all players have disconnected. The other respawn types will not make a mission persistent. The kind of respawn a certain mission uses is set in its [[Description.ext]]. || -
| sssmC
|  
|  
|-
|-
| <tt>requiredBuild = xxxxx;</tt> || <tt>UNKNOWN</tt> || Minimum required client version. Clients with version lower than <tt>requiredBuild</tt> will not be able to connect. If <tt>requiredBuild</tt> is set to a large number, like <tt>requiredBuild = 999999999;</tt> for example, it will automatically be lowered to the current server version. || -
| sbDrw
|  
|  
|-
|-
| <tt>statisticsEnabled = 1;</tt> || <tt>1</tt> || Allows to opt-out of [[Arma 3: Analytics|Arma 3 analytics]] for the server by using 0 || {{GVI|arma3|1.56}}
| aniMt
|  
|  
|-
|-
| <tt>forcedDifficulty = "regular";</tt> || <tt>""</tt> || Enforces the selected difficulty on the server. <tt>'''forcedDifficulty''' = "<difficultyClass>";</tt>
| ppSSSM
* If Recruit, Regular or Veteran is passed as the parameter, the particular difficulty options will be taken from data config, from the class CfgDifficultyPresets.
|  
* If Custom will be passed as the parameter, the particular flags will be taken from CustomDifficulty class from server's profile (only Custom is saved to the profile).
|  
* If mission cycle is defined in the [[server.cfg]], the difficulty set in the mission cycle overrides the difficulty set by '''forcedDifficulty''' parameter.
| {{GVI|arma3|1.56}}
|-
|-
| <tt>missionWhitelist[] = {"intro.altis"};</tt> || <tt>{}</tt> || Limit the available missions for the admin for the mission change. See [[Arma 3: MP Mission Names]] for a full list. || {{GVI|arma3|1.56}}
| drwROM
|  
|  
|-
|-
| <tt>steamProtocolMaxDataSize = 1024;</tt> || <tt>UNKNOWN</tt> || Limit for maximum Steam Query packet length. Increasing this value is dangerous as it can cause {{arma3}} server to send UDP packets of a size larger than the MTU. This will cause UDP packets to be fragmented which is not supported by some older routers. But increasing this will fix the modlist length limit in [[Arma 3: Launcher]]. || {{GVI|arma3|2.00}}
| drwIn
|  
|  
|-
|-
|
| wDraw
<syntaxhighlight lang="cpp">
|
class AdvancedOptions
|
{
|-
    LogObjectNotFound = true; // Logging enabled
| lDPGT
    SkipDescriptionParsing = false; // Parse description.ext
|
    ignoreMissionLoadErrors = false; // Do not ingore errors
|
};</syntaxhighlight>
|-
| <tt>true/false/false</tt>
| oSDrw
|
|
{{GVI|arma3|2.02}}
|
* LogObjectNotFound - [[false|False]] to skip logging "Server: Object not found" messages
|-
* SkipDescriptionParsing - [[true|True]] to skip parsing of description.ext/mission.sqm. Will show pbo filename instead of configured missionName. OverviewText and such won't work, but loading the mission list is a lot faster when you have many missions
| oPasO
{{GVI|arma3|2.04}}
|
* ignoreMissionLoadErrors - When server log gets filled with  too many logs entries the mission loading will be aborted and jump bad to mission selection, this forces the server to continue loading mission {{Clarify}}
|
| {{GVI|arma3|2.02}}{{GVI|arma3|2.04}}
|-
| lDSky
|
|
|-
| swRdr
|
|
|-
| ppSWDD
|
|
|-
| swRdGeom
|
|
|-
| swRdGeomVB
|
|
|-
| swFillV
|
|
|-
| oPasA
|
|
|-
| ppShrpn
|
|
|-
| lDWat
|
|
|-
| oPas2
|
|
|-
| o2Drw
|
|
|-
| oPas5
|
|
|-
| o5Drw
|
|
|-
| EDraw3D
|
|
|-
| MEventPrcs
|
|
|-
| cLGSY
|
|
|-
| stpAll
|
|
|-
| stpCB
|
|
|-
| stpTxtCS
|
|
|-
| stpUAVsCS
|
|
|-
| ppHDRCL
|
|
|-
| ppGSB
|
|
|-
| ppDOF
|
|
|-
| ppGlwNw
|
|
|-
| ppGLu
|
|
|-
| stpCBUpd
|
|
|-
| ppQWt
|
|
|-
| ppCMAA
|
|
|-
| hudDr
|
|
|-
| 3DEN_UI_OnDraw
|
|
|-
| 3DEN_PrepareDraw
|
|
|-
| clObL
|
|
|-
| 3DEN_Drawing
|
|
|-
| stpTxtGS
|
|
|-
| txt2D
|
|
|-
| mapDr
|
|
|-
| mapSeaAndNormal
|
|
|-
| mapPM
|
|
|-
| lndPM
|
|
|-
| MapObjectsPrepTask
|
|
|-
| mapSeaAndNormalDraw
|
|
|-
| mapCntDraw
|
|
|-
| mapObjectsDraw
|
|
|-
| mapForestShape
|
|
|-
| mapGrid
|
|
|-
| drwFn
|
|
|-
| dtTot
|
|
|-
| wFram
|
|
|-
| 3dSwp
|
|
|-
| preLd
|
|
|-
| preLV
|
|
|-
| actObjPrld
|
|
|-
| hashChk
|
|
|-
| sSim
|
|
|-
| enfWorkShort
|  
|  
|-
| updAttPos
|
|  
|-
| oSo1AN
|  
|  
|-
| prpAMCf
|  
|  
|-
| prpAMCSlt
|
|
|-
| prpSDM
|
|
|-
| locL
|
|
|-
| mapSeaAndNormalWork
|
|
|-
| mapObjectsPrepWork
|
|
|-
| drwIdxPrm
|
|
|-
| oSo3
|
|
|-
| lsCVB
|
|
|-
| oSo5
|
|
|-
| oSo2CL
|
|
|-
| oSo1AF
|
|
|-
| Visualize
|
|
|-
| visul
|
|
|-
| txMLo
|
|
|-
| oSo2Srt
|
|
|-
| oSoSdw
|
|
|-
| prpAMCbsi
|
|
|-
| prpAMCp
|
|
|-
| Render
|
|
|-
| bgD3D
|
|  
|-
|-
| <tt>armaUnitsTimeout = 30;</tt> || <tt>30</tt> || Defines how long the player will be stuck connecting and wait for [https://units.arma3.com/ armaUnits data]. Player will be notified if timeout elapsed and no units data was received || {{GVI|arma3|2.06}}
| stpTxtVS
|  
|  
|-
|-
| ppHBAOPlus
|
|
|}
|}


= Server Administration =
<sqf>
If you are not using BattlEye RCon, there could only be 1 server admin at any given time. There are two ways of becoming admin, through a vote or through login with authenticated credentials.
private _ctrlTV = ctrlparent (_this select 0) displayCtrl 101;
 
== Voted In Admin ==
It is possible to become a server administrator through player voting process. Such admin has less abilities than logged in admin.<br>
For example, voted in admin would be able to kick a player, but only logged in admin would be able to ban a player.<br>
For more information on voting and voting configuration see page [[Arma_3:_Mission_voting|'''Server Voting''']].
 
== Logged In Admin ==
To log in as admin, one is required to type in<tt>#login</tt> command followed by server password, which matches password defined in '''passwordAdmin''' param.<br>
Since Arma2OA it is possible to add one or several user ids [[getPlayerUID|UIDs]] into '''admins[]''' server config parameter, which would allow listed users to log in as admin by simply typing <tt>#login</tt> without a password.<br>
This presents several advantages for managing the servers. The server owner can have multiple admins selected from the community and doesn't have to provide each one with server admin password.<br>
The adding and removing of UIDs is done on the server side which makes it easy to add and to remove admins if necessary. On the server, admins are handled on first come first served basis.<br>
Here are the rules:<br>
* If there is already a logged in admin on the server, the new admin will not be able to log in until previously logged in admin logs out
* If there is a voted in admin on the server, the logged in admin will override voted in admin and take admin role
* There is no difference between logged in admin that used admin password or logged in admin that was whitelisted with '''admins[]''' param
<br>
The logged in and voted in admins have different set of '''[[Multiplayer Server Commands]]''' available to them. See '''[[serverCommandAvailable]]''' for more information.
 
= Server Security =
Several of these settings directly contribute to the security of the server and have been highlighted as important, particularly for running public - no password - servers.
 
;The most updated ones that give a good protection (and are, ''de facto'', the standard for public servers) are:
<syntaxhighlight lang=cpp>
battlEye = 1;
verifySignatures = 2;
allowedFilePatching = 0;
allowedLoadFileExtensions[] = {"hpp","sqs","sqf","fsm","cpp","paa","txt","xml","inc","ext","sqm","ods","fxy","lip","csv","kb","bik","bikb","html","htm","biedi"};
allowedPreprocessFileExtensions[] = {"hpp","sqs","sqf","fsm","cpp","paa","txt","xml","inc","ext","sqm","ods","fxy","lip","csv","kb","bik","bikb","html","htm","biedi"};
allowedHTMLLoadExtensions[] = {"htm","html","xml","txt"};
//allowedHTMLLoadURIs[] = {};
passwordAdmin = "xyzxyz123";
serverCommandPassword = "xyzxyz456";
</syntaxhighlight>
 
== Notes ==
The properties allowedLoad*/allowedPreprocess*/allowedHTML* are server.cfg settings with array list of extensions for server-side use only. The above listed examples are for basic game multiplayer modes. Server admins may attempt to make it stricter for their servers. However, if too strict then server's log file will contain warning entries about unable read.
: With the exception of allowedHTMLLoadURIs those arrays covers both files inside and outside PBOs so don't change the above defaults w/o testing first as there's a chance you'll break the game.
 
* To read [[loadFile]] , [[preprocessFile]] , [[preprocessFileLineNumbers]] and to remember, those works on files only-within {{arma3}} server directory and its sub-directories!
* Refer to [[ArmA: Addon Signatures]] for current best practices in server mod signing and the use of key signature files.<br>
* To further increase security of your servers remember [[BattlEye]] has ability to utilize server-side (including preventing remote execution) and client-side script check filters.
** These BattlEye filters needs to be written specifically for each mission and mod as the scripting differs in each of them.<br>
 
== Safe Folder Structure ==
Engine supports absolute outside Arma 3 server folder for command-line parameters <tt>-servermod=, -mod=</tt> and same for profile directories and config locations.
This puts those out of reach by various load script command features which are limited only within {{arma3}} folder and it is sub-directories for security reason.
thus e.g. safe folder-structure looks like:
* <tt>\arma3server\</tt>
* <tt>\arma3server\@publicmods\</tt>
* <tt>\arma3server_servermods_secrethash\</tt>
* <tt>\arma3server_profiles_and_configs_secrethash\</tt>
 
Note that [[callExtension]]s are loaded only from {{arma3}} server root / sub-folders
 
= Example Configuration File =
<spoiler><syntaxhighlight lang="cpp">
// server.cfg
 
// GLOBAL SETTINGS
hostname = "Fun and Test Server"; // The name of the server that shall be displayed in the public server list
password = ""; // Password for joining, eg connecting to the server
passwordAdmin = "xyz"; // Password to become server admin. When you're in Arma MP and connected to the server, type '#login xyz'
serverCommandPassword = "xyzxyz"; // Password required by alternate syntax of [[serverCommand]] server-side scripting.
 
logFile = "server_console.log"; // Where the logfile should go and what it should be called
 
// WELCOME MESSAGE ("message of the day")
// It can be several lines, separated by comma
// Empty messages "" will not be displayed at all but are only for increasing the interval
motd[] = {
"", "",
"Two empty lines above for increasing interval",
"Welcome to our server",
"", "",
"We are looking for fun - Join us Now !",
"http://www.example.com",
"One more empty line below for increasing interval",
""
};
motdInterval = 5; // Time interval (in seconds) between each message
 
 
// JOINING RULES
maxPlayers = 64; // Maximum amount of players. Civilians and watchers, beholder, bystanders and so on also count as player.
kickDuplicate = 1; // Each ArmA version has its own ID. If kickDuplicate is set to 1, a player will be kicked when he joins a server where another player with the same ID is playing.
verifySignatures = 2; // Verifies .pbos against .bisign files. Valid values 0 (disabled), 1 (prefer v2 sigs but accept v1 too) and 2 (only v2 sigs are allowed).
equalModRequired = 0; // Outdated. If set to 1, player has to use exactly the same -mod= startup parameter as the server.
allowedFilePatching = 0; // Allow or prevent client using -filePatching to join the server. 0, is disallow, 1 is allow HC, 2 is allow all clients (since Arma 3 v1.50)
filePatchingExceptions[] = {"123456789","987654321"}; // Whitelisted Steam IDs allowed to join with -filePatching enabled
//requiredBuild = 12345; // Require clients joining to have at least build 12345 of game, preventing obsolete clients to connect


private _export = "{| class=""wikitable sortable"""  + endl + "|-" + endl;
_export = _export + "! Technical Name !! Descriptive Name !! Description";


// VOTING
private _fnc_logChilden =
voteMissionPlayers = 1; // Tells the server how many people must connect so that it displays the mission selection screen.
voteThreshold = 0.33; // 33% or more players need to vote for something, for example an admin or a new map, to become effective
 
 
// INGAME SETTINGS
disableVoN = 0; // If set to 1, Voice over Net will not be available
vonCodec = 1; // If set to 1 then it uses IETF standard OPUS codec, if to 0 then it uses SPEEX codec (since Arma 3 update 1.58+)
vonCodecQuality = 30; // since 1.62.95417 supports range 1-20 //since 1.63.x will supports range 1-30 //8kHz is 0-10, 16kHz is 11-20, 32kHz(48kHz) is 21-30
persistent = 1; // If 1, missions still run on even after the last player disconnected.
timeStampFormat = "short"; // Set the timestamp format used on each report line in server-side RPT file. Possible values are "none" (default),"short","full".
BattlEye = 1; // Server to use BattlEye system
allowedLoadFileExtensions[] = {"hpp","sqs","sqf","fsm","cpp","paa","txt","xml","inc","ext","sqm","ods","fxy","lip","csv","kb","bik","bikb","html","htm","biedi"}; //only allow files with those extensions to be loaded via loadFile command (since Arma 3 build 1.19.124216)
allowedPreprocessFileExtensions[] = {"hpp","sqs","sqf","fsm","cpp","paa","txt","xml","inc","ext","sqm","ods","fxy","lip","csv","kb","bik","bikb","html","htm","biedi"}; //only allow files with those extensions to be loaded via preprocessFile/preprocessFileLineNumber commands (since Arma 3 build 1.19.124323)
allowedHTMLLoadExtensions[] = {"htm","html","xml","txt"}; //only allow files with those extensions to be loaded via HTMLLoad command (since Arma 3 build 1.27.126715)
//allowedHTMLLoadURIs[] = {}; // Leave commented to let missions/campaigns/addons decide what URIs are supported. Uncomment to define server-level restrictions for URIs
 
// TIMEOUTS
disconnectTimeout = 5; // Time to wait before disconnecting a user which temporarly lost connection. Range is 5 to 90 seconds.
maxDesync = 150; // Max desync value until server kick the user
maxPing= 200; // Max ping value until server kick the user
maxPacketLoss= 50; // Max packetloss value until server kick the user
kickClientsOnSlowNetwork[] = { 0, 0, 0, 0 }; // Defines if {<MaxPing>, <MaxPacketLoss>, <MaxDesync>, <DisconnectTimeout>} will be logged (0) or kicked (1)
kickTimeout[] = { {0, -1}, {1, 180}, {2, 180}, {3, 180} };
votingTimeOut[] = {60, 90}; // Kicks users from server if they spend too much time in mission voting
roleTimeOut[] = {90, 120}; // Kicks users from server if they spend too much time in role selection
briefingTimeOut[] = {60, 90}; // Kicks users from server if they spend too much time in briefing (map) screen
debriefingTimeOut[] = {45, 60}; // Kicks users from server if they spend too much time in debriefing screen
lobbyIdleTimeout = 300; // The amount of time the server will wait before force-starting a mission without a logged-in Admin.
 
 
// SCRIPTING ISSUES
onUserConnected = "";
onUserDisconnected = "";
doubleIdDetected = "";
 
// SIGNATURE VERIFICATION
onUnsignedData = "kick (_this select 0)"; // unsigned data detected
onHackedData = "kick (_this select 0)"; // tampering of the signature detected
onDifferentData = ""; // data with a valid signature, but different version than the one present on server detected
 
 
// MISSIONS CYCLE (see below)
randomMissionOrder = true; // Randomly iterate through Missions list
autoSelectMission = true; // Server auto selects next mission in cycle
 
class Missions {}; // An empty Missions class means there will be no mission rotation
 
missionWhitelist[] = {}; // An empty whitelist means there is no restriction on what missions' available</syntaxhighlight></spoiler>
 
= Mission rotation =
One can set an automatic mission rotation. Without an admin, the server will automatically select a mission when at least one player is connected. Once the mission is done and if there are still players on the server, it will automatically switch to the next in the cycle.
 
Example:<br>
 
{{Feature | Informative | When difficulty is set to <tt>difficulty {{=}} "Custom";</tt> the server will look into <tt>USERNAME.Arma3Profile</tt> file for the definition of custom difficulty, which should look like this: [[server.armaprofile#Server_Difficulty_Example | click to see example]]}}
 
<syntaxhighlight lang="cpp">
class Missions
{
{
class TestMission01
    params ["_path"];
{
template = MP_Marksmen_01.Altis;
difficulty = "veteran";
class Params {};
};
class TestMission02
{
template = MP_End_Game_01.Altis;
difficulty = "veteran";
class Params {};
};
class TestMission03
{
template = MP_End_Game_02.Altis;
difficulty = "veteran";
class Params {};
};
class TestMission04
{
template = MP_End_Game_03.Altis;
difficulty = "veteran";
class Params {};
};
};
</syntaxhighlight>


= Arma 3: Apex - Mission collection =
    for "_i" from 0 to ((_ctrlTV tvCount _path) - 1) do
Mainly intended for MP campaigns. If the progress is defined in the MPMissions class, server administrator can simply add the whole campaign by adding ''campaign class'' into the ''server.cfg''. See the example below.
    {
        private _text = _ctrlTV tvText (_path + [_i]);
        _text = _text splitString " " select 0;


'''config.cpp:'''
        if !(_text in _export) then
<syntaxhighlight lang="cpp">
        {
class MPMissions
            _export = _export + endl + "|-" + endl + "| " + _text + endl + "| " + endl + "| ";
{
        };
class Apex
{
briefingName = $STR_A3_CoopCampaignName;


class EXP_m01
        if (_ctrlTV tvCount (_path + [_i]) > 0 ) then
{
        {
briefingName = $STR_A3_exp_m01_missionname;
            [_path + [_i]] call _fnc_logChilden;
directory = "a3\missions_f_exp\campaign\missions\exp_m01.tanoa";
        };
};
    };
 
class EXP_m02
{
briefingName = $STR_A3_exp_m02_missionname;
directory = "a3\missions_f_exp\campaign\missions\exp_m02.tanoa";
};
 
class EXP_m03
{
briefingName = $STR_A3_exp_m03_missionname;
directory = "a3\missions_f_exp\campaign\missions\exp_m03.tanoa";
};
};
};
};
</syntaxhighlight>


'''server.cfg:'''
[[]] call _fnc_logChilden;
<syntaxhighlight lang="cpp">


// MISSIONS CYCLE
copyToClipboard (_export + endl + "|}" + endl);
class Missions
</sqf>
{
class Apex{};
};
</syntaxhighlight>
 
Also the difficulty of the each mission can be overridden


<syntaxhighlight lang="cpp">
== See Also ==
class Missions
{
class Apex
{
class EXP_m01
{
difficulty = "veteran";
};
};
};
</syntaxhighlight>


= Additional details =
* [[Code Optimisation]]
For hosting server behind NAT or firewall, please ensure gameport and STEAMports are forwarded and open!<br>
* [[Mission Optimisation]]
Set the ICMP "echo reply" as allowed so the server is able return ping delay properly.<br>
It's recommended to enable the NAT traversal (so called "Edge traversal" in Windows Firewall) for '''arma3server.exe''', '''arma3.exe''' to better support clients/servers behind NAT.


= Overriding Mission Parameters =
On dedicated server unless you are an admin you cannot set mission options provided by mission maker via class Params. However as a server owner you can override default setting with your own. See [[Mission Parameters]] for more info


= See Also =
[[Category:Arma Scripting Tutorials]]
* [[basic.cfg|Server Basic Config file]]
* [[Arma 3: Startup Parameters]]
* [[Arma 3: Dedicated Server]]
* [[Arma 3: Headless Client]]
* [[Arma 3: Server Security]]
* [[Arma 3: Mission voting]]

Latest revision as of 18:23, 4 November 2024

If you have ever wondered why you scenario is running so badly, performance profiling is the way to find it out. It allows you to find bottlenecks and slow code by capturing a "slow" frame. The captured data can then be viewed and analysed.

Getting the correct Version

Profiling is enabled in the following Arma 3 versions

  • arma3profiling_x64.exe - Part of the Performance Profiling Build
  • arma3diag_x64.exe - Part of the Development Build

Read Arma_3: Steam Branches for a guide on how to access these branches.

It is recommended to use the Performance Profiling Build (arma3profiling_x64.exe) for performance profiling because:
  • Has tools that might not make it into development build
  • Has all the profiling related commands that arma3diag_x64.exe has
  • Its performance is closer to the default arma3_x64.exe

Frame Capturing

There are several commands that allow you to capture a frame.

In most cases you do not want to capture any or all frames, you just want to capture "slow" frames. A slow frame is a frame that takes longer than the average frame and slows down the game.

How to Use

  1. Run a mission
  2. Execute a scripted command diag_captureSlowFrame ["total", 0.3]; using any means (Debug Console, mission radio trigger...)
  3. Once a slow frame is detected, a window will open
  4. In the window you will be able to browse a lot of performance-related data, which can be interesting
  5. To export the gathered information for sharing with others:
    1. Select Main Thread (if not selected yet)
    2. Press the Copy button
    3. Open an external text editor
    4. Paste the text into a new file
    5. Save the file

Capture Frame UI

arma3-capture frame ui overview.png

  1. 🚧
    TODO: this must be updated.
  2. 🚧
    TODO: this must be updated.
  3. 🚧
    TODO: this must be updated.
  4. 🚧
    TODO: this must be updated.
  5. 🚧
    TODO: this must be updated.
  6. 🚧
    TODO: this must be updated.
  7. 🚧
    TODO: this must be updated.
  8. 🚧
    TODO: this must be updated.
  9. 🚧
    TODO: this must be updated.

External Viewer

diag_captureFrame sample output with custom subtree

Creating Your Own Subtree

When Profiling Per-Frame Eventhandlers (PFH), diag_captureFrame only shows one blob called siFEH that contains all PFH's so you can't see what part of that is caused by your PFH.
You can create your own subtree inside siFEH by wrapping your function call inside a isNil CODE statement like this:
Turn your old call which may look like this:

addMissionEventHandler ["EachFrame", { call myPFHFunction }];

Into something like this:

addMissionEventHandler ["EachFrame", { isNil { call myPFHFunction } // isNil creates the subtree }];

Now when you run diag_captureFrame inside of siPFH you will have a subtree called gsEva and behind that you can see the first line of code inside the isNil statement.
It will only show a part of the first line of that code so you should put something descriptive into the isNil statement.
You can use the same to create a subtree for any function you like. This will also work inside Scheduled (spawned) scripts.
But using this method to "subtree" a function with return values requires a little bit of trickery to get the return value out.


Notes

  • 0.3 is a time in second used to determine what duration of a frame you consider abnormal, and first such frame will be captured.
  • 0.3 is definitely something you should not see in a normal game.
  • If you do not capture any frames with 0.3, try lowering it to 0.2 or 0.1.
  • If it triggers too early, before the main slowdown happens, increase it to a higher value, e.g. 1.0.

Scopes

Technical Name Descriptive Name Description
Main
total
fsPHa
winMs
dlcSim
steamCbk
input
wSimu
docSim
wSimDisp
MFDManager
wDisp
EventPrcs
gsEva
gbFrm
memLo
siScr
scrVM
wsSet
sLand
simSW
cLWObj
oTemp
FPres
waitSnd
job
sound
ssAdv
snCmt
play
ARTCpl
rendr
drwVi
txHLi
txPMM
dsr2t
wPrep
dPr
fmiRun
fmiWait
fmiMDrw
fmiSIns
wPrepFtr
clPrp
oPrep
sceAC
oSplt
sceACTA
sceACPrx
lodUL
PrxObj
manAn
ppdOT
flProx
PrxObjTransport
oSoSL
oSoJE
oSoJE1
oSoJE2
oSo1OFOv
oSo1ON
sceCLsHSH
prpAMCt
oSoJEw
pDrwFNP
oSoSLu
lPGCl
pdDrw
lDGnd
lGSMM
recCB
mtPmj
cuDrw
prepT
drwCB
oPasD
o1Drw
lckDnBf
prpTx
inst
stpSctnTL
o1ShV
scSVI
oPas3
sssmC
sbDrw
aniMt
ppSSSM
drwROM
drwIn
wDraw
lDPGT
oSDrw
oPasO
lDSky
swRdr
ppSWDD
swRdGeom
swRdGeomVB
swFillV
oPasA
ppShrpn
lDWat
oPas2
o2Drw
oPas5
o5Drw
EDraw3D
MEventPrcs
cLGSY
stpAll
stpCB
stpTxtCS
stpUAVsCS
ppHDRCL
ppGSB
ppDOF
ppGlwNw
ppGLu
stpCBUpd
ppQWt
ppCMAA
hudDr
3DEN_UI_OnDraw
3DEN_PrepareDraw
clObL
3DEN_Drawing
stpTxtGS
txt2D
mapDr
mapSeaAndNormal
mapPM
lndPM
MapObjectsPrepTask
mapSeaAndNormalDraw
mapCntDraw
mapObjectsDraw
mapForestShape
mapGrid
drwFn
dtTot
wFram
3dSwp
preLd
preLV
actObjPrld
hashChk
sSim
enfWorkShort
updAttPos
oSo1AN
prpAMCf
prpAMCSlt
prpSDM
locL
mapSeaAndNormalWork
mapObjectsPrepWork
drwIdxPrm
oSo3
lsCVB
oSo5
oSo2CL
oSo1AF
Visualize
visul
txMLo
oSo2Srt
oSoSdw
prpAMCbsi
prpAMCp
Render
bgD3D
stpTxtVS
ppHBAOPlus

private _ctrlTV = ctrlparent (_this select 0) displayCtrl 101; private _export = "{| class=""wikitable sortable""" + endl + "|-" + endl; _export = _export + "! Technical Name !! Descriptive Name !! Description"; private _fnc_logChilden = { params ["_path"]; for "_i" from 0 to ((_ctrlTV tvCount _path) - 1) do { private _text = _ctrlTV tvText (_path + [_i]); _text = _text splitString " " select 0; if !(_text in _export) then { _export = _export + endl + "|-" + endl + "| " + _text + endl + "| " + endl + "| "; }; if (_ctrlTV tvCount (_path + [_i]) > 0 ) then { [_path + [_i]] call _fnc_logChilden; }; }; }; [[]] call _fnc_logChilden; copyToClipboard (_export + endl + "|}" + endl);

See Also