From 12ef61e067c9bf74edbec97cc90ae2e6b6ef319d Mon Sep 17 00:00:00 2001 From: IndigoFox Date: Mon, 10 Apr 2023 02:20:54 -0700 Subject: [PATCH] further expansion of metrics collection --- .../addons/RangerMetrics/config.cpp | 30 ++-- .../capture/EHOnly/fn_EntityKilled.sqf | 41 ++++++ .../functions/capture/EHOnly/fn_FiredMan.sqf | 21 +++ .../capture/EHOnly/fn_HandleChatMessage.sqf | 40 ++++++ .../capture/EHOnly/fn_MarkerCreated.sqf | 30 ++++ .../capture/EHOnly/fn_MarkerDeleted.sqf | 30 ++++ .../capture/EHOnly/fn_MarkerUpdated.sqf | 31 +++++ .../capture/EHOnly/fn_ace_unconscious.sqf | 20 +++ .../functions/capture/fn_entity_count.sqf | 25 ++++ .../capture/fn_mission_config_file.sqf | 2 + .../functions/capture/fn_player_identity.sqf | 9 +- .../capture/fn_player_performance.sqf | 2 + .../functions/capture/fn_player_status.sqf | 3 +- .../functions/capture/fn_running_mission.sqf | 5 +- .../functions/capture/fn_running_scripts.sqf | 2 + .../capture/fn_server_performance.sqf | 2 + .../functions/capture/fn_server_time.sqf | 2 + .../functions/capture/fn_unit_inventory.sqf | 48 +++++++ .../functions/capture/fn_unit_state.sqf | 72 ++++++++++ .../functions/capture/fn_view_distance.sqf | 9 ++ .../functions/capture/fn_weather.sqf | 2 + .../captureDefinitions/fn_client_poll.sqf | 18 +-- .../captureDefinitions/fn_server_CBA.sqf | 5 + .../fn_server_missionEH.sqf | 129 ++++++++++++++---- .../captureDefinitions/fn_server_poll.sqf | 7 +- .../functions/core/fn_classHandlers.sqf | 29 ++++ .../functions/core/fn_initUnit.sqf | 129 ++++++++++++++++++ .../functions/core/fn_postInit.sqf | 38 ++++-- .../RangerMetrics/functions/core/fn_send.sqf | 4 +- 29 files changed, 714 insertions(+), 71 deletions(-) create mode 100644 @RangerMetrics/addons/RangerMetrics/functions/capture/EHOnly/fn_EntityKilled.sqf create mode 100644 @RangerMetrics/addons/RangerMetrics/functions/capture/EHOnly/fn_FiredMan.sqf create mode 100644 @RangerMetrics/addons/RangerMetrics/functions/capture/EHOnly/fn_HandleChatMessage.sqf create mode 100644 @RangerMetrics/addons/RangerMetrics/functions/capture/EHOnly/fn_MarkerCreated.sqf create mode 100644 @RangerMetrics/addons/RangerMetrics/functions/capture/EHOnly/fn_MarkerDeleted.sqf create mode 100644 @RangerMetrics/addons/RangerMetrics/functions/capture/EHOnly/fn_MarkerUpdated.sqf create mode 100644 @RangerMetrics/addons/RangerMetrics/functions/capture/EHOnly/fn_ace_unconscious.sqf create mode 100644 @RangerMetrics/addons/RangerMetrics/functions/capture/fn_entity_count.sqf create mode 100644 @RangerMetrics/addons/RangerMetrics/functions/capture/fn_unit_inventory.sqf create mode 100644 @RangerMetrics/addons/RangerMetrics/functions/capture/fn_unit_state.sqf create mode 100644 @RangerMetrics/addons/RangerMetrics/functions/capture/fn_view_distance.sqf create mode 100644 @RangerMetrics/addons/RangerMetrics/functions/captureDefinitions/fn_server_CBA.sqf create mode 100644 @RangerMetrics/addons/RangerMetrics/functions/core/fn_classHandlers.sqf create mode 100644 @RangerMetrics/addons/RangerMetrics/functions/core/fn_initUnit.sqf diff --git a/@RangerMetrics/addons/RangerMetrics/config.cpp b/@RangerMetrics/addons/RangerMetrics/config.cpp index 83e725a..ee0a44a 100644 --- a/@RangerMetrics/addons/RangerMetrics/config.cpp +++ b/@RangerMetrics/addons/RangerMetrics/config.cpp @@ -10,6 +10,18 @@ class CfgPatches { }; class CfgFunctions { + class RangerMetrics_event { + class functions { + file = "\RangerMetrics\functions\capture\EHOnly"; + class ace_unconscious {}; + class EntityKilled {}; + class FiredMan {}; + class HandleChatMessage {}; + class MarkerCreated {}; + class MarkerDeleted {}; + class MarkerUpdated {}; + }; + } class RangerMetrics_cDefinitions { class functions { file = "\RangerMetrics\functions\captureDefinitions"; @@ -17,31 +29,32 @@ class CfgFunctions { class server_missionEH {}; class client_poll {}; // class clientEvent {}; + class server_CBA {}; }; }; class RangerMetrics_capture { // these names represent measurement names send to InfluxDB - snake case class functions { file = "\RangerMetrics\functions\capture"; - class chat_message {}; - class entities_global {}; - class entities_local {}; + class entity_count {}; class mission_config_file {}; class player_identity {}; - class player_loadout {}; class player_performance {}; class player_status {}; class running_mission {}; class running_scripts {}; class server_performance {}; class server_time {}; + class unit_inventory {}; + class unit_state {}; + class view_distance {}; class weather {}; }; }; class RangerMetrics { class core { file = "\RangerMetrics\functions\core"; - class postInit { postInit = 1;}; + class postInit { postInit = 1; }; class captureLoop {}; class log {}; class queue {}; @@ -49,11 +62,8 @@ class CfgFunctions { class callbackHandler {}; class sendClientPoll {}; class startServerPoll {}; - }; - - class eventHandlers { - file = "\RangerMetrics\functions\eventHandlers"; - class addHandlers {}; + class classHandlers {}; + class initUnit {}; }; class helpers { file = "\RangerMetrics\functions\helpers"; diff --git a/@RangerMetrics/addons/RangerMetrics/functions/capture/EHOnly/fn_EntityKilled.sqf b/@RangerMetrics/addons/RangerMetrics/functions/capture/EHOnly/fn_EntityKilled.sqf new file mode 100644 index 0000000..1897e00 --- /dev/null +++ b/@RangerMetrics/addons/RangerMetrics/functions/capture/EHOnly/fn_EntityKilled.sqf @@ -0,0 +1,41 @@ +if (!RangerMetrics_run) exitWith {}; +params ["_killed", "_killer", "_instigator"]; + +// check in case ACE is active and lastDamageSource has been broadcast via addLocalSoldierEH +_instigator = _unit getVariable [ + "ace_medical_lastDamageSource", + _instigator +]; + + +if (isNull _instigator) then { _instigator = UAVControl vehicle _killer select 0 }; // UAV/UGV player operated road kill +if (isNull _instigator) then { _instigator = _killer }; // player driven vehicle road kill +if (isNull _instigator) then { _instigator = _killed }; +// hint format ["Killed By %1", name _instigator]; + + + +private _tags = []; +private _fields = []; + +if (getPlayerUID _instigator != "") then { + _tags pushBack ["string", "killerPlayerUID", getPlayerUID _instigator]; +}; +if (name _instigator != "") then { + _fields pushBack ["string", "killerName", name _instigator]; +}; + +if (getPlayerUID _killed != "") then { + _tags pushBack ["string", "killedPlayerUID", getPlayerUID _killed]; +}; +if (name _killed != "") then { + _fields pushBack ["string", "killedName", name _killed]; +}; + +[ + "server_events", + "EntityKilled", + _tags, + _fields, + nil +] call RangerMetrics_fnc_queue; diff --git a/@RangerMetrics/addons/RangerMetrics/functions/capture/EHOnly/fn_FiredMan.sqf b/@RangerMetrics/addons/RangerMetrics/functions/capture/EHOnly/fn_FiredMan.sqf new file mode 100644 index 0000000..6e698f2 --- /dev/null +++ b/@RangerMetrics/addons/RangerMetrics/functions/capture/EHOnly/fn_FiredMan.sqf @@ -0,0 +1,21 @@ +params ["_unit", "_weapon", "_muzzle", "_mode", "_ammo", "_magazine", "_projectile", "_vehicle"]; +private _unitPlayerId = getPlayerId _unit; +private _userInfo = getUserInfo _unitPlayerId; + +[ + "player_events", + "FiredMan", + [ + ["string", "playerUID", _userInfo select 2] + ], + [ + ["string", "weapon", _weapon], + ["string", "muzzle", _muzzle], + ["string", "mode", _mode], + ["string", "ammo", _ammo], + ["string", "magazine", _magazine], + // ["object", "projectile", _projectile], + ["string", "vehicle", [configOf _vehicle] call displayName], + ["string", "vehicleClass", typeOf _vehicle] + ] +] call RangerMetrics_fnc_queue; \ No newline at end of file diff --git a/@RangerMetrics/addons/RangerMetrics/functions/capture/EHOnly/fn_HandleChatMessage.sqf b/@RangerMetrics/addons/RangerMetrics/functions/capture/EHOnly/fn_HandleChatMessage.sqf new file mode 100644 index 0000000..d7fb89b --- /dev/null +++ b/@RangerMetrics/addons/RangerMetrics/functions/capture/EHOnly/fn_HandleChatMessage.sqf @@ -0,0 +1,40 @@ +if (!RangerMetrics_run) exitWith {}; + +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; \ No newline at end of file diff --git a/@RangerMetrics/addons/RangerMetrics/functions/capture/EHOnly/fn_MarkerCreated.sqf b/@RangerMetrics/addons/RangerMetrics/functions/capture/EHOnly/fn_MarkerCreated.sqf new file mode 100644 index 0000000..482e7e8 --- /dev/null +++ b/@RangerMetrics/addons/RangerMetrics/functions/capture/EHOnly/fn_MarkerCreated.sqf @@ -0,0 +1,30 @@ +if (!RangerMetrics_run) exitWith {}; + +params ["_marker", "_channelNumber", "_owner", "_local"]; + +// Log marker +if (_marker isEqualTo "") exitWith {}; +if (_channelNumber isEqualTo "") exitWith {}; +if (_owner isEqualTo "") exitWith {}; + +// Get marker +private _markerData = _marker call BIS_fnc_markerToString; + +// Get owner playerUID +private _ownerUID = getPlayerUID _owner; +if (_ownerUID isEqualTo "") then { + _ownerUID = "-1"; +}; + +[ + "server_events", + "MarkerCreated", + [ + ["string", "actorPlayerUID", _ownerUID] + ], + [ + ["string", "marker", _markerData], + ["number", "channelNumber", _channelNumber], + ["string", "owner", _ownerUID] + ] +] call RangerMetrics_fnc_queue; diff --git a/@RangerMetrics/addons/RangerMetrics/functions/capture/EHOnly/fn_MarkerDeleted.sqf b/@RangerMetrics/addons/RangerMetrics/functions/capture/EHOnly/fn_MarkerDeleted.sqf new file mode 100644 index 0000000..4c52bc2 --- /dev/null +++ b/@RangerMetrics/addons/RangerMetrics/functions/capture/EHOnly/fn_MarkerDeleted.sqf @@ -0,0 +1,30 @@ +if (!RangerMetrics_run) exitWith {}; + +params ["_marker", "_channelNumber", "_owner", "_local"]; + +// Log marker +if (_marker isEqualTo "") exitWith {}; +if (_channelNumber isEqualTo "") exitWith {}; +if (_owner isEqualTo "") exitWith {}; + +// Get marker +private _markerData = _marker call BIS_fnc_markerToString; + +// Get owner playerUID +private _ownerUID = getPlayerUID _owner; +if (_ownerUID isEqualTo "") then { + _ownerUID = "-1"; +}; + +[ + "server_events", + "MarkerDeleted", + [ + ["string", "actorPlayerUID", _ownerUID] + ], + [ + ["string", "marker", _markerData], + ["number", "channelNumber", _channelNumber], + ["string", "owner", _ownerUID] + ] +] call RangerMetrics_fnc_queue; diff --git a/@RangerMetrics/addons/RangerMetrics/functions/capture/EHOnly/fn_MarkerUpdated.sqf b/@RangerMetrics/addons/RangerMetrics/functions/capture/EHOnly/fn_MarkerUpdated.sqf new file mode 100644 index 0000000..67d48ce --- /dev/null +++ b/@RangerMetrics/addons/RangerMetrics/functions/capture/EHOnly/fn_MarkerUpdated.sqf @@ -0,0 +1,31 @@ +if (!RangerMetrics_run) exitWith {}; + +params ["_marker", "_channelNumber", "_owner", "_local"]; + +// Log marker +if (_marker isEqualTo "") exitWith {}; +if (_channelNumber isEqualTo "") exitWith {}; +if (_owner isEqualTo "") exitWith {}; + +// Get marker +private _markerData = _marker call BIS_fnc_markerToString; + +// Get owner playerUID +private _ownerUID = getPlayerUID _owner; +if (_ownerUID isEqualTo "") then { + _ownerUID = "-1"; +}; + +[ + "server_events", + "MarkerUpdated", + [ + ["string", "actorPlayerUID", _ownerUID] + ], + [ + ["string", "marker", _markerData], + ["number", "channelNumber", _channelNumber], + ["string", "owner", _ownerUID] + ] +] call RangerMetrics_fnc_queue; + diff --git a/@RangerMetrics/addons/RangerMetrics/functions/capture/EHOnly/fn_ace_unconscious.sqf b/@RangerMetrics/addons/RangerMetrics/functions/capture/EHOnly/fn_ace_unconscious.sqf new file mode 100644 index 0000000..699471e --- /dev/null +++ b/@RangerMetrics/addons/RangerMetrics/functions/capture/EHOnly/fn_ace_unconscious.sqf @@ -0,0 +1,20 @@ +if (!RangerMetrics_run) exitWith {}; + +params [["_unit", objNull], "_unconscious"]; +if (isNull _unit) exitWith {}; + +// Get owner playerUID +private _unitUID = getPlayerUID _unitUID; +if (_unitUID isEqualTo "") exitWith {}; + +[ + "player_state", + "player_health", + [ + ["string", "playerUID", _unitUID] + ], + [ + ["int", "health", damage _unit], + ["bool", "state", _unconscious] + ] +] call RangerMetrics_fnc_queue; \ No newline at end of file diff --git a/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_entity_count.sqf b/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_entity_count.sqf new file mode 100644 index 0000000..66c532b --- /dev/null +++ b/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_entity_count.sqf @@ -0,0 +1,25 @@ +if (!RangerMetrics_run) exitWith {}; + +// Number of remote units +["server_state", "entities_remote", nil, [ + ["int", "units_alive", { not (local _x)} count allUnits ], + ["int", "units_dead", { not (local _x) } count allDeadMen], + ["int", "groups_total", { not (local _x) } count allGroups], + ["int", "vehicles_total", { not (local _x) } count vehicles] +]] call RangerMetrics_fnc_queue; + +// 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; + +// 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; \ No newline at end of file diff --git a/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_mission_config_file.sqf b/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_mission_config_file.sqf index 0179421..400b6dd 100644 --- a/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_mission_config_file.sqf +++ b/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_mission_config_file.sqf @@ -1,3 +1,5 @@ +if (!RangerMetrics_run) exitWith {}; + // get basic config properties private _properties = [ ["mission_info", [ diff --git a/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_player_identity.sqf b/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_player_identity.sqf index 51b30cf..2d0a280 100644 --- a/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_player_identity.sqf +++ b/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_player_identity.sqf @@ -1,3 +1,5 @@ +if (!RangerMetrics_run) exitWith {}; + params ["_playerID", "_ownerId", "_playerUID", "_profileName", "_displayName", "_steamName", "_clientState", "_isHC", "_adminState", "_networkInfo", "_unit", ["_jip", false]]; // _networkInfo params ["_avgPing", "_avgBandwidth", "_desync"]; @@ -12,13 +14,6 @@ private _fields = [ ["bool", "isJip", _jip] ]; -if (!isNil "_unit") then { - private _roleDescription = roleDescription _unit; - if (_roleDescription isNotEqualTo "") then { - _fields pushBack ["string", "roleDescription", _roleDescription]; - }; -}; - [ "player_state", "player_identity", diff --git a/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_player_performance.sqf b/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_player_performance.sqf index 0c8b2f8..1e8f6c0 100644 --- a/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_player_performance.sqf +++ b/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_player_performance.sqf @@ -1,3 +1,5 @@ +if (!RangerMetrics_run) exitWith {}; + { _x params ["_playerID", "_ownerId", "_playerUID", "_profileName", "_displayName", "_steamName", "_clientState", "_isHC", "_adminState", "_networkInfo", "_unit"]; _networkInfo params ["_avgPing", "_avgBandwidth", "_desync"]; diff --git a/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_player_status.sqf b/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_player_status.sqf index c70226c..fefa718 100644 --- a/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_player_status.sqf +++ b/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_player_status.sqf @@ -1,10 +1,11 @@ +if (!RangerMetrics_run) exitWith {}; + params ["_playerID", "_ownerId", "_playerUID", "_profileName", "_displayName", "_steamName", "_clientState", "_isHC", "_adminState", "_networkInfo", "_unit"]; // _networkInfo params ["_avgPing", "_avgBandwidth", "_desync"]; ["player_state", "player_status", [["string", "playerUID", _playerUID]], [ - ["int", "clientStateNumber", _clientState], ["int", "adminState", _adminState] ], diff --git a/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_running_mission.sqf b/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_running_mission.sqf index 4d4ed3a..7cc74dd 100644 --- a/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_running_mission.sqf +++ b/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_running_mission.sqf @@ -1,3 +1,5 @@ +if (!RangerMetrics_run) exitWith {}; + // Mission name [ "server_state", // bucket to store the data @@ -12,5 +14,6 @@ ["string","briefingName", briefingName], ["string","missionName", missionName], ["string","missionNameSource", missionNameSource] - ] + ], + ["profile", "server", "world"] // context ] call RangerMetrics_fnc_queue; diff --git a/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_running_scripts.sqf b/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_running_scripts.sqf index ba0e80f..fc6c7c3 100644 --- a/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_running_scripts.sqf +++ b/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_running_scripts.sqf @@ -1,3 +1,5 @@ +if (!RangerMetrics_run) exitWith {}; + ["server_state", "running_scripts", nil, [ ["int", "spawn", diag_activeScripts select 0], ["int", "execVM", diag_activeScripts select 1], diff --git a/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_server_performance.sqf b/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_server_performance.sqf index a2395e6..e1068c0 100644 --- a/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_server_performance.sqf +++ b/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_server_performance.sqf @@ -1,3 +1,5 @@ +if (!RangerMetrics_run) exitWith {}; + ["server_state", "server_performance", nil, [ ["float", "avg", diag_fps toFixed 2], ["float", "min", diag_fpsMin toFixed 2] diff --git a/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_server_time.sqf b/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_server_time.sqf index f3880f8..7a443ac 100644 --- a/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_server_time.sqf +++ b/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_server_time.sqf @@ -1,3 +1,5 @@ +if (!RangerMetrics_run) exitWith {}; + ["server_state", "server_time", nil, [ ["float", "diag_tickTime", diag_tickTime toFixed 2], ["float", "serverTime", time toFixed 2], diff --git a/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_unit_inventory.sqf b/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_unit_inventory.sqf new file mode 100644 index 0000000..4ba3f94 --- /dev/null +++ b/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_unit_inventory.sqf @@ -0,0 +1,48 @@ +params [ + ["_unit", objNull, [objNull]] +]; + +if (isNull _unit) exitWith {}; + +private _lastLoadout = _unit getVariable "RangerMetrics_myLoadout"; +if (isNil "_lastLoadout") then { + _lastLoadout = []; +}; + +private _currentLoadout = [ + ["string", "currentWeapon", currentWeapon _unit], + ["string", "uniform", uniform _unit], + ["string", "vest", vest _unit], + ["string", "backpack", backpack _unit], + ["string", "headgear", headgear _unit], + ["string", "goggles", goggles _unit], + ["string", "hmd", hmd _unit], + ["string", "primaryWeapon", primaryWeapon _unit], + ["string", "primaryWeaponMagazine", primaryWeaponMagazine _unit], + ["string", "secondaryWeapon", secondaryWeapon _unit], + ["string", "secondaryWeaponMagazine", secondaryWeaponMagazine _unit], + ["string", "handgunWeapon", handgunWeapon _unit], + ["string", "handgunMagazine", handgunMagazine _unit] +]; + +// exit if loadout hasn't changed +if (_lastLoadout isEqualTo _currentLoadout) exitWith {}; + +// continue if loadout has changed + +// store loadout data locally +_unit setVariable ["RangerMetrics_myLoadout", _currentLoadout]; + +_playerUID = getPlayerUID _unit; + + +// send loadout data +[ + "player_state", + "unit_loadout", + [ + ["string", "playerUID", _playerUID] + ], + _currentLoadout, + ["server"] +] call RangerMetrics_fnc_queue; \ No newline at end of file diff --git a/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_unit_state.sqf b/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_unit_state.sqf new file mode 100644 index 0000000..3022e93 --- /dev/null +++ b/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_unit_state.sqf @@ -0,0 +1,72 @@ +if (!RangerMetrics_run) exitWith {}; + +params ["_unit"]; +if (isNull _unit || !(isPlayer _unit)) exitWith {}; + +// Get owner playerUID +private _unitUID = getPlayerUID _unitUID; +if (_unitUID isEqualTo "") exitWith {}; + +// Medical info +private _isUnconscious = false; +private _isInCardiacArrest = false; +if (RangerMetrics_aceMedicalPresent) then { + _isUnconscious = _unit getVariable ["ace_medical_isUnconscious", false]; + _isInCardiacArrest = _unit getVariable ["ace_medical_isInCardiacArrest", false]; +} else { + _isUnconscious = (lifeState _unit) isEqualTo "INCAPACITATED"; +}; + +// Vehicle info +if (!isNull (objectParent _unit)) then { + _crew = fullCrew (objectParent _unit); + _pos = _crew find {(_x select 0) isEqualTo _unit}; + _vehicleRole = toLower _crew select _pos select 1; +} else { + _vehicleRole = ""; +}; + +// Declare fields +private _fields = [ + ["float", "health", 1 - (damage _unit)], + ["bool", "is_unconscious", _isUnconscious], + ["bool", "is_cardiac_arrest", _isInCardiacArrest], + ["bool", "is_captive", captive _unit], + ["bool", "in_vehicle", !isNull (objectParent _unit)], + ["string", "vehicle_role", _vehicleRole], + ["float", "speed_kmh", speed _unit] +]; + +// Role description +private _roleDescription = roleDescription _unit; +if (_roleDescription isNotEqualTo "") then { + _fields pushBack ["string", "roleDescription", _roleDescription]; +}; + +// Traits +private _playerTraits = getAllUnitTraits player; +{ + private _valueType = typeNAME (_x select 1); + switch (_valueType) do { + case "BOOL": { + _fields pushBack ["bool", (_x select 0), (_x select 1)]; + }; + case "SCALAR": { + _fields pushBack ["float", (_x select 0), (_x select 1)]; + }; + case "STRING": { + _fields pushBack ["string", (_x select 0), (_x select 1)]; + }; + }; +} forEach _playerTraits; + + +[ + "player_state", + "unit_status", + [ + ["string", "playerUID", _unitUID] + ], + _fields, + ["server"] +] call RangerMetrics_fnc_queue; \ No newline at end of file diff --git a/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_view_distance.sqf b/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_view_distance.sqf new file mode 100644 index 0000000..e1e7862 --- /dev/null +++ b/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_view_distance.sqf @@ -0,0 +1,9 @@ +[ + "server_state", + "view_distance", + nil, + [ + ["float", "objectViewDistance", getObjectViewDistance # 0], + ["float", "viewDistance", viewDistance] + ] +] call RangerMetrics_fnc_queue; \ No newline at end of file diff --git a/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_weather.sqf b/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_weather.sqf index 1099908..3e36920 100644 --- a/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_weather.sqf +++ b/@RangerMetrics/addons/RangerMetrics/functions/capture/fn_weather.sqf @@ -1,3 +1,5 @@ +if (!RangerMetrics_run) exitWith {}; + [ "server_state", // bucket to store the data "weather", // measurement classifier inside of bucket diff --git a/@RangerMetrics/addons/RangerMetrics/functions/captureDefinitions/fn_client_poll.sqf b/@RangerMetrics/addons/RangerMetrics/functions/captureDefinitions/fn_client_poll.sqf index cbf9e0f..42e418c 100644 --- a/@RangerMetrics/addons/RangerMetrics/functions/captureDefinitions/fn_client_poll.sqf +++ b/@RangerMetrics/addons/RangerMetrics/functions/captureDefinitions/fn_client_poll.sqf @@ -1,11 +1,11 @@ [ - [ - 5, // Poll interval in seconds - [ // Array of things to poll on clients - [ - "RangerMetrics_poll_loadout", // Name of localNamespace variable to save the handler as on clients - RangerMetrics_capture_fnc_player_loadout // Function to call - ] - ] - ] + // [ + // 5, // Poll interval in seconds + // [ // Array of things to poll on clients + // [ + // "RangerMetrics_poll_loadout", // Name of localNamespace variable to save the handler as on clients + // RangerMetrics_capture_fnc_player_loadout // Function to call + // ] + // ] + // ] ] \ No newline at end of file diff --git a/@RangerMetrics/addons/RangerMetrics/functions/captureDefinitions/fn_server_CBA.sqf b/@RangerMetrics/addons/RangerMetrics/functions/captureDefinitions/fn_server_CBA.sqf new file mode 100644 index 0000000..577a14a --- /dev/null +++ b/@RangerMetrics/addons/RangerMetrics/functions/captureDefinitions/fn_server_CBA.sqf @@ -0,0 +1,5 @@ +[ + ["ace_unconscious", { + call RangerMetrics_event_fnc_aceUnconscious + }] +] \ No newline at end of file diff --git a/@RangerMetrics/addons/RangerMetrics/functions/captureDefinitions/fn_server_missionEH.sqf b/@RangerMetrics/addons/RangerMetrics/functions/captureDefinitions/fn_server_missionEH.sqf index 7cece29..efc6fce 100644 --- a/@RangerMetrics/addons/RangerMetrics/functions/captureDefinitions/fn_server_missionEH.sqf +++ b/@RangerMetrics/addons/RangerMetrics/functions/captureDefinitions/fn_server_missionEH.sqf @@ -1,19 +1,12 @@ [ - ["MPEnded", { - private ["_winner", "_reason"]; - _winner = "Unknown"; - _reason = "Mission Complete"; - ["server_events", "MPEnded", nil, [ - ["string", "winner", _winner], - ["string", "reason", _reason] - ]] call RangerMetrics_fnc_queue; - call RangerMetrics_capture_fnc_running_mission; - }], ["OnUserConnected", { params ["_networkId", "_clientStateNumber", "_clientState"]; - (getUserInfo _networkId) call RangerMetrics_capture_fnc_player_identity; - (getUserInfo _networkId) call RangerMetrics_capture_fnc_player_status; - ["server_events", "UserConnected", nil, [ + private _userInfo = (getUserInfo _networkId); + _userInfo call RangerMetrics_capture_fnc_player_identity; + _userInfo call RangerMetrics_capture_fnc_player_status; + ["server_events", "UserConnected", [ + ["string", "playerUID", _userInfo#2] + ], [ ["string", "networkId", _networkId], ["int", "clientStateNumber", _clientStateNumber], ["string", "clientState", _clientState] @@ -21,9 +14,12 @@ }], ["OnUserDisconnected", { params ["_networkId", "_clientStateNumber", "_clientState"]; - (getUserInfo _networkId) call RangerMetrics_capture_fnc_player_identity; - (getUserInfo _networkId) call RangerMetrics_capture_fnc_player_status; - ["server_events", "OnUserDisconnected", nil, [ + private _userInfo = (getUserInfo _networkId); + _userInfo call RangerMetrics_capture_fnc_player_identity; + _userInfo call RangerMetrics_capture_fnc_player_status; + ["server_events", "OnUserDisconnected", [ + ["string", "playerUID", _userInfo#2] + ], [ ["string", "networkId", _networkId], ["int", "clientStateNumber", _clientStateNumber], ["string", "clientState", _clientState] @@ -31,9 +27,12 @@ }], ["PlayerConnected", { params ["_id", "_uid", "_name", "_jip", "_owner", "_idstr"]; - (getUserInfo _idstr) call RangerMetrics_capture_fnc_player_identity; - (getUserInfo _idstr) call RangerMetrics_capture_fnc_player_status; - ["server_events", "PlayerConnected", nil, [ + private _userInfo = (getUserInfo _networkId); + _userInfo call RangerMetrics_capture_fnc_player_identity; + _userInfo call RangerMetrics_capture_fnc_player_status; + ["server_events", "PlayerConnected", [ + ["string", "playerUID", _userInfo#2] + ], [ ["int", "id", _id], ["string", "uid", _uid], ["string", "name", _name], @@ -44,9 +43,12 @@ }], ["PlayerDisconnected", { params ["_id", "_uid", "_name", "_jip", "_owner", "_idstr"]; - (getUserInfo _idstr) call RangerMetrics_capture_fnc_player_identity; - (getUserInfo _idstr) call RangerMetrics_capture_fnc_player_status; - ["server_events", "PlayerDisconnected", nil, [ + private _userInfo = (getUserInfo _networkId); + _userInfo call RangerMetrics_capture_fnc_player_identity; + _userInfo call RangerMetrics_capture_fnc_player_status; + ["server_events", "PlayerDisconnected", [ + ["string", "playerUID", _userInfo#2] + ], [ ["int", "id", _id], ["string", "uid", _uid], ["string", "name", _name], @@ -57,8 +59,11 @@ }], ["OnUserClientStateChanged", { params ["_networkId", "_clientStateNumber", "_clientState"]; - (getUserInfo _networkId) call RangerMetrics_capture_fnc_player_status; - ["server_events", "OnUserClientStateChanged", nil, [ + private _userInfo = (getUserInfo _networkId); + _userInfo call RangerMetrics_capture_fnc_player_status; + ["server_events", "OnUserClientStateChanged", [ + ["string", "playerUID", _userInfo#2] + ], [ ["string", "networkId", _networkId], ["int", "clientStateNumber", _clientStateNumber], ["string", "clientState", _clientState] @@ -66,16 +71,86 @@ }], ["OnUserAdminStateChanged", { params ["_networkId", "_loggedIn", "_votedIn"]; - (getUserInfo _networkId) call RangerMetrics_capture_fnc_player_status; - ["server_events", "OnUserAdminStateChanged", nil, [ + private _userInfo = (getUserInfo _networkId); + _userInfo call RangerMetrics_capture_fnc_player_status; + ["server_events", "OnUserAdminStateChanged", [ + ["string", "playerUID", _userInfo#2] + ], [ ["string", "networkId", _networkId], ["bool", "loggedIn", _loggedIn], ["bool", "votedIn", _votedIn] ]] call RangerMetrics_fnc_queue; }], + ["OnUserKicked", { + params ["_networkId", "_kickTypeNumber", "_kickType", "_kickReason", "_kickMessageIncReason"]; + private _userInfo = (getUserInfo _networkId); + _userInfo call RangerMetrics_capture_fnc_player_identity; + _userInfo call RangerMetrics_capture_fnc_player_status; + ["server_events", "OnUserKicked", [ + ["string", "playerUID", _userInfo#2] + ], [ + ["string", "networkId", _networkId], + ["int", "kickTypeNumber", _kickTypeNumber], + ["string", "kickType", _kickType], + ["string", "kickReason", _kickReason], + ["string", "kickMessageIncReason", _kickMessageIncReason] + ]] call RangerMetrics_fnc_queue; + }], ["HandleChatMessage", { - _this call RangerMetrics_capture_fnc_chat_message; + _this call RangerMetrics_event_fnc_HandleChatMessage; // don't interfaere with the chat message false; + }], + ["MPEnded", { + private ["_winner", "_reason"]; + _winner = "Unknown"; + _reason = "Mission Complete"; + ["server_events", "MPEnded", nil, [ + ["string", "winner", _winner], + ["string", "reason", _reason] + ]] call RangerMetrics_fnc_queue; + call RangerMetrics_capture_fnc_running_mission; + }], + ["EntityCreated", { + params ["_entity"]; + call RangerMetrics_capture_fnc_entity_count; + }], + ["EntityKilled", { + _this call RangerMetrics_event_fnc_EntityKilled; + }], + ["GroupCreated", { + params ["_group"]; + call RangerMetrics_capture_fnc_entity_count; + }], + ["GroupDeleted", { + params ["_group"]; + call RangerMetrics_capture_fnc_entity_count; + }], + ["MarkerCreated", { + params ["_marker", "_channelNumber", "_owner", "_local"]; + _this call RangerMetrics_event_fnc_MarkerCreated; + }], + ["MarkerDeleted", { + params ["_marker", "_channelNumber", "_owner", "_local"]; + _this call RangerMetrics_event_fnc_MarkerDeleted; + }], + ["MarkerUpdated", { + params ["_marker", "_channelNumber", "_owner", "_local"]; + _this call RangerMetrics_event_fnc_MarkerUpdated; + }], + ["Service", { + params ["_serviceVehicle", "_servicedVehicle", "_serviceType", "_needsService", "_autoSupply"]; + [ + "server_events", + "Service", + [ + ["string", "serviceVehicle", typeOf _serviceVehicle], + ["string", "servicedVehicle", typeOf _servicedVehicle], + ["int", "serviceType", _serviceType], + ["bool", "needsService", _needsService], + ["bool", "autoSupply", _autoSupply] + ], + nil + ] call RangerMetrics_fnc_queue; }] ] \ No newline at end of file diff --git a/@RangerMetrics/addons/RangerMetrics/functions/captureDefinitions/fn_server_poll.sqf b/@RangerMetrics/addons/RangerMetrics/functions/captureDefinitions/fn_server_poll.sqf index 31c5a77..1a8555b 100644 --- a/@RangerMetrics/addons/RangerMetrics/functions/captureDefinitions/fn_server_poll.sqf +++ b/@RangerMetrics/addons/RangerMetrics/functions/captureDefinitions/fn_server_poll.sqf @@ -5,15 +5,16 @@ RangerMetrics_capture_fnc_server_performance, RangerMetrics_capture_fnc_running_scripts, RangerMetrics_capture_fnc_server_time, - RangerMetrics_capture_fnc_entities_local, - RangerMetrics_capture_fnc_entities_global, + RangerMetrics_capture_fnc_entity_count, RangerMetrics_capture_fnc_player_performance ] ], [ 60, [ - RangerMetrics_capture_fnc_weather + RangerMetrics_capture_fnc_weather, + RangerMetrics_capture_fnc_view_distance, + RangerMetrics_capture_fnc_running_mission ] ] ] \ No newline at end of file diff --git a/@RangerMetrics/addons/RangerMetrics/functions/core/fn_classHandlers.sqf b/@RangerMetrics/addons/RangerMetrics/functions/core/fn_classHandlers.sqf new file mode 100644 index 0000000..86b0003 --- /dev/null +++ b/@RangerMetrics/addons/RangerMetrics/functions/core/fn_classHandlers.sqf @@ -0,0 +1,29 @@ +if (!RangerMetrics_cbaPresent) exitWith { + [ + format["RangerMetrics: CBA not present, aborting class EHs."], + "WARN" + ] call RangerMetrics_fnc_log; +}; + +/////////////////////////////////////////////////////////////////////// +// Initialize all units +/////////////////////////////////////////////////////////////////////// +["All", "InitPost", { + private _unit = _this # 0; + + + if (_unit isKindOf "CAManBase" && isPlayer _unit) then { + [_unit] call RangerMetrics_fnc_initUnit; + }; + + + _unit setVariable ["RangerMetrics_id", RangerMetrics_nextID, true]; + + if (RangerMetrics_debug) then { + [ + format["ID %1, Object %2 (%3)", RangerMetrics_nextID, _unit, [configOf _unit] call BIS_fnc_displayName], + "DEBUG" + ] call RangerMetrics_fnc_log; + }; + RangerMetrics_nextID = RangerMetrics_nextID + 1; +}, nil, nil, true] call CBA_fnc_addClassEventHandler; \ No newline at end of file diff --git a/@RangerMetrics/addons/RangerMetrics/functions/core/fn_initUnit.sqf b/@RangerMetrics/addons/RangerMetrics/functions/core/fn_initUnit.sqf new file mode 100644 index 0000000..949d6ab --- /dev/null +++ b/@RangerMetrics/addons/RangerMetrics/functions/core/fn_initUnit.sqf @@ -0,0 +1,129 @@ +params [ + ["_unit", objNull, [objNull]] +]; + +if (isNull _unit) exitWith {}; +if (!isPlayer _unit) exitWith {}; + + +[RangerMetrics_aceMedicalPresent, { + if (not _this) exitWith {}; + player addEventHandler ["Dammaged", { + params ["_unit", "_killer", "_instigator", "_useEffects"]; + private _aceLastDamage = _unit getVariable "ace_medical_lastDamageSource"; + if (!isNil "_aceLastDamage") then { + _unit setVariable ["ace_medical_lastDamageSource", _aceLastDamage, 2]; + }; + }]; +}] remoteExec ["call", owner _unit, _unit]; + +_unit addEventHandler ["Dammaged", { + params ["_unit", "_selection", "_damage", "_hitIndex", "_hitPoint", "_shooter", "_projectile"]; + private _unitPlayerId = getPlayerId _unit; + private _userInfo = getUserInfo _unitPlayerId; + private _shooterPlayerId = (getPlayerId (getShotParents _projectile select 1)); + private _shooterInfo = getUserInfo _shooterPlayerId; + [_unit] call RangerMetrics_capture_fnc_unit_state; + + [ + "player_events", + "Dammaged", + [ + ["string", "playerUID", _userInfo select 2] + ], + [ + ["string", "selection", _selection], + ["number", "damage", _damage], + ["number", "hitIndex", _hitIndex], + ["string", "hitPoint", _hitPoint], + ["string", "shooter", _shooterInfo select 2], + ["string", "projectile", _projectile] + ], + ["server"] + ] call RangerMetrics_fnc_queue; +}]; + +_unit addEventHandler ["FiredMan", { + _this call RangerMetrics_event_fnc_FiredMan; +}]; + +_unit addEventHandler ["GetInMan", { + params ["_unit", "_role", "_vehicle", "_turret"]; + private _unitPlayerId = getPlayerId _unit; + private _userInfo = getUserInfo _unitPlayerId; + + [ + "player_events", + "GetInMan", + [ + ["string", "playerUID", _userInfo select 2] + ], + [ + ["string", "role", _role], + ["string", "vehicle", _vehicle], + ["string", "turret", _turret] + ], + ["server"] + ] call RangerMetrics_fnc_queue; +}]; + +_unit addEventHandler ["GetOutMan", { + params ["_unit", "_role", "_vehicle", "_turret"]; + private _unitPlayerId = getPlayerId _unit; + private _userInfo = getUserInfo _unitPlayerId; + + [ + "player_events", + "GetOutMan", + [ + ["string", "playerUID", _userInfo select 2] + ], + [ + ["string", "role", _role], + ["string", "vehicle", _vehicle], + ["string", "turret", _turret] + ], + ["server"] + ] call RangerMetrics_fnc_queue; +}]; + +_unit addEventHandler ["HandleScore", { + params ["_unit", "_object", "_score"]; + private _unitPlayerId = getPlayerId _unit; + private _userInfo = getUserInfo _unitPlayerId; + + [ + "player_events", + "HandleScore", + [ + ["string", "playerUID", _userInfo select 2] + ], + [ + ["int", "score", _score], + ["string", "objectClass", typeOf _object], + ["string", "object", [configOf _object] call BIS_fnc_displayName] + ], + ["server"] + ] call RangerMetrics_fnc_queue; + + nil; +}]; + + +// _unit addEventHandler ["InventoryClosed", { +// params ["_unit", "_container"]; +// private _unitPlayerId = getPlayerId _unit; +// private _userInfo = getUserInfo _unitPlayerId; + +// [ +// "player_events", +// "InventoryClosed", +// [ +// ["string", "playerUID", _userInfo select 2] +// ], +// [ +// ["string", "container", _container] +// ], +// ["server"] +// ] call RangerMetrics_fnc_queue; +// }]; \ No newline at end of file diff --git a/@RangerMetrics/addons/RangerMetrics/functions/core/fn_postInit.sqf b/@RangerMetrics/addons/RangerMetrics/functions/core/fn_postInit.sqf index 54c06ff..5ec7716 100644 --- a/@RangerMetrics/addons/RangerMetrics/functions/core/fn_postInit.sqf +++ b/@RangerMetrics/addons/RangerMetrics/functions/core/fn_postInit.sqf @@ -2,12 +2,13 @@ if (is3DEN || !isMultiplayer) exitWith {}; -RangerMetrics_cbaPresent = (isClass(configFile >> "CfgPatches" >> "cba_main")); +RangerMetrics_cbaPresent = isClass(configFile >> "CfgPatches" >> "cba_main"); +RangerMetrics_aceMedicalPresent = isClass(configFile >> "CfgPatches" >> "ace_medical_status"); RangerMetrics_logPrefix = "RangerMetrics"; RangerMetrics_debug = true; RangerMetrics_initialized = false; RangerMetrics_run = false; -RangerMetrics_activeThreads = []; +RangerMetrics_nextID = 0; RangerMetrics_messageQueue = createHashMap; RangerMetrics_sendBatchHandle = scriptNull; @@ -84,6 +85,10 @@ RangerMetrics_captureDefinitions = createHashMapFromArray [ [ "ClientPoll", call RangerMetrics_cDefinitions_fnc_client_poll + ], + [ + "CBAEvent", + call RangerMetrics_cDefinitions_fnc_server_CBA ] ]; @@ -113,21 +118,32 @@ RangerMetrics_captureDefinitions = createHashMapFromArray [ // begin client polling +// set up CBA event listeners +{_x params ["_handleName", "_code"]; + missionNamespace setVariable [ + ("RangerMetrics" + "_CBAEH_" + _handleName), + ([_handleName, _code] call CBA_fnc_addEventHandlerArgs) + ]; +} forEach (RangerMetrics_captureDefinitions get "CBAEvent"); + + +// set up CBA class inits if CBA loaded +call RangerMetrics_fnc_classHandlers; -// start sending -[{ - params ["_args", "_idPFH"]; - if (scriptDone RangerMetrics_sendBatchHandle) then { - RangerMetrics_sendBatchHandle = [] spawn RangerMetrics_fnc_send; - }; -}, 2, []] call CBA_fnc_addPerFrameHandler; RangerMetrics_initialized = true; RangerMetrics_run = true; - -call RangerMetrics_capture_fnc_running_mission; +["RangerMetrics_run", true] remoteExecCall ["setVariable", 0, true]; +// start sending +[{ + params ["_args", "_idPFH"]; + // if (scriptDone RangerMetrics_sendBatchHandle) then { + // RangerMetrics_sendBatchHandle = [] spawn RangerMetrics_fnc_send; + // }; + call RangerMetrics_fnc_send; +}, 3, []] call CBA_fnc_addPerFrameHandler; \ No newline at end of file diff --git a/@RangerMetrics/addons/RangerMetrics/functions/core/fn_send.sqf b/@RangerMetrics/addons/RangerMetrics/functions/core/fn_send.sqf index 19314ea..df8fd94 100644 --- a/@RangerMetrics/addons/RangerMetrics/functions/core/fn_send.sqf +++ b/@RangerMetrics/addons/RangerMetrics/functions/core/fn_send.sqf @@ -23,8 +23,8 @@ if ( // 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]; + _processing = _records select [0, (count _records -1) min 750]; + _records = _records select [750, count _records - 1]; // send the data if (