Skip to content

fix(ace): gate ACE explosives placement on locality#117

Merged
fank merged 4 commits into
mainfrom
fix/ace-explosives-position-on-dedicated
May 12, 2026
Merged

fix(ace): gate ACE explosives placement on locality#117
fank merged 4 commits into
mainfrom
fix/ace-explosives-position-on-dedicated

Conversation

@fank
Copy link
Copy Markdown
Member

@fank fank commented May 12, 2026

Summary

  • ACE-placed explosives have been recorded at the map origin (0,0,0) on dedicated servers.
  • Root cause: ace_explosives_place is a CBA global event, so the listener body ran on every machine. On a dedicated server the explosive's position is not yet network-synced when the event fires — getPosASL returns 0,0,~0. The placer's client has the correct position immediately.
  • Fix: gate execution on local _explosive so only the placer (which owns the object with the authoritative position) packages the data and forwards it via CBA_fnc_serverEvent. Same pattern as the vanilla mine path in fnc_eh_fired_client.sqf.

Test plan

  • Dedicated server: place an ACE explosive, confirm :PLACED:CREATE: arrives with the real position (not 0,0,...).
  • Hosted/SP: place an ACE explosive, confirm recording still captures it.
  • Detonate/delete an existing ACE charge, confirm :PLACED:EVENT: detonated/deleted still fires (lifecycle EHs are added on the placer's machine, same machine that already ran them before this change).

ace_explosives_place is a CBA global event that fires on every machine.
On a dedicated server the explosive's position has not yet network-synced
when the event fires, so getPosASL returns 0,0,~0 and the recording shows
the charge at the map origin.

Gate the listener body on `local _explosive` so only the placer — who owns
the object with the authoritative position — packages and ships the data
via CBA_fnc_serverEvent. This matches the vanilla mine path in
fnc_eh_fired_client.sqf.
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a locality check in fnc_aceExplosives.sqf to ensure that only the machine where an explosive is local processes the placement event, preventing incorrect position data (0,0,0) on dedicated servers. The reviewer noted that gating the entire function prevents lifecycle event handlers from being registered on other machines, which could lead to lost tracking if the object's locality changes (e.g., due to a player disconnect). It is recommended to restrict the locality check to the data transmission logic while allowing event handler registration to proceed globally.

Comment thread addons/recorder/fnc_aceExplosives.sqf Outdated
Per review feedback: addEventHandler is local, so registering EHs only on
the placer means tracking breaks if locality transfers (e.g. placer
disconnect). Move the locality check to gate just the :PLACED:CREATE:
send — EH registration now happens on every machine, and whichever one
owns the object at event-time fires its local EH.
@fank
Copy link
Copy Markdown
Member Author

fank commented May 12, 2026

Addressed in ba2e734 — moved the locality check to gate only the :PLACED:CREATE: data send. The HitExplosion/Explode/Deleted EHs now register on every machine, so whichever machine owns the explosive at event-time fires its local EH. Order of operations: EHs registered first → server processes handlePlacedData and broadcasts the placedId via public setVariable → lifecycle EHs find it when they fire.

Locality check on the placer was wrong: ace_explosives_place fires before
the explosive's position has synced on the server (getPosASL returns
0,0,~0 immediately, correct after ~1s), and OCAP_recorder_captureFrameNo
only exists on the server, so a client-side send produced no valid
:PLACED:CREATE: at all.

Send from the server, delayed by 1s via CBA_fnc_waitAndExecute. This
matches the empirical timing the user reported. Lifecycle EHs remain
registered on every machine so locality transfers don't lose tracking.
@fank
Copy link
Copy Markdown
Member Author

fank commented May 12, 2026

Reworked in 327d7ca. The locality fix was wrong — the log showed no :PLACED:CREATE: arrived at all, but the Deleted event came through with a valid frame number, which only the server has (OCAP_recorder_captureFrameNo is set by the server-only captureLoop). So local _explosive is true on the server, not the placer — and a client send wouldn't have worked anyway because captureFrameNo is nil there.

New approach: send from the server with a 1s CBA_fnc_waitAndExecute delay, matching the empirical timing ("server after delaying 1 second shows coords correctly"). EH registration stays on every machine for locality-transfer resilience.

Caveat to flag: there's now a 1s window between placement and the :PLACED:CREATE: send. If a charge detonates within that window (rare for satchels, possible for tripwires/IEDs), the lifecycle EH will fire with placedId = -1 since the server hasn't assigned it yet. The previous code had the same race in theory; with the delay it's now a guaranteed minimum window. If that becomes an issue we can buffer lifecycle events until placedId is assigned, but I'd treat that as a follow-up.

Drop the incorrect rationale about captureFrameNo being server-only;
clients receive it via publicVariable. The reason for the server-side
delayed send is simpler: getPosASL needs ~1s on the server to reflect
the settled position after ace_explosives_place fires.
@fank
Copy link
Copy Markdown
Member Author

fank commented May 12, 2026

Correction: you're right, captureFrameNo is publicVariabled (fnc_captureLoop.sqf:60, fnc_init.sqf:49, fnc_exportData.sqf:162) and clients use it directly in the vanilla fired-client paths. My earlier rationale for why the locality-on-placer fix produced no :PLACED:CREATE: was wrong.

What we actually know empirically: with if (!local _explosive) exitWith {}; no send arrived. We don't actually have proof of where locality was true — frame=64 on the Deleted event doesn't pin it down.

The server-only + 1s delay fix still stands on the simpler grounds you originally flagged: getPosASL on the server needs ~1s to reflect the settled position. Cleaned up the misleading comment in 0c9eeb9.

@fank fank merged commit eefa6f7 into main May 12, 2026
1 check passed
@fank fank deleted the fix/ace-explosives-position-on-dedicated branch May 12, 2026 10:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant