feat: add socket.io events for narration broadcast
Wire narration events through the socket layer so clients receive real-time narration updates. Server emits narration-event on creation, narration-update when LLM text arrives, and narration-history on connect. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { io, Socket } from 'socket.io-client';
|
||||
import type { ServerEvents, ClientEvents, WorldState, StateUpdate, PlayerJoined, PlayerLeft, PlayerInput } from '@dflike/shared';
|
||||
import type { ServerEvents, ClientEvents, WorldState, StateUpdate, PlayerJoined, PlayerLeft, PlayerInput, NarrationEvent } from '@dflike/shared';
|
||||
|
||||
type TypedSocket = Socket<ServerEvents, ClientEvents>;
|
||||
|
||||
@@ -13,6 +13,9 @@ export class SocketClient {
|
||||
onStateUpdate: ((data: StateUpdate) => void) | null = null;
|
||||
onPlayerJoined: ((data: PlayerJoined) => void) | null = null;
|
||||
onPlayerLeft: ((data: PlayerLeft) => void) | null = null;
|
||||
onNarrationEvent: ((data: NarrationEvent) => void) | null = null;
|
||||
onNarrationUpdate: ((data: { id: number; narration: string }) => void) | null = null;
|
||||
onNarrationHistory: ((data: NarrationEvent[]) => void) | null = null;
|
||||
|
||||
constructor(url: string) {
|
||||
this.socket = io(url);
|
||||
@@ -36,6 +39,10 @@ export class SocketClient {
|
||||
this.socket.on('player-left', (data) => {
|
||||
this.onPlayerLeft?.(data);
|
||||
});
|
||||
|
||||
this.socket.on('narration-event', (data) => this.onNarrationEvent?.(data));
|
||||
this.socket.on('narration-update', (data) => this.onNarrationUpdate?.(data));
|
||||
this.socket.on('narration-history', (data) => this.onNarrationHistory?.(data));
|
||||
}
|
||||
|
||||
get playerId(): string | null { return this._playerId; }
|
||||
|
||||
@@ -26,6 +26,16 @@ export class SocketServer {
|
||||
const update = serializeStateUpdate(this.gameLoop.world, this.gameLoop.getTick(), this.gameLoop.getGameTime());
|
||||
this.io.emit('state-update', update);
|
||||
});
|
||||
|
||||
const narrationService = this.gameLoop.narrationService;
|
||||
|
||||
narrationService.onEventCreated = (event) => {
|
||||
this.io.emit('narration-event', event);
|
||||
};
|
||||
|
||||
narrationService.onEventUpdated = (event) => {
|
||||
this.io.emit('narration-update', { id: event.id, narration: event.narration });
|
||||
};
|
||||
}
|
||||
|
||||
private setupConnections(): void {
|
||||
@@ -51,6 +61,9 @@ export class SocketServer {
|
||||
socket.emit('world-state', serializeWorldState(world, map));
|
||||
socket.emit('player-joined', { playerId, entityId: entity });
|
||||
|
||||
// Send narration history
|
||||
socket.emit('narration-history', this.gameLoop.narrationService.getRecentEvents());
|
||||
|
||||
// Notify others
|
||||
socket.broadcast.emit('player-joined', { playerId, entityId: entity });
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { AccessorySlot, PortraitSlot } from './constants.js';
|
||||
import type { NarrationEvent } from './narration.js';
|
||||
|
||||
// Entity is just a numeric ID
|
||||
export type EntityId = number;
|
||||
@@ -171,6 +172,9 @@ export interface ServerEvents {
|
||||
'player-joined': (data: PlayerJoined) => void;
|
||||
'player-left': (data: PlayerLeft) => void;
|
||||
'npc-recomposed': (data: { entityId: EntityId; appearance: Appearance }) => void;
|
||||
'narration-event': (data: NarrationEvent) => void;
|
||||
'narration-update': (data: { id: number; narration: string }) => void;
|
||||
'narration-history': (data: NarrationEvent[]) => void;
|
||||
}
|
||||
|
||||
// Client -> Server events
|
||||
|
||||
Reference in New Issue
Block a user