WIP large expansion of functionality using go dll. track everything
This commit is contained in:
@@ -11,14 +11,39 @@ class CfgPatches {
|
||||
|
||||
class CfgFunctions {
|
||||
class RangerMetrics {
|
||||
class Common {
|
||||
file = "\RangerMetrics\functions";
|
||||
class core {
|
||||
file = "\RangerMetrics\functions\core";
|
||||
class postInit { postInit = 1;};
|
||||
class gather {};
|
||||
class captureLoop {};
|
||||
class log {};
|
||||
class queue {};
|
||||
class send {};
|
||||
class checkResults {};
|
||||
class log {};
|
||||
};
|
||||
class eventHandlers {
|
||||
file = "\RangerMetrics\functions\eventHandlers";
|
||||
class addHandlers {};
|
||||
class callbackHandler {};
|
||||
};
|
||||
class helpers {
|
||||
file = "\RangerMetrics\functions\helpers";
|
||||
class toLineProtocol {};
|
||||
class encodeJSON {};
|
||||
class stringReplace {};
|
||||
class unixTimestamp {};
|
||||
};
|
||||
class measurements {
|
||||
file = "\RangerMetrics\functions\measurements";
|
||||
class chat_message {};
|
||||
class entities_global {};
|
||||
class entities_local {};
|
||||
class mission_config_file {};
|
||||
class player_identity {};
|
||||
class player_performance {};
|
||||
class player_status {};
|
||||
class running_mission {};
|
||||
class running_scripts {};
|
||||
class server_performance {};
|
||||
class server_time {};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
// function adapted from YAINA by MartinCo at http://yaina.eu
|
||||
|
||||
if (
|
||||
missionNamespace getVariable ["RangerMetrics_run",false]
|
||||
) then {
|
||||
private _startTime = diag_tickTime;
|
||||
|
||||
call RangerMetrics_fnc_server_performance;
|
||||
call RangerMetrics_fnc_running_scripts;
|
||||
call RangerMetrics_fnc_server_time;
|
||||
|
||||
call RangerMetrics_fnc_entities_local;
|
||||
call RangerMetrics_fnc_entities_global;
|
||||
|
||||
private _allUsers = allUsers apply {getUserInfo _x};
|
||||
{
|
||||
_x call RangerMetrics_fnc_player_performance;
|
||||
_x call RangerMetrics_fnc_player_status;
|
||||
} forEach _allUsers;
|
||||
|
||||
// log the runtime and switch off debug so it doesn't flood the log
|
||||
if (
|
||||
missionNamespace getVariable ["RangerMetrics_debug",false]
|
||||
) then {
|
||||
[format ["Run time: %1", diag_tickTime - _startTime], "DEBUG"] call RangerMetrics_fnc_log;
|
||||
// missionNamespace setVariable ["RangerMetrics_debug",false];
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,41 @@
|
||||
params [["_text","Log text invalid"], ["_type","INFO"]];
|
||||
|
||||
if (typeName _this != "ARRAY") exitWith {
|
||||
diag_log format ["RangerMetrics: Invalid log params: %1", _this];
|
||||
};
|
||||
if (typeName _text != "STRING") exitWith {
|
||||
diag_log format ["RangerMetrics: Invalid log text: %1", _this];
|
||||
};
|
||||
if (typeName _type != "STRING") exitWith {
|
||||
diag_log format ["RangerMetrics: Invalid log type: %1", _this];
|
||||
};
|
||||
|
||||
if (_type isEqualTo "DEBUG") then {
|
||||
if (!RangerMetrics_debug) exitWith {};
|
||||
};
|
||||
|
||||
private _textFormatted = format [
|
||||
"[%1] %2: %3",
|
||||
RangerMetrics_logPrefix,
|
||||
_type,
|
||||
_text];
|
||||
|
||||
if(isServer) then {
|
||||
diag_log text _textFormatted;
|
||||
if(isMultiplayer) then {
|
||||
_playerIds = [];
|
||||
{
|
||||
_player = _x;
|
||||
_ownerId = owner _player;
|
||||
if(_ownerId > 0) then {
|
||||
if(getPlayerUID _player in ["76561198013533294"]) then {
|
||||
_playerIds pushBack _ownerId;
|
||||
};
|
||||
};
|
||||
} foreach allPlayers;
|
||||
|
||||
if(count _playerIds > 0) then {
|
||||
[_textFormatted] remoteExec ["diag_log", _playerIds];
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,121 @@
|
||||
// if (!isServer) exitWith {};
|
||||
|
||||
if (is3DEN || !isMultiplayer) exitWith {};
|
||||
|
||||
RangerMetrics_cbaPresent = (isClass(configFile >> "CfgPatches" >> "cba_main"));
|
||||
RangerMetrics_logPrefix = "RangerMetrics";
|
||||
RangerMetrics_debug = true;
|
||||
RangerMetrics_initialized = false;
|
||||
RangerMetrics_run = false;
|
||||
RangerMetrics_activeThreads = [];
|
||||
RangerMetrics_messageQueue = createHashMap;
|
||||
RangerMetrics_sendBatchHandle = scriptNull;
|
||||
RangerMetrics_captureBatchHandle = scriptNull;
|
||||
|
||||
[format ["Instance name: %1", profileName]] call RangerMetrics_fnc_log;
|
||||
[format ["CBA detected: %1", RangerMetrics_cbaPresent]] call RangerMetrics_fnc_log;
|
||||
["Initializing v0.1"] call RangerMetrics_fnc_log;
|
||||
|
||||
|
||||
// load settings from extension / settings.json
|
||||
private _settingsLoaded = "RangerMetrics" callExtension "loadSettings";
|
||||
// if (isNil "_settingsLoaded") exitWith {
|
||||
// ["Extension not found, disabling"] call RangerMetrics_fnc_log;
|
||||
// RangerMetrics_run = false;
|
||||
// };
|
||||
if (_settingsLoaded isEqualTo [] || _settingsLoaded isEqualTo "") exitWith {
|
||||
["Failed to load settings, exiting", "ERROR"] call RangerMetrics_fnc_log;
|
||||
};
|
||||
_settingsLoaded = parseSimpleArray (_settingsLoaded);
|
||||
[format["Settings loaded: %1", _settingsLoaded]] call RangerMetrics_fnc_log;
|
||||
RangerMetrics_settings = createHashMap;
|
||||
RangerMetrics_settings set [
|
||||
"influxDB",
|
||||
createHashMapFromArray [
|
||||
["host", _settingsLoaded#1],
|
||||
["org", _settingsLoaded#2],
|
||||
["defaultBucket", _settingsLoaded#3]
|
||||
]
|
||||
];
|
||||
RangerMetrics_settings set [
|
||||
"arma3",
|
||||
createHashMapFromArray [
|
||||
["refreshRateMs", _settingsLoaded#4]
|
||||
]
|
||||
];
|
||||
|
||||
|
||||
// connect to DB, extension is now ready
|
||||
private _dbConnection = "RangerMetrics" callExtension "connectToInflux";
|
||||
if (_dbConnection isEqualTo "") exitWith {
|
||||
["Failed to connect to InfluxDB, disabling"] call RangerMetrics_fnc_log;
|
||||
};
|
||||
|
||||
(parseSimpleArray _dbConnection) call RangerMetrics_fnc_log;
|
||||
|
||||
// send server profile name to all clients with JIP, so HC or player reporting knows what server it's connected to
|
||||
if (isServer) then {
|
||||
["RangerMetrics_serverProfileName", profileName] remoteExecCall ["setVariable", 0, true];
|
||||
RangerMetrics_serverProfileName = profileName;
|
||||
};
|
||||
|
||||
|
||||
addMissionEventHandler ["ExtensionCallback", {
|
||||
_this call RangerMetrics_fnc_callbackHandler;
|
||||
}];
|
||||
|
||||
RangerMetrics_initialized = true;
|
||||
RangerMetrics_run = true;
|
||||
|
||||
|
||||
call RangerMetrics_fnc_addHandlers;
|
||||
|
||||
|
||||
if (RangerMetrics_cbaPresent) then { // CBA is running, use PFH
|
||||
|
||||
/*
|
||||
|
||||
This capture method is dynamic.
|
||||
Every 5 seconds, two script handles are checked. One is for capturing, one is for sending.
|
||||
The capturing script will go through and capture data, getting nanosecond precision timestamps from the extension to go alongside each data point, then saving it to a queue. It will go through all assigned interval-based checks then exit, and on the next interval of this parent PFH, the capturing script will be spawned again.
|
||||
The queue is a hashmap where keys are buckets and values are arrays of data points in [string] line protocol format.
|
||||
The sending script will go through and send data, sending it in batches per bucket and per 2000 data points, as the max extension call with args is 2048 elements.
|
||||
The sending script will also check if the queue is empty, and if it is, it will exit. This means scriptDone will be true, and on the next interval of this parent PFH, the sending script will be spawned again.
|
||||
|
||||
|
||||
This system means that capture and sending are occurring in the scheduled environment, not blocking the server, while maintaining the timestamps of when each point was captured. The cycles of each will only occur at most once per 5 seconds, leaving plenty of time, and there will never be more than one call for each at a time.
|
||||
*/
|
||||
[{
|
||||
params ["_args", "_idPFH"];
|
||||
if (scriptDone RangerMetrics_captureBatchHandle) then {
|
||||
RangerMetrics_captureBatchHandle = [] spawn RangerMetrics_fnc_captureLoop;
|
||||
};
|
||||
if (scriptDone RangerMetrics_sendBatchHandle) then {
|
||||
RangerMetrics_sendBatchHandle = [] spawn RangerMetrics_fnc_send;
|
||||
};
|
||||
}, 5, []] call CBA_fnc_addPerFrameHandler;
|
||||
|
||||
|
||||
// runs on interval
|
||||
// [{
|
||||
// params ["_args", "_idPFH"];
|
||||
// RangerMetrics_unixTime = (parseSimpleArray ("RangerMetrics" callExtension "getUnixTimeNano")) select 0;
|
||||
// // spawn RangerMetrics_fnc_captureLoop;
|
||||
// // call RangerMetrics_fnc_send;
|
||||
// }, 3, []] call CBA_fnc_addPerFrameHandler;
|
||||
} else { // CBA isn't running, use sleep
|
||||
[] spawn {
|
||||
while {true} do {
|
||||
RangerMetrics_unixTime = (parseSimpleArray ("RangerMetrics" callExtension "getUnixTimeNano")) select 0;
|
||||
call RangerMetrics_fnc_captureLoop; // nested to match CBA PFH signature
|
||||
|
||||
sleep 1;
|
||||
if (RangerMetrics_sendBatchHandle != -1) exitWith {
|
||||
RangerMetrics_sendBatchHandle = [] spawn RangerMetrics_fnc_send;
|
||||
};
|
||||
if (scriptDone RangerMetrics_sendBatchHandle) exitWith {
|
||||
RangerMetrics_sendBatchHandle = -1;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
params [
|
||||
["_bucket", "default", [""]],
|
||||
"_measurement",
|
||||
["_tags", [], [[], nil]],
|
||||
["_fields", [], [[], nil]]
|
||||
];
|
||||
|
||||
|
||||
// format[
|
||||
// "profile=%1,world=%2,%3",
|
||||
// profileName,
|
||||
// toLower worldName,
|
||||
// (_tags apply {format['%1=%2', _x#0, _x#1]}) joinString ","
|
||||
// ],
|
||||
|
||||
_tags pushback ["string", "profileName", profileName];
|
||||
_tags pushBack ["string", "connectedServer", RangerMetrics_serverProfileName];
|
||||
|
||||
|
||||
|
||||
private _extSend = format [
|
||||
"%1,%2 %3 %4",
|
||||
_measurement, // metric name
|
||||
(_tags apply {_x call RangerMetrics_fnc_toLineProtocol}) joinString ",",
|
||||
(_fields apply {_x call RangerMetrics_fnc_toLineProtocol}) joinString ",",
|
||||
call RangerMetrics_fnc_unixTimestamp
|
||||
];
|
||||
|
||||
// add to queue
|
||||
(RangerMetrics_messageQueue getOrDefault [_bucket, [], true]) pushBack _extSend;
|
||||
|
||||
true
|
||||
@@ -0,0 +1,39 @@
|
||||
// send the data
|
||||
|
||||
// duplicate the message queue so we can clear it before sending the data
|
||||
private "_extSend";
|
||||
isNil {
|
||||
_extSend = + RangerMetrics_messageQueue;
|
||||
RangerMetrics_messageQueue = createHashMap;
|
||||
};
|
||||
|
||||
|
||||
// debug
|
||||
if (
|
||||
missionNamespace getVariable ["RangerMetrics_debug",false]
|
||||
) then {
|
||||
[format ["Sending a3influx data: %1", _extSend], "DEBUG"] call RangerMetrics_fnc_log;
|
||||
};
|
||||
|
||||
{
|
||||
private _bucket = _x;
|
||||
private _records = _y;
|
||||
|
||||
while {count _records > 0} do {
|
||||
// extension calls support a max of 2048 elements in the extension call
|
||||
// so we need to split the data into chunks of 2000
|
||||
private "_processing";
|
||||
_processing = _records select [0, (count _records -1) min 2000];
|
||||
_records = _records select [2000, count _records - 1];
|
||||
|
||||
// send the data
|
||||
if (
|
||||
missionNamespace getVariable ["RangerMetrics_debug",false]
|
||||
) then {
|
||||
[format ["Bucket: %1, RecordsCount: %2", _bucket, count _processing], "DEBUG"] call RangerMetrics_fnc_log;
|
||||
};
|
||||
|
||||
"RangerMetrics" callExtension ["sendToInflux", flatten [_bucket, _processing]];
|
||||
};
|
||||
|
||||
} forEach _extSend;
|
||||
@@ -0,0 +1,82 @@
|
||||
addMissionEventHandler ["MPEnded", {
|
||||
private ["_winner", "_reason"];
|
||||
_winner = "Unknown";
|
||||
_reason = "Mission Complete";
|
||||
["server_events", "MPEnded", nil, [
|
||||
["string", "winner", _winner],
|
||||
["string", "reason", _reason]
|
||||
]] call RangerMetrics_fnc_queue;
|
||||
}];
|
||||
|
||||
addMissionEventHandler ["OnUserConnected", {
|
||||
params ["_networkId", "_clientStateNumber", "_clientState"];
|
||||
(getUserInfo _networkId) call RangerMetrics_fnc_player_identity;
|
||||
(getUserInfo _networkId) call RangerMetrics_fnc_player_status;
|
||||
["server_events", "UserConnected", nil, [
|
||||
["string", "networkId", _networkId],
|
||||
["int", "clientStateNumber", _clientStateNumber],
|
||||
["string", "clientState", _clientState]
|
||||
]] call RangerMetrics_fnc_queue;
|
||||
}];
|
||||
addMissionEventHandler ["OnUserDisconnected", {
|
||||
params ["_networkId", "_clientStateNumber", "_clientState"];
|
||||
(getUserInfo _networkId) call RangerMetrics_fnc_player_identity;
|
||||
(getUserInfo _networkId) call RangerMetrics_fnc_player_status;
|
||||
["server_events", "OnUserDisconnected", nil, [
|
||||
["string", "networkId", _networkId],
|
||||
["int", "clientStateNumber", _clientStateNumber],
|
||||
["string", "clientState", _clientState]
|
||||
]] call RangerMetrics_fnc_queue;
|
||||
}];
|
||||
|
||||
addMissionEventHandler ["PlayerConnected", {
|
||||
params ["_id", "_uid", "_name", "_jip", "_owner", "_idstr"];
|
||||
(getUserInfo _idstr) call RangerMetrics_fnc_player_identity;
|
||||
(getUserInfo _idstr) call RangerMetrics_fnc_player_status;
|
||||
["server_events", "PlayerConnected", nil, [
|
||||
["int", "id", _id],
|
||||
["string", "uid", _uid],
|
||||
["string", "name", _name],
|
||||
["bool", "jip", _jip],
|
||||
["int", "owner", _owner],
|
||||
["string", "idstr", _idstr]
|
||||
]] call RangerMetrics_fnc_queue;
|
||||
}];
|
||||
addMissionEventHandler ["PlayerDisconnected", {
|
||||
params ["_id", "_uid", "_name", "_jip", "_owner", "_idstr"];
|
||||
(getUserInfo _idstr) call RangerMetrics_fnc_player_identity;
|
||||
(getUserInfo _idstr) call RangerMetrics_fnc_player_status;
|
||||
["server_events", "PlayerDisconnected", nil, [
|
||||
["int", "id", _id],
|
||||
["string", "uid", _uid],
|
||||
["string", "name", _name],
|
||||
["bool", "jip", _jip],
|
||||
["int", "owner", _owner],
|
||||
["string", "idstr", _idstr]
|
||||
]] call RangerMetrics_fnc_queue;
|
||||
}];
|
||||
|
||||
addMissionEventHandler ["OnUserClientStateChanged", {
|
||||
params ["_networkId", "_clientStateNumber", "_clientState"];
|
||||
(getUserInfo _networkId) call RangerMetrics_fnc_player_status;
|
||||
["server_events", "OnUserClientStateChanged", nil, [
|
||||
["string", "networkId", _networkId],
|
||||
["int", "clientStateNumber", _clientStateNumber],
|
||||
["string", "clientState", _clientState]
|
||||
]] call RangerMetrics_fnc_queue;
|
||||
}];
|
||||
addMissionEventHandler ["OnUserAdminStateChanged", {
|
||||
params ["_networkId", "_loggedIn", "_votedIn"];
|
||||
(getUserInfo _networkId) call RangerMetrics_fnc_player_status;
|
||||
["server_events", "OnUserAdminStateChanged", nil, [
|
||||
["string", "networkId", _networkId],
|
||||
["bool", "loggedIn", _loggedIn],
|
||||
["bool", "votedIn", _votedIn]
|
||||
]] call RangerMetrics_fnc_queue;
|
||||
}];
|
||||
|
||||
addMissionEventHandler ["HandleChatMessage", {
|
||||
_this call RangerMetrics_fnc_chat_message;
|
||||
// don't interfaere with the chat message
|
||||
false;
|
||||
}];
|
||||
@@ -0,0 +1,14 @@
|
||||
params ["_name", "_function", "_data"];
|
||||
if (_name == "RangerMetrics") then {
|
||||
if (isNil "_data") then {_data = ""};
|
||||
try {
|
||||
if (_data isEqualType "") exitWith {
|
||||
_data = parseSimpleArray _data;
|
||||
_data call RangerMetrics_fnc_log;
|
||||
};
|
||||
|
||||
diag_log format ["Callback unsupported type: %1: %2", _function, _data];
|
||||
} catch {
|
||||
_data = format ["%1", _data];
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
private _visualSettings = [
|
||||
["objectViewDistance", getObjectViewDistance # 0],
|
||||
["viewDistance", viewDistance]
|
||||
];
|
||||
@@ -10,24 +10,24 @@ RangerMetrics_messageQueue = createHashMap;
|
||||
[format ["CBA detected: %1", _cba]] call RangerMetrics_fnc_log;
|
||||
["Initializing v1.1"] call RangerMetrics_fnc_log;
|
||||
|
||||
private _settingsLoaded = ["RangerMetrics.influx.load_settings", []] call py3_fnc_callExtension;
|
||||
if (isNil "_settingsLoaded") exitWith {
|
||||
["Extension not found, disabling"] call RangerMetrics_fnc_log;
|
||||
RangerMetrics_run = false;
|
||||
};
|
||||
if (_settingsLoaded isEqualTo []) then {
|
||||
if (count _settingsLoaded == 0) exitWith {
|
||||
["Settings not loaded, disabling"] call RangerMetrics_fnc_log;
|
||||
RangerMetrics_run = false;
|
||||
};
|
||||
if (_settingsLoaded#0 isEqualTo 1) exitWith {
|
||||
[
|
||||
format["Settings not loaded, disabling. %1", _settingsLoaded#1],
|
||||
"ERROR"
|
||||
] call RangerMetrics_fnc_log;
|
||||
RangerMetrics_run = false;
|
||||
};
|
||||
};
|
||||
private _settingsLoaded = "RangerMetrics" callExtension "loadSettings";
|
||||
// if (isNil "_settingsLoaded") exitWith {
|
||||
// ["Extension not found, disabling"] call RangerMetrics_fnc_log;
|
||||
// RangerMetrics_run = false;
|
||||
// };
|
||||
// if (_settingsLoaded isEqualTo []) then {
|
||||
// if (count _settingsLoaded == 0) exitWith {
|
||||
// ["Settings not loaded, disabling"] call RangerMetrics_fnc_log;
|
||||
// RangerMetrics_run = false;
|
||||
// };
|
||||
// if (_settingsLoaded#0 isEqualTo 1) exitWith {
|
||||
// [
|
||||
// format["Settings not loaded, disabling. %1", _settingsLoaded#1],
|
||||
// "ERROR"
|
||||
// ] call RangerMetrics_fnc_log;
|
||||
// RangerMetrics_run = false;
|
||||
// };
|
||||
// };
|
||||
format["Settings loaded: %1", _settingsLoaded#2] call RangerMetrics_fnc_log;
|
||||
RangerMetrics_settings = _settingsLoaded#2;
|
||||
// RangerMetrics_settings = createHashMap;
|
||||
@@ -40,7 +40,7 @@ RangerMetrics_settings = _settingsLoaded#2;
|
||||
// "arma3",
|
||||
// createHashMapFromArray (_top get "refreshRateMs")
|
||||
// ];
|
||||
["RangerMetrics.influx.connect_to_influx", []] call py3_fnc_callExtension;
|
||||
"RangerMetrics" callExtension "connectToInflux";
|
||||
|
||||
RangerMetrics_run = true;
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ private _prefix = "Arma3";
|
||||
|
||||
private _extSend = [
|
||||
_measurement, // metric name
|
||||
_valueType, // float or int or bool
|
||||
_valueType // float or int or bool
|
||||
];
|
||||
|
||||
private _outTags = [ // tags
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/* ----------------------------------------------------------------------------
|
||||
Function: CBA_fnc_encodeJSON
|
||||
|
||||
Description:
|
||||
Serializes input to a JSON string. Can handle
|
||||
- ARRAY
|
||||
- BOOL
|
||||
- CONTROL
|
||||
- GROUP
|
||||
- LOCATION
|
||||
- NAMESPACE
|
||||
- NIL (ANY)
|
||||
- NUMBER
|
||||
- OBJECT
|
||||
- STRING
|
||||
- TASK
|
||||
- TEAM_MEMBER
|
||||
- HASHMAP
|
||||
- Everything else will simply be stringified.
|
||||
|
||||
Parameters:
|
||||
_object - Object to serialize. <ARRAY, ...>
|
||||
|
||||
Returns:
|
||||
_json - JSON string containing serialized object.
|
||||
|
||||
Examples:
|
||||
(begin example)
|
||||
private _settings = call CBA_fnc_createNamespace;
|
||||
_settings setVariable ["enabled", true];
|
||||
private _json = [_settings] call CBA_fnc_encodeJSON;
|
||||
(end)
|
||||
|
||||
Author:
|
||||
BaerMitUmlaut
|
||||
---------------------------------------------------------------------------- */
|
||||
params ["_object"];
|
||||
|
||||
if (isNil "_object") exitWith { "null" };
|
||||
|
||||
switch (typeName _object) do {
|
||||
case "SCALAR";
|
||||
case "BOOL": {
|
||||
str _object;
|
||||
};
|
||||
|
||||
case "STRING": {
|
||||
{
|
||||
_object = [_object, _x#0, _x#1] call CBA_fnc_replace;
|
||||
} forEach [
|
||||
["\", "\\"],
|
||||
["""", "\"""],
|
||||
[toString [8], "\b"],
|
||||
[toString [12], "\f"],
|
||||
[endl, "\n"],
|
||||
[toString [10], "\n"],
|
||||
[toString [13], "\r"],
|
||||
[toString [9], "\t"]
|
||||
];
|
||||
// Stringify without escaping inter string quote marks.
|
||||
"""" + _object + """"
|
||||
};
|
||||
|
||||
case "ARRAY": {
|
||||
if ([_object] call CBA_fnc_isHash) then {
|
||||
private _json = (([_object] call CBA_fnc_hashKeys) apply {
|
||||
private _name = _x;
|
||||
private _value = [_object, _name] call CBA_fnc_hashGet;
|
||||
|
||||
format ["%1: %2", [_name] call CBA_fnc_encodeJSON, [_value] call CBA_fnc_encodeJSON]
|
||||
}) joinString ", ";
|
||||
"{" + _json + "}"
|
||||
} else {
|
||||
private _json = (_object apply {[_x] call CBA_fnc_encodeJSON}) joinString ", ";
|
||||
"[" + _json + "]"
|
||||
};
|
||||
};
|
||||
|
||||
case "HASHMAP": {
|
||||
private _json = ((_object toArray false) apply {
|
||||
_x params ["_key", ["_value", objNull]];
|
||||
|
||||
if !(_key isEqualType "") then {
|
||||
_key = str _key;
|
||||
};
|
||||
|
||||
format ["%1: %2", [_key] call CBA_fnc_encodeJSON, [_value] call CBA_fnc_encodeJSON]
|
||||
}) joinString ", ";
|
||||
"{" + _json + "}"
|
||||
};
|
||||
|
||||
default {
|
||||
if !(typeName _object in (supportInfo "u:allVariables*" apply {_x splitString " " select 1})) exitWith {
|
||||
[str _object] call CBA_fnc_encodeJSON
|
||||
};
|
||||
|
||||
if (isNull _object) exitWith { "null" };
|
||||
|
||||
private _json = ((allVariables _object) apply {
|
||||
private _name = _x;
|
||||
private _value = _object getVariable [_name, objNull];
|
||||
|
||||
format ["%1: %2", [_name] call CBA_fnc_encodeJSON, [_value] call CBA_fnc_encodeJSON]
|
||||
}) joinString ", ";
|
||||
"{" + _json + "}"
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// PX_fnc_stringReplace :: Replace substrings
|
||||
// Author: Colin J.D. Stewart
|
||||
// Usage: ["xxx is awesome, I love xxx!", "xxx" || [], "Arma"] call PX_fnc_stringReplace;
|
||||
//
|
||||
|
||||
params["_str", "_find", "_replace"];
|
||||
private["_return", "_len", "_pos"];
|
||||
|
||||
if !(_str isEqualType "") exitWith {
|
||||
[
|
||||
format[
|
||||
"RangerMetrics_fnc_stringReplace: _str is not a string. %1",
|
||||
_str
|
||||
],
|
||||
"ERROR"
|
||||
] call RangerMetrics_fnc_log;
|
||||
"";
|
||||
};
|
||||
|
||||
if (!(_find isEqualType [])) then {
|
||||
_find = [_find];
|
||||
};
|
||||
|
||||
{
|
||||
_return = "";
|
||||
_len = count _x;
|
||||
_pos = _str find _x;
|
||||
|
||||
while {(_pos != -1) && (count _str > 0)} do {
|
||||
_return = _return + (_str select [0, _pos]) + _replace;
|
||||
|
||||
_str = (_str select [_pos+_len]);
|
||||
_pos = _str find _x;
|
||||
};
|
||||
_str = _return + _str;
|
||||
} forEach _find;
|
||||
|
||||
_str;
|
||||
@@ -0,0 +1,17 @@
|
||||
params [
|
||||
["_valueType", "string", [""]],
|
||||
"_key",
|
||||
"_value"
|
||||
];
|
||||
|
||||
// debug
|
||||
// diag_log format["%1=%2", _key, _value];
|
||||
|
||||
if (_value isEqualTo "") exitWith {
|
||||
"";
|
||||
};
|
||||
if (_valueType isEqualTo "string") exitWith {
|
||||
format['%1="%2"', _key, _value];
|
||||
};
|
||||
|
||||
format['%1=%2', _key, _value];
|
||||
@@ -0,0 +1 @@
|
||||
(parseSimpleArray ("RangerMetrics" callExtension "getUnixTimeNano")) select 0;
|
||||
@@ -0,0 +1,40 @@
|
||||
params ["_channel", "_owner", "_from", "_text", "_person", "_name", "_strID", "_forcedDisplay", "_isPlayerMessage", "_sentenceType", "_chatMessageType"];
|
||||
|
||||
|
||||
|
||||
private _fields = [
|
||||
["int", "channel", _channel],
|
||||
["int", "owner", _owner],
|
||||
["string", "from", _from],
|
||||
["string", "text", _text],
|
||||
// ["object", "person", _person],
|
||||
["string", "name", _name],
|
||||
["string", "strID", _strID],
|
||||
["bool", "forcedDisplay", _forcedDisplay],
|
||||
["bool", "isPlayerMessage", _isPlayerMessage],
|
||||
["int", "sentenceType", _sentenceType],
|
||||
["int", "chatMessageType", _chatMessageType]
|
||||
];
|
||||
|
||||
// we need special processing to ensure the object is valid and we have a playerUid. Line protocol doesn't support empty string
|
||||
private "_playerUid";
|
||||
if (isNil "_person") then {
|
||||
_playerUid = "";
|
||||
} else {
|
||||
if !(objNull isEqualType _person) then {
|
||||
_playerUid = getPlayerUID _person;
|
||||
} else {
|
||||
_playerUid = "";
|
||||
};
|
||||
};
|
||||
|
||||
if (_playerUid isNotEqualTo "") then {
|
||||
_fields pushBack ["string", "playerUid", _playerUid];
|
||||
};
|
||||
|
||||
[
|
||||
"server_events",
|
||||
"HandleChatMessage",
|
||||
nil,
|
||||
_fields
|
||||
] call RangerMetrics_fnc_queue;
|
||||
@@ -0,0 +1,7 @@
|
||||
// Number of global units
|
||||
["server_state", "entities_global", nil, [
|
||||
["int", "units_alive", count allUnits ],
|
||||
["int", "units_dead", count allDeadMen],
|
||||
["int", "groups_total", count allGroups],
|
||||
["int", "vehicles_total", count vehicles]
|
||||
]] call RangerMetrics_fnc_queue;
|
||||
@@ -0,0 +1,7 @@
|
||||
// Number of local units
|
||||
["server_state", "entities_local", nil, [
|
||||
["int", "units_alive", { local _x} count allUnits ],
|
||||
["int", "units_dead", { local _x } count allDeadMen],
|
||||
["int", "groups_total", { local _x } count allGroups],
|
||||
["int", "vehicles_total", { local _x } count vehicles]
|
||||
]] call RangerMetrics_fnc_queue;
|
||||
@@ -0,0 +1,210 @@
|
||||
// get basic config properties
|
||||
private _properties = [
|
||||
["mission_info", [
|
||||
"author",
|
||||
"onLoadName",
|
||||
"onLoadMission",
|
||||
"loadScreen",
|
||||
// "header",
|
||||
"gameType",
|
||||
"minPlayers",
|
||||
"maxPlayers",
|
||||
"onLoadIntro",
|
||||
"onLoadMissionTime",
|
||||
"onLoadIntroTime",
|
||||
"briefingName",
|
||||
"overviewPicture",
|
||||
"overviewText",
|
||||
"overviewTextLocked"
|
||||
]],
|
||||
["respawn", [
|
||||
"respawn",
|
||||
"respawnButton",
|
||||
"respawnDelay",
|
||||
"respawnVehicleDelay",
|
||||
"respawnDialog",
|
||||
"respawnOnStart",
|
||||
"respawnTemplates",
|
||||
"respawnTemplatesWest",
|
||||
"respawnTemplatesEast",
|
||||
"respawnTemplatesGuer",
|
||||
"respawnTemplatesCiv",
|
||||
"respawnWeapons",
|
||||
"respawnMagazines",
|
||||
"reviveMode",
|
||||
"reviveUnconsciousStateMode",
|
||||
"reviveRequiredTrait",
|
||||
"reviveRequiredItems",
|
||||
"reviveRequiredItemsFakConsumed",
|
||||
"reviveMedicSpeedMultiplier",
|
||||
"reviveDelay",
|
||||
"reviveForceRespawnDelay",
|
||||
"reviveBleedOutDelay",
|
||||
"enablePlayerAddRespawn"
|
||||
]],
|
||||
["player_ui", [
|
||||
"overrideFeedback",
|
||||
"showHUD",
|
||||
"showCompass",
|
||||
"showGPS",
|
||||
"showGroupIndicator",
|
||||
"showMap",
|
||||
"showNotePad",
|
||||
"showPad",
|
||||
"showWatch",
|
||||
"showUAVFeed",
|
||||
"showSquadRadar"
|
||||
]],
|
||||
["corpse_and_wreck", [
|
||||
"corpseManagerMode",
|
||||
"corpseLimit",
|
||||
"corpseRemovalMinTime",
|
||||
"corpseRemovalMaxTime",
|
||||
"wreckManagerMode",
|
||||
"wreckLimit",
|
||||
"wreckRemovalMinTime",
|
||||
"wreckRemovalMaxTime",
|
||||
"minPlayerDistance"
|
||||
]],
|
||||
["mission_settings", [
|
||||
"aiKills",
|
||||
"briefing",
|
||||
"debriefing",
|
||||
"disableChannels",
|
||||
"disabledAI",
|
||||
"disableRandomization",
|
||||
"enableDebugConsole",
|
||||
"enableItemsDropping",
|
||||
"enableTeamSwitch",
|
||||
"forceRotorLibSimulation",
|
||||
"joinUnassigned",
|
||||
"minScore",
|
||||
"avgScore",
|
||||
"maxScore",
|
||||
"onCheat",
|
||||
"onPauseScript",
|
||||
"saving",
|
||||
"scriptedPlayer",
|
||||
"skipLobby",
|
||||
"HostDoesNotSkipLobby",
|
||||
"missionGroup"
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
private _propertyValues = createHashMap;
|
||||
// recursively walk through missionConfigFile and get all properties into a single hashmap
|
||||
// iterate through list of categories with desired property names
|
||||
// if the property exists in the extracted missionConfigFile property hash, save it with the category into _propertyValues
|
||||
{
|
||||
private _category = _x#0;
|
||||
private _values = _x#1;
|
||||
{
|
||||
private _property = _x;
|
||||
private _value = (missionConfigFile >> _property) call BIS_fnc_getCfgData;
|
||||
// hint str [_category, _property, _value];
|
||||
if (!isNil "_value") then {
|
||||
if (typeName _value == "ARRAY") then {
|
||||
_value = _value joinString ",";
|
||||
};
|
||||
if (isNil {_propertyValues get _category}) then {
|
||||
_propertyValues set [_category, createHashMap];
|
||||
};
|
||||
_propertyValues get _category set [_property, _value];
|
||||
};
|
||||
} forEach _values;
|
||||
} forEach _properties;
|
||||
|
||||
|
||||
// Take the generated hashmap of custom-categorized configuration properties and queue them for metrics
|
||||
{
|
||||
private _measurementCategory = _x;
|
||||
private _fields = _y;
|
||||
private _fieldsWithType = [];
|
||||
|
||||
// InfluxDB lookup hash
|
||||
_types = createHashMapFromArray [
|
||||
["STRING", "string"],
|
||||
["ARRAY", "string"],
|
||||
["SCALAR", "float"],
|
||||
["BOOL", "bool"]
|
||||
];
|
||||
|
||||
// Preprocess the fields to clean the raw data
|
||||
{
|
||||
private _fieldName = _x;
|
||||
private _fieldValue = _y;
|
||||
private _fieldType = _types get (typeName _fieldValue);
|
||||
// turn ARRAY into string since Influx can't take them
|
||||
if (typeName _fieldValue == "ARRAY") then {
|
||||
_fieldValue = _fieldValue joinString "|";
|
||||
};
|
||||
// convert 0 or 1 (from config) to BOOL
|
||||
if (typeName _fieldValue == "SCALAR" && _fieldValue in [0, 1]) then {
|
||||
_fieldType = "bool";
|
||||
if (_fieldValue == 0) then {
|
||||
_fieldValue = "false";
|
||||
} else {
|
||||
_fieldValue = "true";
|
||||
};
|
||||
};
|
||||
_fieldsWithType pushBack [_fieldType, _fieldName, _fieldValue];
|
||||
} forEach _fields;
|
||||
|
||||
// finally, send the data
|
||||
[
|
||||
"config_state",
|
||||
"mission_config_file",
|
||||
[
|
||||
["category", _measurementCategory]
|
||||
],
|
||||
_fieldsWithType
|
||||
] call RangerMetrics_fnc_queue;
|
||||
} forEach _propertyValues;
|
||||
|
||||
|
||||
|
||||
|
||||
// get all properties in missionConfigFile (recursive)
|
||||
// private _nextCfgClasses = "true" configClasses (missionConfigFile);
|
||||
// private _nextCfgProperties = configProperties [missionConfigFile];
|
||||
// private _cfgProperties = createHashMap;
|
||||
// while {count _nextCfgClasses > 0} do {
|
||||
// {
|
||||
// private _thisConfig = _x;
|
||||
// private _thisConfigClasses = "true" configClasses _thisConfig;
|
||||
// _thisCfgProperties = configProperties [_thisConfig, "!isClass _x"];
|
||||
// _saveHash = createHashMap;
|
||||
// {
|
||||
// _propertyCfg = _x;
|
||||
// _saveHash set [configName _propertyCfg, (_propertyCfg) call BIS_fnc_getCfgData];
|
||||
// } forEach _thisCfgProperties;
|
||||
// _hierarchy = (configHierarchy _thisConfig);
|
||||
// _hierarchy deleteAt 0;
|
||||
// _hierarchy = _hierarchy apply {configName _x};
|
||||
// _hierarchyStr = _hierarchy joinString ".";
|
||||
// _hierarchyStrParent = (_hierarchy select [0, count _hierarchy - 2]) joinString ".";
|
||||
// systemChat _hierarchyStrParent;
|
||||
|
||||
// // if (_cfgProperties get _hierarchyStrParent == nil) then {
|
||||
// // _cfgProperties set [_hierarchyStrParent, createHashMap];
|
||||
// // };
|
||||
// _cfgProperties set [_hierarchyStr, _saveHash];
|
||||
|
||||
|
||||
// // _cfgProperties set [_hierarchy, _saveHash];
|
||||
// _nextCfgClasses append _thisConfigClasses;
|
||||
|
||||
// } forEach _nextCfgClasses;
|
||||
// _nextCfgClasses = _nextCfgClasses - _cfgClasses;
|
||||
// };
|
||||
// text ([_cfgProperties] call RangerMetrics_fnc_encodeJSON);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// iterate through _cfgProperties hashmap and queue metrics
|
||||
// {
|
||||
|
||||
// } forEach _cfgProperties;
|
||||
@@ -0,0 +1,22 @@
|
||||
params ["_playerID", "_ownerId", "_playerUID", "_profileName", "_displayName", "_steamName", "_clientState", "_isHC", "_adminState", "_networkInfo", "_unit", ["_jip", false]];
|
||||
// _networkInfo params ["_avgPing", "_avgBandwidth", "_desync"];
|
||||
|
||||
private _fields = [
|
||||
["string", "playerID", _playerID],
|
||||
["string", "ownerId", _ownerId],
|
||||
["string", "playerUID", _playerUID],
|
||||
["string", "profileName", _profileName],
|
||||
["string", "displayName", _displayName],
|
||||
["string", "steamName", _steamName],
|
||||
["bool", "isHC", _isHC],
|
||||
["bool", "jip", _jip]
|
||||
];
|
||||
|
||||
if (!isNil "_unit") then {
|
||||
private _roleDescription = roleDescription _unit;
|
||||
if (_roleDescription isNotEqualTo "") then {
|
||||
_fields pushBack ["string", "roleDescription", _roleDescription];
|
||||
};
|
||||
};
|
||||
|
||||
["player_state", "player_identity", [], _fields] call RangerMetrics_fnc_queue;
|
||||
@@ -0,0 +1,8 @@
|
||||
params ["_playerID", "_ownerId", "_playerUID", "_profileName", "_displayName", "_steamName", "_clientState", "_isHC", "_adminState", "_networkInfo", "_unit"];
|
||||
_networkInfo params ["_avgPing", "_avgBandwidth", "_desync"];
|
||||
|
||||
["player_state", "player_performance", [], [
|
||||
["float", "avgPing", _avgPing],
|
||||
["float", "avgBandwidth", _avgBandwidth],
|
||||
["float", "desync", _desync]
|
||||
]] call RangerMetrics_fnc_queue;
|
||||
@@ -0,0 +1,7 @@
|
||||
params ["_playerID", "_ownerId", "_playerUID", "_profileName", "_displayName", "_steamName", "_clientState", "_isHC", "_adminState", "_networkInfo", "_unit"];
|
||||
// _networkInfo params ["_avgPing", "_avgBandwidth", "_desync"];
|
||||
|
||||
["player_state", "player_status", [], [
|
||||
["int", "clientStateNumber", _clientState],
|
||||
["int", "adminState", _adminState]
|
||||
]] call RangerMetrics_fnc_queue;
|
||||
@@ -0,0 +1,20 @@
|
||||
// Mission name
|
||||
[
|
||||
"server_state", // bucket to store the data
|
||||
"mission_name", // measurement classifier inside of bucket
|
||||
nil, // tags
|
||||
[ // fields
|
||||
[
|
||||
"string",
|
||||
"onLoadName",
|
||||
[
|
||||
getMissionConfigValue ["onLoadName", ""],
|
||||
" ",
|
||||
"\ "
|
||||
] call RangerMetrics_fnc_stringReplace
|
||||
],
|
||||
["string","briefingName", briefingName],
|
||||
["string","missionName", missionName],
|
||||
["string","missionNameSource", missionNameSource]
|
||||
]
|
||||
] call RangerMetrics_fnc_queue;
|
||||
@@ -0,0 +1,7 @@
|
||||
["server_state", "running_scripts", nil, [
|
||||
["int", "spawn", diag_activeScripts select 0],
|
||||
["int", "execVM", diag_activeScripts select 1],
|
||||
["int", "exec", diag_activeScripts select 2],
|
||||
["int", "execFSM", diag_activeScripts select 3],
|
||||
["int", "pfh", if (RangerMetrics_cbaPresent) then {count CBA_common_perFrameHandlerArray} else {0}]
|
||||
]] call RangerMetrics_fnc_queue;
|
||||
@@ -0,0 +1,4 @@
|
||||
["server_state", "server_performance", nil, [
|
||||
["float", "avg", diag_fps toFixed 2],
|
||||
["float", "min", diag_fpsMin toFixed 2]
|
||||
]] call RangerMetrics_fnc_queue;
|
||||
@@ -0,0 +1,6 @@
|
||||
["server_state", "server_time", nil, [
|
||||
["float", "diag_tickTime", diag_tickTime toFixed 2],
|
||||
["float", "serverTime", time toFixed 2],
|
||||
["float", "timeMultiplier", timeMultiplier toFixed 2],
|
||||
["float", "accTime", accTime toFixed 2]
|
||||
]] call RangerMetrics_fnc_queue;
|
||||
243
@RangerMetrics/addons/RangerMetrics/influxSchema.plantuml
Normal file
243
@RangerMetrics/addons/RangerMetrics/influxSchema.plantuml
Normal file
@@ -0,0 +1,243 @@
|
||||
@startuml classDiagram
|
||||
class server_state {
|
||||
BUCKET
|
||||
}
|
||||
server_state --> running_mission
|
||||
class running_mission {
|
||||
tag string profileName
|
||||
tag string connectedServer
|
||||
field string onLoadName
|
||||
field string missionName
|
||||
field string missionNameSource
|
||||
field string briefingName
|
||||
}
|
||||
|
||||
server_state --> time
|
||||
class time {
|
||||
tag string profileName
|
||||
tag string connectedServer
|
||||
field float diag_tickTime
|
||||
field int serverTime
|
||||
field float timeMultiplier
|
||||
field int accTime
|
||||
}
|
||||
|
||||
server_state --> running_scripts
|
||||
class running_scripts {
|
||||
tag string profileName
|
||||
tag string connectedServer
|
||||
field int spawn_total
|
||||
field int execVM_total
|
||||
field int exec_total
|
||||
field int execFSM_total
|
||||
field int pfh_total
|
||||
}
|
||||
|
||||
server_state --> entities_local
|
||||
class entities_local {
|
||||
tag string profileName
|
||||
tag string connectedServer
|
||||
field int units_alive
|
||||
field int units_dead
|
||||
field int vehicles_total
|
||||
field int groups_total
|
||||
}
|
||||
server_state --> entities_global
|
||||
class entities_global {
|
||||
tag string profileName
|
||||
tag string connectedServer
|
||||
field int units_alive
|
||||
field int units_dead
|
||||
field int vehicles_total
|
||||
field int groups_total
|
||||
}
|
||||
|
||||
server_state --> server_performance
|
||||
class server_performance {
|
||||
tag string profileName
|
||||
tag string connectedServer
|
||||
field string fps_avg
|
||||
field string fps_min
|
||||
|
||||
}
|
||||
|
||||
server_state --> weather
|
||||
class weather {
|
||||
tag string profileName
|
||||
tag string connectedServer
|
||||
field string fog
|
||||
field string overcast
|
||||
field string rain
|
||||
field string humidity
|
||||
field string waves
|
||||
field string windDir
|
||||
field string windStr
|
||||
field string gusts
|
||||
field string lightnings
|
||||
field string moonIntensity
|
||||
field string moonPhase
|
||||
field string sunOrMoon
|
||||
}
|
||||
|
||||
class config_state {
|
||||
tag string profileName
|
||||
tag string connectedServer
|
||||
Measurement mission_config_file
|
||||
Measurement addon_options
|
||||
Measurement mission_parameters
|
||||
Measurement visual_settings
|
||||
}
|
||||
|
||||
config_state --> mission_config_file
|
||||
class mission_config_file {
|
||||
tag string profileName
|
||||
tag string connectedServer
|
||||
tag string category [
|
||||
mission_info
|
||||
respawn
|
||||
player_ui
|
||||
corpse_and_wreck
|
||||
mission_settings
|
||||
]
|
||||
|
||||
}
|
||||
' link fields in each category
|
||||
mission_config_file --> mission_info
|
||||
class mission_info {
|
||||
field string author
|
||||
field string onLoadName
|
||||
field string onLoadMission
|
||||
field string loadScreen
|
||||
' field string header
|
||||
field string gameType
|
||||
field int minPlayers
|
||||
field int maxPlayers
|
||||
field int onLoadIntro
|
||||
field int onLoadMissionTime
|
||||
field int onLoadIntroTime
|
||||
field string briefingName
|
||||
field string overviewPicture
|
||||
field string overviewText
|
||||
field string overviewTextLocked
|
||||
}
|
||||
|
||||
mission_config_file --> respawn
|
||||
class respawn {
|
||||
field string respawn
|
||||
field string respawnButton
|
||||
field string respawnDelay
|
||||
field string respawnVehicleDelay
|
||||
field string respawnDialog
|
||||
field string respawnOnStart
|
||||
field string respawnTemplates
|
||||
field string respawnTemplatesWest
|
||||
field string respawnTemplatesEast
|
||||
field string respawnTemplatesGuer
|
||||
field string respawnTemplatesCiv
|
||||
field string respawnWeapons
|
||||
field string respawnMagazines
|
||||
field int reviveMode
|
||||
field int reviveUnconsciousStateMode
|
||||
field int reviveRequiredTrait
|
||||
field int reviveRequiredItems
|
||||
field int reviveRequiredItemsFakConsumed
|
||||
field int reviveMedicSpeedMultiplier
|
||||
field int reviveDelay
|
||||
field int reviveForceRespawnDelay
|
||||
field int reviveBleedOutDelay
|
||||
field int enablePlayerAddRespawn
|
||||
}
|
||||
|
||||
mission_config_file --> player_ui
|
||||
class player_ui {
|
||||
field int overrideFeedback
|
||||
field int showHUD
|
||||
field int showCompass
|
||||
field int showGPS
|
||||
field int showGroupIndicator
|
||||
field int showMap
|
||||
field int showNotePad
|
||||
field int showPad
|
||||
field int showWatch
|
||||
field int showUAVFeed
|
||||
field int showSquadRadar
|
||||
}
|
||||
|
||||
mission_config_file --> corpse_and_wreck
|
||||
class corpse_and_wreck {
|
||||
field int corpseManagerMode
|
||||
field int corpseLimit
|
||||
field int corpseRemovalMinTime
|
||||
field int corpseRemovalMaxTime
|
||||
field int wreckManagerMode
|
||||
field int wreckLimit
|
||||
field int wreckRemovalMinTime
|
||||
field int wreckRemovalMaxTime
|
||||
field int minPlayerDistance
|
||||
}
|
||||
|
||||
mission_config_file --> mission_settings
|
||||
class mission_settings {
|
||||
field int aiKills
|
||||
field int briefing
|
||||
field int debriefing
|
||||
field string disableChannels
|
||||
field int disabledAI
|
||||
field string disableRandomization
|
||||
field List~string~ enableDebugConsole
|
||||
field int enableItemsDropping
|
||||
field int enableTeamSwitch
|
||||
field int forceRotorLibSimulation
|
||||
field int joinUnassigned
|
||||
field int minScore
|
||||
field int avgScore
|
||||
field int maxScore
|
||||
field string onCheat
|
||||
field string onPauseScript
|
||||
field int saving
|
||||
field int scriptedPlayer
|
||||
field int skipLobby
|
||||
field int HostDoesNotSkipLobby
|
||||
field string missionGroup
|
||||
}
|
||||
|
||||
|
||||
config_state --> visual_settings
|
||||
class visual_settings {
|
||||
field string getTIParameters
|
||||
field string objectViewDistance
|
||||
}
|
||||
|
||||
class player_state {
|
||||
Measurement identity
|
||||
Measurement status
|
||||
}
|
||||
|
||||
player_state --> player_identity
|
||||
class player_identity {
|
||||
field string playerID
|
||||
field string ownerId
|
||||
field string playerUID
|
||||
field string profileName
|
||||
field string displayName
|
||||
field string steamName
|
||||
bool string isHC
|
||||
}
|
||||
|
||||
player_state --> player_status
|
||||
class player_status {
|
||||
field int clientStateNumber
|
||||
field int adminState
|
||||
}
|
||||
|
||||
player_state --> player_performance
|
||||
class player_performance {
|
||||
field float avgPing
|
||||
field float avgBandwidth
|
||||
field float desync
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@enduml
|
||||
Reference in New Issue
Block a user