Практические рецепты
Эти короткие фрагменты дополняют, а не заменяют запускаемый пример.
Повтор события
Храните обработанные shot_id в пределах одного раунда. Очищайте набор при новом сеансе; ограничивайте размер в долгих режимах. Сам факт доставки callback не гарантирует, что игровая цель ещё активна: проверяйте фазу, паузу и countdown.
Асинхронный обработчик
Обработчики событий вызываются синхронно. Если callback запускает async-работу, он обязан сам обработать rejection. Исключения синхронного listener превращаются в error с кодом LISTENER, но это не заменяет catch у промиса.
Освобождение
Метод on возвращает функцию отписки. Храните её при подписке и вызывайте при смене сцены или уничтожении игры. Не создавайте второй клиент при каждом попадании. Удалите собственные DOM-listeners и остановите свои фоновые задачи перед disconnect.
Пример кода
Фрагмент интеграции: переменные игрового проекта задаются приложением. Полный запускаемый пример — в Playground.
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();