diff --git a/CLAUDE.md b/CLAUDE.md index 486e896..bfdfad2 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -97,5 +97,9 @@ Author: ---------------------------------------------------------------------------- */ ``` +### Extension Commands + +Commands sent to the extension DLL via `callExtension` follow a `:RESOURCE:ACTION:` naming convention. New commands must use this pattern — resource noun first, then verb/qualifier (e.g., `:SOLDIER:CREATE:`, `:EVENT:KILL:`, `:SYS:INIT:`). + ### ACE3 Integration ACE3 support is optional with graceful fallback. `fnc_aceExplosives.sqf` handles placed explosives and detonation tracking. diff --git a/addons/extension/fnc_initSession.sqf b/addons/extension/fnc_initSession.sqf index 11fe45d..a7d7abd 100644 --- a/addons/extension/fnc_initSession.sqf +++ b/addons/extension/fnc_initSession.sqf @@ -16,7 +16,7 @@ addMissionEventHandler ["ExtensionCallback", { TRACE_3("ExtensionCallback",_name,_function,_data); - if (_function isEqualTo ":VERSION:") exitWith { + if (_function isEqualTo ":SYS:VERSION:") exitWith { // version return is automatic during extension init process private _ver = _data#0; GVAR(dllVersion) = _ver; @@ -24,41 +24,41 @@ addMissionEventHandler ["ExtensionCallback", { INFO_1("Extension version: %1",str _ver); }; - if (_function isEqualTo ":GETDIR:ARMA:") exitWith { + if (_function isEqualTo ":SYS:DIR:ARMA:") exitWith { // arma dir return is automatic during extension init process private _dir = _data#0; GVAR(armaDir) = _dir; INFO_1("Arma directory: %1",_dir); }; - if (_function isEqualTo ":GETDIR:MODULE:") exitWith { + if (_function isEqualTo ":SYS:DIR:MODULE:") exitWith { // module dir return is automatic during extension init process private _dir = _data#0; GVAR(addonDir) = _dir; INFO_1("Addon directory: %1",_dir); }; - if (_function isEqualTo ":GETDIR:OCAPLOG:") exitWith { + if (_function isEqualTo ":SYS:DIR:LOG:") exitWith { // logging dir return is automatic during extension init process private _dir = _data#0; GVAR(logPath) = _dir; INFO_1("Extension logging path: %1",_dir); }; - if (_function isEqualTo ":EXT:READY:") exitWith { + if (_function isEqualTo ":SYS:READY:") exitWith { INFO("Extension ready."); // extension is ready, send version - [":ADDON:VERSION:", [QUOTE(VERSION_STR)], 'ocap_recorder'] call FUNC(sendData); + [":SYS:ADDON_VERSION:", [QUOTE(VERSION_STR)], 'ocap_recorder'] call FUNC(sendData); // get arma dir and module dir - [":GETDIR:ARMA:", [], 'ocap_recorder'] call FUNC(sendData); - [":GETDIR:MODULE:", [], 'ocap_recorder'] call FUNC(sendData); + [":SYS:DIR:ARMA:", [], 'ocap_recorder'] call FUNC(sendData); + [":SYS:DIR:MODULE:", [], 'ocap_recorder'] call FUNC(sendData); // get logging dir - [":GETDIR:OCAPLOG:", [], 'ocap_recorder'] call FUNC(sendData); + [":SYS:DIR:LOG:", [], 'ocap_recorder'] call FUNC(sendData); INFO("Initializing storage..."); - [":INIT:STORAGE:", [], 'ocap_recorder'] call FUNC(sendData); + [":STORAGE:INIT:", [], 'ocap_recorder'] call FUNC(sendData); }; @@ -146,7 +146,7 @@ addMissionEventHandler ["ExtensionCallback", { // Save mission and world context INFO("Saving mission and world context"); TRACE_2("World and mission context",GVAR(worldContext),GVAR(missionContext)); - [":NEW:MISSION:", [GVAR(worldContext), GVAR(missionContext)], 'ocap_recorder'] call FUNC(sendData); + [":MISSION:START:", [GVAR(worldContext), GVAR(missionContext)], 'ocap_recorder'] call FUNC(sendData); }; if (_function isEqualTo ":MISSION:OK:") exitWith { @@ -159,5 +159,5 @@ addMissionEventHandler ["ExtensionCallback", { INFO("Initializing extension..."); GVAR(initTimer) = diag_tickTime; -[":INIT:", []] call FUNC(sendData); +[":SYS:INIT:", []] call FUNC(sendData); true diff --git a/addons/extension/fnc_newMission.sqf b/addons/extension/fnc_newMission.sqf index 5d6e44b..3734ded 100644 --- a/addons/extension/fnc_newMission.sqf +++ b/addons/extension/fnc_newMission.sqf @@ -34,4 +34,4 @@ if (isNil QGVAR(worldContext) || isNil QGVAR(missionContext)) exitWith { INFO("Re-registering new mission with extension"); GVAR(initTimer) = diag_tickTime; -[":NEW:MISSION:", [GVAR(worldContext), GVAR(missionContext)], 'ocap_recorder'] call FUNC(sendData); +[":MISSION:START:", [GVAR(worldContext), GVAR(missionContext)], 'ocap_recorder'] call FUNC(sendData); diff --git a/addons/main/script_macros.hpp b/addons/main/script_macros.hpp index 4c6752c..6e4b7c2 100644 --- a/addons/main/script_macros.hpp +++ b/addons/main/script_macros.hpp @@ -21,7 +21,7 @@ // MACRO: LOG // Used for logging messages to the extension (ocap-ext log file). -#define OCAPEXTLOG(_args) [":LOG:", _args] call EFUNC(extension,sendData) +#define OCAPEXTLOG(_args) [":SYS:LOG:", _args] call EFUNC(extension,sendData) // MACRO: SYSCHAT // Used for debug purposes to send a string to all clients with interfaces. diff --git a/addons/recorder/fnc_aceExplosives.sqf b/addons/recorder/fnc_aceExplosives.sqf index 465cb2a..3e41427 100644 --- a/addons/recorder/fnc_aceExplosives.sqf +++ b/addons/recorder/fnc_aceExplosives.sqf @@ -5,7 +5,7 @@ FUNCTION: OCAP_recorder_fnc_aceExplosives Description: Integrates ACE3-placed explosives into the placed object pipeline. - Sends :NEW:PLACED: data and attaches lifecycle EHs (HitExplosion, Explode, + Sends :PLACED:CREATE: data and attaches lifecycle EHs (HitExplosion, Explode, Deleted) identical to vanilla mines in fnc_eh_fired_client.sqf. Called by CBA listener. @@ -50,7 +50,7 @@ if (_unitOcapId isEqualTo -1) exitWith {}; _explosive setVariable [QGVARMAIN(detonated), false]; -// Build :NEW:PLACED: data — same format as vanilla mines in fnc_eh_fired_client.sqf +// Build :PLACED:CREATE: data — same format as vanilla mines in fnc_eh_fired_client.sqf private _placedData = [ EGVAR(recorder,captureFrameNo), // 0: captureFrameNo -1, // 1: placedId (assigned by server) diff --git a/addons/recorder/fnc_captureLoop.sqf b/addons/recorder/fnc_captureLoop.sqf index 972582d..2825aa5 100644 --- a/addons/recorder/fnc_captureLoop.sqf +++ b/addons/recorder/fnc_captureLoop.sqf @@ -112,7 +112,7 @@ GVAR(PFHObject) = [ [ {missionNamespace getVariable [QEGVAR(extension,sessionReady), false]}, - {[":NEW:SOLDIER:", _this] call EFUNC(extension,sendData);}, + {[":SOLDIER:CREATE:", _this] call EFUNC(extension,sendData);}, _newUnit, 30 ] call CBA_fnc_waitUntilAndExecute; @@ -168,7 +168,7 @@ GVAR(PFHObject) = [ ]; if (_x getVariable ["unitData", []] isNotEqualTo _unitData) then { - [":NEW:SOLDIER:STATE:", _unitData] call EFUNC(extension,sendData); + [":SOLDIER:STATE:", _unitData] call EFUNC(extension,sendData); _x setVariable [QGVARMAIN(unitData), _unitData]; }; }; @@ -217,7 +217,7 @@ GVAR(PFHObject) = [ [ {missionNamespace getVariable [QEGVAR(extension,sessionReady), false]}, - {[":NEW:VEHICLE:", _this] call EFUNC(extension,sendData);}, + {[":VEHICLE:CREATE:", _this] call EFUNC(extension,sendData);}, _newVehicleData, 30 ] call CBA_fnc_waitUntilAndExecute; @@ -260,11 +260,11 @@ GVAR(PFHObject) = [ // Stop tracking parachutes/ejection seats that are empty or dead if ((_x getVariable [QGVARMAIN(vehicleClass), ""]) isEqualTo "parachute" && {!((alive _x) && {_crew isNotEqualTo []})}) then { _vehicleData set [3, 0]; - [":NEW:VEHICLE:STATE:", _vehicleData] call EFUNC(extension,sendData); + [":VEHICLE:STATE:", _vehicleData] call EFUNC(extension,sendData); _x setVariable [QGVARMAIN(exclude), true, true]; GVAR(trackedVehicles) deleteAt _ocapId; } else { - [":NEW:VEHICLE:STATE:", _vehicleData] call EFUNC(extension,sendData); + [":VEHICLE:STATE:", _vehicleData] call EFUNC(extension,sendData); GVAR(trackedVehicles) set [_ocapId, [_x, _pos, round getDir _x, side _x, vectorDir _x, vectorUp _x]]; }; }; @@ -276,7 +276,7 @@ GVAR(PFHObject) = [ { (GVAR(trackedVehicles) get _x) params ["_obj", "_lastPos", "_lastDir", "_lastSide", "_lastVectorDir", "_lastVectorUp"]; if (isNull _obj) then { - [":NEW:VEHICLE:STATE:", [ + [":VEHICLE:STATE:", [ _x, _lastPos, _lastDir, 0, [], GVAR(captureFrameNo), 0, 1, false, false, _lastSide, _lastVectorDir, _lastVectorUp, 0, 0 ]] call EFUNC(extension,sendData); diff --git a/addons/recorder/fnc_eh_connected.sqf b/addons/recorder/fnc_eh_connected.sqf index 89a079a..a0e8210 100644 --- a/addons/recorder/fnc_eh_connected.sqf +++ b/addons/recorder/fnc_eh_connected.sqf @@ -32,7 +32,7 @@ params ["_id", "_uid", "_name", "_jip", "_owner", "_idstr"]; if (_owner isEqualTo 2) exitWith {}; // log to timeline -[":EVENT:", [ +[":EVENT:GENERAL:", [ GVAR(captureFrameNo), "connected", _name, diff --git a/addons/recorder/fnc_eh_disconnected.sqf b/addons/recorder/fnc_eh_disconnected.sqf index 94df879..842bb6e 100644 --- a/addons/recorder/fnc_eh_disconnected.sqf +++ b/addons/recorder/fnc_eh_disconnected.sqf @@ -27,7 +27,7 @@ params ["_unit", "_id", "_uid", "_name"]; -[":EVENT:", [ +[":EVENT:GENERAL:", [ GVAR(captureFrameNo), "disconnected", _name, diff --git a/addons/recorder/fnc_eh_fired_client.sqf b/addons/recorder/fnc_eh_fired_client.sqf index 46fee20..ac0ae94 100644 --- a/addons/recorder/fnc_eh_fired_client.sqf +++ b/addons/recorder/fnc_eh_fired_client.sqf @@ -113,7 +113,7 @@ _projectile setVariable [QGVARMAIN(projectileData), _data]; if (_weapon == "put") then { _projectile setVariable [QGVARMAIN(detonated), false]; - // Build :NEW:PLACED: data — placedId assigned server-side (GVAR(nextId) only exists there) + // Build :PLACED:CREATE: data — placedId assigned server-side (GVAR(nextId) only exists there) private _placedData = [ EGVAR(recorder,captureFrameNo), // 0: captureFrameNo -1, // 1: placedId (assigned by server) diff --git a/addons/recorder/fnc_eh_fired_server.sqf b/addons/recorder/fnc_eh_fired_server.sqf index b45727c..78d4773 100644 --- a/addons/recorder/fnc_eh_fired_server.sqf +++ b/addons/recorder/fnc_eh_fired_server.sqf @@ -127,7 +127,7 @@ TRACE_1("Sending fired data to extension",_data); _data spawn { sleep 2; - [":PROJECTILE:", _this] call EFUNC(extension,sendData); + [":EVENT:PROJECTILE:", _this] call EFUNC(extension,sendData); }; }] call CBA_fnc_addEventHandler; @@ -140,7 +140,7 @@ _data set [1, _placedId]; _projectile setVariable [QGVARMAIN(placedId), _placedId, true]; TRACE_2("Sending placed object data to extension",_placedId,_data); - [":NEW:PLACED:", _data] call EFUNC(extension,sendData); + [":PLACED:CREATE:", _data] call EFUNC(extension,sendData); }] call CBA_fnc_addEventHandler; // Handle placed object lifecycle events (detonation, deletion) diff --git a/addons/recorder/fnc_eh_killed.sqf b/addons/recorder/fnc_eh_killed.sqf index 114cbe3..2b5c92c 100644 --- a/addons/recorder/fnc_eh_killed.sqf +++ b/addons/recorder/fnc_eh_killed.sqf @@ -98,7 +98,7 @@ if !(_victim getvariable [QGVARMAIN(isKilled),false]) then { OCAPEXTLOG(ARR4("KILLED EVENT",_killedFrame,_victimId,_killerId)); }; - [":KILL:", [ + [":EVENT:KILL:", [ _killedFrame, _victimId, _killerId, diff --git a/addons/recorder/fnc_exportData.sqf b/addons/recorder/fnc_exportData.sqf index 57f89b9..41cc991 100644 --- a/addons/recorder/fnc_exportData.sqf +++ b/addons/recorder/fnc_exportData.sqf @@ -114,7 +114,7 @@ if (!isNil QGVAR(PFHObject)) then { private _winSide = if (isNil "_side") then {""} else {if (_side isEqualTo sideUnknown) then {""} else {str _side}}; private _endMessage = if (isNil "_message") then {if (_winSide == "") then {"Mission ended"} else {""}} else {_message}; -[":EVENT:", [ +[":EVENT:GENERAL:", [ _endFrameNumber, "endMission", "", @@ -126,7 +126,7 @@ private _endMessage = if (isNil "_message") then {if (_winSide == "") then {"Mis private _saveTag = if (!isNil "_tag") then {_tag} else {EGVAR(settings,saveTag)}; -[":SAVE:MISSION:", [worldName, GVAR(missionName), getMissionConfigValue ["author", ""], GVAR(frameCaptureDelay), _endFrameNumber, _saveTag]] call EFUNC(extension,sendData); +[":MISSION:SAVE:", [worldName, GVAR(missionName), getMissionConfigValue ["author", ""], GVAR(frameCaptureDelay), _endFrameNumber, _saveTag]] call EFUNC(extension,sendData); OCAPEXTLOG(ARR4("Saved recording of mission",GVAR(missionName),"with tag",_saveTag)); diff --git a/addons/recorder/fnc_handleChatMessage.sqf b/addons/recorder/fnc_handleChatMessage.sqf index cc941f6..db49f80 100644 --- a/addons/recorder/fnc_handleChatMessage.sqf +++ b/addons/recorder/fnc_handleChatMessage.sqf @@ -12,7 +12,7 @@ if (parseNumber _strID > 1) then { private _senderOcapId = _person getVariable [QGVARMAIN(id), -1]; -[":CHAT:", [ +[":EVENT:CHAT:", [ GVAR(captureFrameNo), _senderOcapId, _channel, diff --git a/addons/recorder/fnc_handleCustomEvent.sqf b/addons/recorder/fnc_handleCustomEvent.sqf index 5b617f9..cccbd4c 100644 --- a/addons/recorder/fnc_handleCustomEvent.sqf +++ b/addons/recorder/fnc_handleCustomEvent.sqf @@ -61,7 +61,7 @@ params [ ["_extraData", createHashMap, [createHashMap, []]] ]; -[":EVENT:", [ +[":EVENT:GENERAL:", [ GVAR(captureFrameNo), _eventName, _eventMessage, diff --git a/addons/recorder/fnc_handleMarkers.sqf b/addons/recorder/fnc_handleMarkers.sqf index 550f186..2df79ab 100644 --- a/addons/recorder/fnc_handleMarkers.sqf +++ b/addons/recorder/fnc_handleMarkers.sqf @@ -128,14 +128,14 @@ EGVAR(listener,markers) = [QGVARMAIN(handleMarker), { private _logParams = (str [_mrk_name, _dir, _type, _text, _captureFrameNo, -1, _mrk_owner, _mrk_color, _size, _sideOfMarker, _pos, _shape, _alpha, _brush]); - [":NEW:MARKER:", [_mrk_name, _dir, _type, _text, _captureFrameNo, -1, _mrk_owner, _mrk_color, _size, _sideOfMarker, _pos, _shape, _alpha, _brush]] call EFUNC(extension,sendData); + [":MARKER:CREATE:", [_mrk_name, _dir, _type, _text, _captureFrameNo, -1, _mrk_owner, _mrk_color, _size, _sideOfMarker, _pos, _shape, _alpha, _brush]] call EFUNC(extension,sendData); }; case "UPDATED":{ if (_mrk_name in GVAR(trackedMarkers)) then { if (isNil "_dir") then {_dir = 0}; - [":NEW:MARKER:STATE:", [_mrk_name, GVAR(captureFrameNo), _pos, _dir, _alpha]] call EFUNC(extension,sendData); + [":MARKER:STATE:", [_mrk_name, GVAR(captureFrameNo), _pos, _dir, _alpha]] call EFUNC(extension,sendData); }; }; @@ -148,7 +148,7 @@ EGVAR(listener,markers) = [QGVARMAIN(handleMarker), { OCAPEXTLOG(ARR3("MARKER:DELETE: Marker",_mrk_name,"deleted")); }; - [":DELETE:MARKER:", [_mrk_name, GVAR(captureFrameNo)]] call EFUNC(extension,sendData); + [":MARKER:DELETE:", [_mrk_name, GVAR(captureFrameNo)]] call EFUNC(extension,sendData); GVAR(trackedMarkers) = GVAR(trackedMarkers) - [_mrk_name]; }; }; diff --git a/addons/recorder/fnc_init.sqf b/addons/recorder/fnc_init.sqf index f815aa8..0242eef 100644 --- a/addons/recorder/fnc_init.sqf +++ b/addons/recorder/fnc_init.sqf @@ -91,7 +91,7 @@ publicVariable QGVARMAIN(version); Global variable that represents the version of OCAP extension being used [String] */ diag_log text "[OCAP] Fetching extension version..."; -EGVAR(extension,version) = ([":VERSION:", []] call EFUNC(extension,sendData)); +EGVAR(extension,version) = ([":SYS:VERSION:", []] call EFUNC(extension,sendData)); diag_log text format ["[OCAP] Extension version result: %1 (type: %2)", EGVAR(extension,version), typeName EGVAR(extension,version)]; publicVariable QEGVAR(extension,version); diff --git a/addons/recorder/fnc_radioEvent.sqf b/addons/recorder/fnc_radioEvent.sqf index 813a909..ef8dae8 100644 --- a/addons/recorder/fnc_radioEvent.sqf +++ b/addons/recorder/fnc_radioEvent.sqf @@ -30,7 +30,7 @@ if (_mod isEqualTo "TFAR") then { ) exitWith {}; [ - ":RADIO:", [ + ":EVENT:RADIO:", [ GVAR(captureFrameNo), _ocapId, _radio, @@ -64,7 +64,7 @@ if (_mod isEqualTo "ACRE") then { ) exitWith {}; [ - ":RADIO:", [ + ":EVENT:RADIO:", [ GVAR(captureFrameNo), _ocapId, _radio, diff --git a/addons/recorder/fnc_telemetryLoop.sqf b/addons/recorder/fnc_telemetryLoop.sqf index b73776b..aad9485 100644 --- a/addons/recorder/fnc_telemetryLoop.sqf +++ b/addons/recorder/fnc_telemetryLoop.sqf @@ -7,7 +7,7 @@ FUNCTION: OCAP_recorder_fnc_telemetryLoop Description: Collects server telemetry data every 10 seconds and sends a single - :TELEMETRY: command to the extension. The extension handles routing + :TELEMETRY:FRAME: command to the extension. The extension handles routing to mission recording (FPS) and InfluxDB (all metrics). Parameters: @@ -102,7 +102,7 @@ Author: } forEach (allUsers apply {getUserInfo _x}); // Single telemetry call — extension handles routing and formatting - [":TELEMETRY:", [ + [":TELEMETRY:FRAME:", [ GVAR(captureFrameNo), [diag_fps, diag_fpsmin], _sideData, diff --git a/addons/recorder/fnc_updateTime.sqf b/addons/recorder/fnc_updateTime.sqf index 3a2d7f6..2c72b82 100644 --- a/addons/recorder/fnc_updateTime.sqf +++ b/addons/recorder/fnc_updateTime.sqf @@ -35,7 +35,7 @@ if (_date isEqualTo []) then { }; _missionDateFormat append (_date apply {if (_x < 10) then {"0" + str _x} else {str _x}}); -[":NEW:TIME:STATE:", [ +[":TIME:STATE:", [ GVAR(captureFrameNo), format _systemTimeFormat, format _missionDateFormat,