Practical recipes
These short fragments supplement rather than replace the runnable example.
Duplicate events
Track processed shot_id values within a round. Clear the set for a new session and bound its size in long-running modes. A delivered callback does not prove that the game target remains active: check phase, pause and countdown.
Asynchronous handlers
Event handlers run synchronously. A callback starting asynchronous work must handle its own rejection. A synchronous listener exception becomes an error with code LISTENER; this does not replace a promise catch.
Disposal
on returns an unsubscribe function. Keep it when subscribing and call it during scene changes or disposal. Do not construct another client for every impact. Remove your own DOM listeners and stop background tasks before disconnect.
Code example
Integration excerpt: game-specific variables belong to the application. Playground contains the runnable reference.
const seen = new Set();
const off = sdk.on('target.hit', hit => {
if (sdk.sessionState !== 'running' || seen.has(hit.shot_id)) return;
seen.add(hit.shot_id);
handleImpact(hit).catch(showGameError);
});
// Scene disposal:
off();
sdk.disconnect();