export enum EventType { INITIAL_STATE = "INITIAL_STATE", SET_CONTROLLABLE = "SET_CONTROLLABLE", ENTITY_BORN = "ENTITY_BORN", ENTITY_DEATH = "ENTITY_DEATH", ENTITY_POSITION_UPDATE = "ENTITY_POSITION_UPDATE", } export interface Event { event_type: EventType; data: any; } export interface EntityPositionUpdateEvent extends Event { event_type: EventType.ENTITY_POSITION_UPDATE; data: { id: string; position: { x: number; y: number; }; }; } export interface InitialStateEvent extends Event { event_type: EventType.INITIAL_STATE; data: { world: { width: number; height: number }; entities: any[]; }; } export interface SetControllableEvent extends Event { event_type: EventType.SET_CONTROLLABLE; data: { id: string; client_id: string; }; } export interface EventQueue { peek(): Event[]; clear(): void; } export interface EventPublisher { add(event: Event): void; publish(): void; } export class WebSocketEventQueue implements EventQueue { private queue: Event[]; constructor(websocket: WebSocket) { this.queue = []; this.listen_to(websocket); } public peek() { return this.queue; } public clear() { this.queue = []; } private listen_to(websocket: WebSocket) { websocket.onmessage = ({ data }) => { const [event_type, event_data] = JSON.parse(data); this.queue.push({ event_type, data: event_data } as Event); }; } } export class WebsocketEventPublisher implements EventPublisher { private queue: Event[]; constructor(private readonly websocket: WebSocket) { this.queue = []; } public add(event: Event) { this.queue.push(event); } public publish() { this.websocket.send(JSON.stringify(this.queue)); this.queue = []; } }