feat: add superlatives subscribe/unsubscribe socket handlers
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Server } from 'socket.io';
|
||||
import { Server, Socket } from 'socket.io';
|
||||
import type http from 'http';
|
||||
import type { ClientEvents, ServerEvents, PlayerInput, Position, Movement, PlayerControlled, Appearance } from '@dflike/shared';
|
||||
import { Direction, MAX_NPC_COUNT } from '@dflike/shared';
|
||||
@@ -6,10 +6,14 @@ import { generateRandomAppearance } from '../spawner/appearanceGenerator.js';
|
||||
import type { GameLoop } from '../game/GameLoop.js';
|
||||
import { spawnNPC } from '../game/spawner.js';
|
||||
import { serializeWorldState, serializeStateUpdate } from './stateSerializer.js';
|
||||
import { computeSuperlatives } from '../systems/superlativesComputer.js';
|
||||
import type { BondRegistry } from '../systems/bondRegistry.js';
|
||||
|
||||
export class SocketServer {
|
||||
private io: Server<ClientEvents, ServerEvents>;
|
||||
private gameLoop: GameLoop;
|
||||
private superlativesSubscribers: Set<Socket<ClientEvents, ServerEvents>> = new Set();
|
||||
private superlativesTimer: ReturnType<typeof setInterval> | null = null;
|
||||
|
||||
constructor(httpServer: http.Server, gameLoop: GameLoop) {
|
||||
this.io = new Server(httpServer, {
|
||||
@@ -69,15 +73,56 @@ export class SocketServer {
|
||||
spawnNPC(world, map, target);
|
||||
});
|
||||
|
||||
// Handle superlatives subscription
|
||||
socket.on('superlatives-subscribe', () => {
|
||||
this.superlativesSubscribers.add(socket);
|
||||
// Send immediately
|
||||
const registry = this.gameLoop.world.getSingleton<BondRegistry>('bondRegistry');
|
||||
if (registry) {
|
||||
const data = computeSuperlatives(this.gameLoop.world, registry);
|
||||
socket.emit('superlatives-update', data);
|
||||
}
|
||||
// Start timer if first subscriber
|
||||
if (!this.superlativesTimer && this.superlativesSubscribers.size === 1) {
|
||||
this.superlativesTimer = setInterval(() => {
|
||||
this.broadcastSuperlatives();
|
||||
}, 10000);
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('superlatives-unsubscribe', () => {
|
||||
this.superlativesSubscribers.delete(socket);
|
||||
this.stopSuperlativesTimerIfEmpty();
|
||||
});
|
||||
|
||||
// Handle disconnect
|
||||
socket.on('disconnect', () => {
|
||||
console.log(`Player disconnected: ${playerId}`);
|
||||
this.superlativesSubscribers.delete(socket);
|
||||
this.stopSuperlativesTimerIfEmpty();
|
||||
world.removeEntity(entity);
|
||||
this.io.emit('player-left', { playerId });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private broadcastSuperlatives(): void {
|
||||
if (this.superlativesSubscribers.size === 0) return;
|
||||
const registry = this.gameLoop.world.getSingleton<BondRegistry>('bondRegistry');
|
||||
if (!registry) return;
|
||||
const data = computeSuperlatives(this.gameLoop.world, registry);
|
||||
for (const socket of this.superlativesSubscribers) {
|
||||
socket.emit('superlatives-update', data);
|
||||
}
|
||||
}
|
||||
|
||||
private stopSuperlativesTimerIfEmpty(): void {
|
||||
if (this.superlativesSubscribers.size === 0 && this.superlativesTimer) {
|
||||
clearInterval(this.superlativesTimer);
|
||||
this.superlativesTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
private handleInput(playerId: string, entityId: number, input: PlayerInput): void {
|
||||
const world = this.gameLoop.world;
|
||||
const pc = world.getComponent<PlayerControlled>(entityId, 'playerControlled');
|
||||
|
||||
Reference in New Issue
Block a user