Skip to content

Commit 13774b7

Browse files
authored
fix: detect entity deletion by Zeus and scripts via null tracking (#109)
The dedup optimization (commits 83/84) combined with extension gap-fill caused Zeus-deleted entities to persist in recordings. Without an explicit DELETE command, gap-fill extends the last alive state to the end of the recording. Units: add trackedUnits HashMap mirroring trackedVehicles. Each frame, check for null object handles and send :SOLDIER:DELETE: when detected. Remove from HashMap on disconnect/respawn to avoid duplicate DELETEs. Vehicles: the existing isNull detection sent a final dead state but no :VEHICLE:DELETE:, so gap-fill had no boundary. Now sends DELETE after the dead state. Catches all deletion sources: Zeus, deleteVehicle, garbage collection.
1 parent 4acbb25 commit 13774b7

3 files changed

Lines changed: 25 additions & 0 deletions

File tree

addons/recorder/fnc_addEventMission.sqf

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ if (isNil QEGVAR(EH,EntityRespawned)) then {
8080
GVAR(captureFrameNo)
8181
]] call EFUNC(extension,sendData);
8282
_corpse setVariable [QGVARMAIN(exclude), true];
83+
if (!isNil QGVAR(trackedUnits)) then {
84+
GVAR(trackedUnits) deleteAt (_corpse getVariable [QGVARMAIN(id), -1]);
85+
};
8386
};
8487

8588
[_entity, true] spawn FUNC(addUnitEventHandlers);

addons/recorder/fnc_captureLoop.sqf

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ if (isNil QGVAR(startTime)) then {
4141
};
4242

4343
GVAR(trackedVehicles) = createHashMap;
44+
GVAR(trackedUnits) = createHashMap;
4445

4546
// Pre-compute frame intervals that depend on frameCaptureDelay (constant for the mission)
4647
// Must be GVARs, not private — PFH code runs in a different scope.
@@ -120,6 +121,7 @@ GVAR(PFHObject) = [
120121
[_x] spawn FUNC(addUnitEventHandlers);
121122
GVAR(nextId) = GVAR(nextId) + 1;
122123
_x setVariable [QGVARMAIN(isInitialized), true, true];
124+
GVAR(trackedUnits) set [_x getVariable [QGVARMAIN(id), -1], _x];
123125
_justInitialized = true;
124126
};
125127
// Re-include units that have become player-controlled again (e.g., reconnected players)
@@ -186,6 +188,19 @@ GVAR(PFHObject) = [
186188
};
187189
} forEach (allUnits + allDeadMen);
188190

191+
// Detect disappeared units (deleted/garbage-collected) and report removal
192+
private _toRemoveUnits = [];
193+
{
194+
if (isNull _y) then {
195+
[":SOLDIER:DELETE:", [
196+
_x,
197+
GVAR(captureFrameNo)
198+
]] call EFUNC(extension,sendData);
199+
_toRemoveUnits pushBack _x;
200+
};
201+
} forEach GVAR(trackedUnits);
202+
{ GVAR(trackedUnits) deleteAt _x } forEach _toRemoveUnits;
203+
189204
{
190205
private _justInitialized = false;
191206
if !(_x getVariable [QGVARMAIN(isInitialized), false]) then {
@@ -305,6 +320,10 @@ GVAR(PFHObject) = [
305320
_x, _lastPos, _lastDir, 0, [], GVAR(captureFrameNo),
306321
0, 1, false, false, _lastSide, _lastVectorDir, _lastVectorUp, 0, 0
307322
]] call EFUNC(extension,sendData);
323+
[":VEHICLE:DELETE:", [
324+
_x,
325+
GVAR(captureFrameNo)
326+
]] call EFUNC(extension,sendData);
308327
_toRemove pushBack _x;
309328
};
310329
} forEach (keys GVAR(trackedVehicles));

addons/recorder/fnc_eh_disconnected.sqf

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ if (_unit getVariable [QGVARMAIN(isInitialized), false]) then {
4242
GVAR(captureFrameNo)
4343
]] call EFUNC(extension,sendData);
4444
_unit setVariable [QGVARMAIN(exclude), true];
45+
if (!isNil QGVAR(trackedUnits)) then {
46+
GVAR(trackedUnits) deleteAt (_unit getVariable [QGVARMAIN(id), -1]);
47+
};
4548
};
4649

4750
// saveOnEmpty: if this was the last player, save immediately

0 commit comments

Comments
 (0)