Add heartbeat telemetry support

This commit is contained in:
2026-09-19 21:52:05 -04:00
parent 8ac420fe61
commit ce0321a6e9
14 changed files with 63 additions and 21 deletions
+4 -4
View File
@@ -13,16 +13,16 @@ export interface TelemetryPlayerStats extends TelemetryPlayer {
export type GameEvent = { server: string; map: string } & (
| { event: 'game_start'; players: TelemetryPlayer[] }
| { event: 'round_change' | 'game_end'; round: number; players: TelemetryPlayerStats[] }
| { event: 'round_change' | 'heartbeat' | 'game_end'; round: number; players: TelemetryPlayerStats[] }
);
export type GameTelemetry = GameEvent & { receivedAt: string };
/** Validate the three script payloads; beta state is never part of the protocol. */
/** Validate the four script payloads; beta state is never part of the protocol. */
export function parseGameEvent(value: unknown): GameEvent {
if (!value || typeof value !== 'object' || Array.isArray(value)) throw new Error('Payload must be a JSON object');
const body = value as Record<string, unknown>;
if (!['game_start', 'round_change', 'game_end'].includes(String(body.event))) throw new Error('event must be game_start, round_change, or game_end');
if (!['game_start', 'round_change', 'heartbeat', 'game_end'].includes(String(body.event))) throw new Error('event must be game_start, round_change, heartbeat, or game_end');
for (const key of ['server', 'map'] as const) {
if (typeof body[key] !== 'string' || !body[key].trim() || body[key].length > 255) throw new Error(`${key} must be a nonempty string (up to 255 characters)`);
}
@@ -48,5 +48,5 @@ export function parseGameEvent(value: unknown): GameEvent {
const common = { server: body.server as string, map: body.map as string };
if (body.event === 'game_start') return { ...common, event: 'game_start', players };
if (!Number.isSafeInteger(body.round) || (body.round as number) < 0) throw new Error('round must be a nonnegative integer');
return { ...common, event: body.event as 'round_change' | 'game_end', round: body.round as number, players: players as TelemetryPlayerStats[] };
return { ...common, event: body.event as 'round_change' | 'heartbeat' | 'game_end', round: body.round as number, players: players as TelemetryPlayerStats[] };
}