diff --git a/client/src/network/SocketClient.ts b/client/src/network/SocketClient.ts index 3f3c997..7c38b6d 100644 --- a/client/src/network/SocketClient.ts +++ b/client/src/network/SocketClient.ts @@ -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; @@ -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; } diff --git a/server/src/network/SocketServer.ts b/server/src/network/SocketServer.ts index 1d1ca0d..7c6f179 100644 --- a/server/src/network/SocketServer.ts +++ b/server/src/network/SocketServer.ts @@ -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 }); diff --git a/shared/src/types.ts b/shared/src/types.ts index a664b05..6974338 100644 --- a/shared/src/types.ts +++ b/shared/src/types.ts @@ -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