Skip to content

Commit 0ca24cb

Browse files
authored
Refactor projectile tracking to use lightweight array format (#43)
- Replace hashmap with flat positional array for projectile data - Remove JSON encoding overhead when sending to extension - Replace non-existent :TIMESTAMP: extension calls with diag_tickTime - Rename variable from dataHash to projectileData This reduces per-projectile data size and eliminates unnecessary encoding/decoding overhead for high-frequency fired events. Array structure documented in fnc_eh_fired_client.sqf with indices 0-18.
1 parent 15c707b commit 0ca24cb

3 files changed

Lines changed: 102 additions & 85 deletions

File tree

addons/database/fnc_eh_fired_client.sqf

Lines changed: 53 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -54,42 +54,50 @@ if (_muzzleDisplay isEqualTo "") then {
5454
_muzzleDisplay = getText(configFile >> "CfgWeapons" >> _weapon >> "displayName");
5555
};
5656

57-
58-
// set variables
59-
// firedAt: refers to timing, i.e. frame number and unixNano timestamp
60-
// firedBy: shooter info
61-
// positions: each registered point of the projectile's path
62-
// firedWith: weapon and ammo info
63-
_projectile setVariable [QGVARMAIN(dataHash), createHashMapFromArray [
64-
["firedFrame", EGVAR(recorder,captureFrameNo)],
65-
["firedTime", [":TIMESTAMP:", []] call EFUNC(extension,sendData)],
66-
["firerID", _firerOcapId],
67-
["vehicleID", _vehicleOcapId],
68-
["vehicleRole", _vehicleRole],
69-
["remoteControllerID", _remoteControllerOcapId],
70-
["weapon", _weapon],
71-
["weaponDisplay", getText(configFile >> "CfgWeapons" >> _weapon >> "displayName")],
72-
["muzzle", _muzzle],
73-
["muzzleDisplay", _muzzleDisplay],
74-
["magazine", _magazine],
75-
["magazineDisplay", getText(configFile >> "CfgMagazines" >> _magazine >> "displayName")],
76-
["ammo", _ammo],
77-
["fireMode", _mode],
78-
["positions", [
79-
[
80-
[":TIMESTAMP:", []] call EFUNC(extension,sendData),
81-
EGVAR(recorder,captureFrameNo),
82-
(getPosASL _projectile) joinString ","
83-
]
84-
]],
85-
["initialVelocity",
86-
(velocity _projectile) joinString ","
87-
],
88-
["hitParts", []],
89-
["sim", getText(configFile >> "CfgAmmo" >> _ammo >> "simulation")],
90-
["isSub", false]
91-
]];
92-
57+
// Projectile data array structure:
58+
// 0: firedFrame
59+
// 1: firedTime (diag_tickTime)
60+
// 2: firerID
61+
// 3: vehicleID
62+
// 4: vehicleRole
63+
// 5: remoteControllerID
64+
// 6: weapon
65+
// 7: weaponDisplay
66+
// 8: muzzle
67+
// 9: muzzleDisplay
68+
// 10: magazine
69+
// 11: magazineDisplay
70+
// 12: ammo
71+
// 13: fireMode
72+
// 14: positions [[tickTime, frame, "x,y,z"], ...]
73+
// 15: initialVelocity
74+
// 16: hitParts [[hitOcapId, component, "x,y,z", frame], ...]
75+
// 17: sim
76+
// 18: isSub
77+
78+
private _data = [
79+
EGVAR(recorder,captureFrameNo), // 0: firedFrame
80+
diag_tickTime, // 1: firedTime
81+
_firerOcapId, // 2: firerID
82+
_vehicleOcapId, // 3: vehicleID
83+
_vehicleRole, // 4: vehicleRole
84+
_remoteControllerOcapId, // 5: remoteControllerID
85+
_weapon, // 6: weapon
86+
getText(configFile >> "CfgWeapons" >> _weapon >> "displayName"), // 7: weaponDisplay
87+
_muzzle, // 8: muzzle
88+
_muzzleDisplay, // 9: muzzleDisplay
89+
_magazine, // 10: magazine
90+
getText(configFile >> "CfgMagazines" >> _magazine >> "displayName"), // 11: magazineDisplay
91+
_ammo, // 12: ammo
92+
_mode, // 13: fireMode
93+
[[diag_tickTime, EGVAR(recorder,captureFrameNo), (getPosASL _projectile) joinString ","]], // 14: positions
94+
(velocity _projectile) joinString ",", // 15: initialVelocity
95+
[], // 16: hitParts
96+
getText(configFile >> "CfgAmmo" >> _ammo >> "simulation"), // 17: sim
97+
false // 18: isSub
98+
];
99+
100+
_projectile setVariable [QGVARMAIN(projectileData), _data];
93101

94102
// the simulation type of this ammo will determine how we handle it.
95103
// "ShotGrenade" // M67
@@ -103,17 +111,17 @@ _projectile setVariable [QGVARMAIN(dataHash), createHashMapFromArray [
103111
// "ShotSubmunition" // Hind minigun, cluster artillery
104112

105113
// carryover variables to submunitions
106-
if (getText(configFile >> "CfgAmmo" >> _ammo >> "simulation") isEqualTo "ShotSubmunition") then {
114+
if ((_data select 17) isEqualTo "ShotSubmunition") then {
107115
_projectile addEventHandler ["SubmunitionCreated", {
108116
params ["_projectile", "_submunitionProjectile"];
109-
_submunitionProjectile setVariable [QGVARMAIN(dataHash), _projectile getVariable QGVARMAIN(dataHash)];
110-
private _hash = _submunitionProjectile getVariable QGVARMAIN(dataHash);
111-
_hash set ["isSub", true];
112-
(_hash get "positions") pushBack [
113-
[":TIMESTAMP:", []] call EFUNC(extension,sendData),
114-
EGVAR(recorder,captureFrameNo),
115-
getPosASL _submunitionProjectile
116-
];
117+
private _data = +(_projectile getVariable QGVARMAIN(projectileData));
118+
_data set [18, true]; // isSub = true
119+
(_data select 14) pushBack [
120+
diag_tickTime,
121+
EGVAR(recorder,captureFrameNo),
122+
(getPosASL _submunitionProjectile) joinString ","
123+
];
124+
_submunitionProjectile setVariable [QGVARMAIN(projectileData), _data];
117125
// add the rest of EHs to submunition
118126
[_submunitionProjectile] call FUNCMAIN(addBulletEH);
119127
}];

addons/database/fnc_eh_fired_clientBullet.sqf

Lines changed: 44 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,18 @@ if (isNil "_projectile") exitWith {
77
WARNING("Projectile EHs: _projectile is nil");
88
};
99

10+
// Projectile data array indices:
11+
// 14: positions
12+
// 16: hitParts
13+
// 17: sim
14+
// 18: isSub
15+
1016
// first, we need to verify simtype & whether this was a submunition or not.
1117
// if this is NOT a deployed submunition itself but the simType of the ammo is "ShotSubmunition", then we need to skip the Deleted EH and leave the Deleted registration to the submunition itself. This will ensure we're tracking start to finish multiple actual projectiles from things like shotguns, cluster artillery, mixed-belt machineguns, etc.
12-
private _hash = _projectile getVariable QGVARMAIN(dataHash);
18+
private _data = _projectile getVariable QGVARMAIN(projectileData);
1319
if (
14-
_hash get "sim" isEqualTo "ShotSubmunition" &&
15-
{_hash get "isSub" isEqualTo false}
20+
(_data select 17) isEqualTo "ShotSubmunition" &&
21+
{(_data select 18) isEqualTo false}
1622
) exitWith {};
1723

1824
// HitExplosion
@@ -31,24 +37,25 @@ _projectile addEventHandler ["HitExplosion", {
3137
// skip if no components were hit
3238
if (count _hitThings isEqualTo 0) exitWith {};
3339

40+
private _data = _projectile getVariable QGVARMAIN(projectileData);
3441

3542
// many hit components for these events, so we'll sort them by radius (_x#3) largest to smallest and keep the top 5
3643
private _hitThings = _hitThings apply {[_x#3, _x#2]};
3744
_hitThings sort true;
3845
_hitThings = _hitThings select [0, 5 min (count _hitThings)];
3946
// add data, _x#1 will be the component name
40-
((_projectile getVariable QGVARMAIN(dataHash)) get "hitParts") pushBack [
47+
(_data select 16) pushBack [
4148
_hitOcapId,
4249
_hitThings apply {_x#1},
4350
(getPosASL _projectile) joinString ",",
4451
EGVAR(recorder,captureFrameNo)
4552
];
4653
// add pos
47-
((_projectile getVariable QGVARMAIN(dataHash)) get "positions") pushBack [
48-
[":TIMESTAMP:", []] call EFUNC(extension,sendData),
49-
EGVAR(recorder,captureFrameNo),
50-
(getPosASL _projectile) joinString ","
51-
];
54+
(_data select 14) pushBack [
55+
diag_tickTime,
56+
EGVAR(recorder,captureFrameNo),
57+
(getPosASL _projectile) joinString ","
58+
];
5259
}];
5360

5461
// HitPart
@@ -67,19 +74,21 @@ _projectile addEventHandler ["HitPart", {
6774
// skip if no components were hit
6875
if (count _hitThings isEqualTo 0) exitWith {};
6976

77+
private _data = _projectile getVariable QGVARMAIN(projectileData);
78+
7079
// add hit data
71-
((_projectile getVariable QGVARMAIN(dataHash)) get "hitParts") pushBack [
80+
(_data select 16) pushBack [
7281
_hitOcapId,
7382
_component,
7483
(getPosASL _projectile) joinString ",",
7584
EGVAR(recorder,captureFrameNo)
7685
];
7786
// add pos
78-
((_projectile getVariable QGVARMAIN(dataHash)) get "positions") pushBack [
79-
[":TIMESTAMP:", []] call EFUNC(extension,sendData),
80-
EGVAR(recorder,captureFrameNo),
81-
_pos joinString ","
82-
];
87+
(_data select 14) pushBack [
88+
diag_tickTime,
89+
EGVAR(recorder,captureFrameNo),
90+
_pos joinString ","
91+
];
8392
}];
8493

8594
// Deflected
@@ -88,12 +97,13 @@ _projectile addEventHandler ["Deflected", {
8897
params ["_projectile", "_pos", "_velocity", "_hitObject"];
8998
TRACE_4("Deflected",_projectile,_pos,_velocity,_hitObject);
9099

100+
private _data = _projectile getVariable QGVARMAIN(projectileData);
91101
// just log position
92-
((_projectile getVariable QGVARMAIN(dataHash)) get "positions") pushBack [
93-
[":TIMESTAMP:", []] call EFUNC(extension,sendData),
94-
EGVAR(recorder,captureFrameNo),
95-
_pos joinString ","
96-
];
102+
(_data select 14) pushBack [
103+
diag_tickTime,
104+
EGVAR(recorder,captureFrameNo),
105+
_pos joinString ","
106+
];
97107
}];
98108

99109
// END EHs
@@ -104,26 +114,27 @@ _projectile addEventHandler ["Explode", {
104114
params ["_projectile", "_pos", "_velocity"];
105115
TRACE_3("Explode",_projectile,_pos,_velocity);
106116

117+
private _data = _projectile getVariable QGVARMAIN(projectileData);
107118
// just log position
108-
((_projectile getVariable QGVARMAIN(dataHash)) get "positions") pushBack [
109-
[":TIMESTAMP:", []] call EFUNC(extension,sendData),
110-
EGVAR(recorder,captureFrameNo),
111-
_pos joinString ","
112-
];
119+
(_data select 14) pushBack [
120+
diag_tickTime,
121+
EGVAR(recorder,captureFrameNo),
122+
_pos joinString ","
123+
];
113124
}];
114125

115126
// Deleted
116127
// Tracks a projectile that was deleted, either by a script or by the game. The final processing call that'll send data to the server for processing.
117128
_projectile addEventHandler ["Deleted", {
118129
params ["_projectile"];
119-
private _hash = _projectile getVariable QGVARMAIN(dataHash);
120-
(_hash get "positions") pushBack [
121-
[":TIMESTAMP:", []] call EFUNC(extension,sendData),
122-
EGVAR(recorder,captureFrameNo),
123-
(getPosASL _projectile) joinString ","
124-
];
125-
TRACE_1("Projectile hash",_hash);
126-
[QGVARMAIN(handleFiredManData), [_hash]] call CBA_fnc_serverEvent;
130+
private _data = _projectile getVariable QGVARMAIN(projectileData);
131+
(_data select 14) pushBack [
132+
diag_tickTime,
133+
EGVAR(recorder,captureFrameNo),
134+
(getPosASL _projectile) joinString ","
135+
];
136+
TRACE_1("Projectile data",_data);
137+
[QGVARMAIN(handleFiredManData), [_data]] call CBA_fnc_serverEvent;
127138
}];
128139

129140
TRACE_1("Finished applying EH",_projectile);

addons/database/fnc_eh_fired_server.sqf

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,11 @@
7979

8080
// Finally, we'll add a CBA Event Handler to take in the pre-processed fired data here on the server and send it to the extension.
8181
[QGVARMAIN(handleFiredManData), {
82-
params ["_hash"];
83-
// Receive hashmap from server, hc, or client.
84-
// Try encoding JSON
85-
private _json = [_hash] call CBA_fnc_encodeJSON;
86-
TRACE_1("Sending fired data JSON to extension",_json);
87-
_json spawn {
82+
params ["_data"];
83+
// Receive array from server, hc, or client.
84+
TRACE_1("Sending fired data to extension",_data);
85+
_data spawn {
8886
sleep 2;
89-
[":PROJECTILE:", [_this]] call EFUNC(extension,sendData);
87+
[":PROJECTILE:", _this] call EFUNC(extension,sendData);
9088
};
9189
}] call CBA_fnc_addEventHandler;

0 commit comments

Comments
 (0)