import { Server, Socket } from 'socket.io'; import { Canvas } from './canvas'; import { config } from '../config'; import { RequestHandler } from 'express'; import { CanvasRecord, Placement } from '../../common/types/canvas'; import { IcyNetUser } from '../../common/types/user'; const PLACEHOLDER_USER: IcyNetUser = { id: 0, username: 'placer', display_name: 'placer', uuid: 'placer', accessToken: 'placer', }; export class Game { private _canvas = new Canvas(config.game.boardSize); private _connections: Socket[] = []; private _changes: CanvasRecord[] = []; private _interval: any; constructor(private io: Server, private session: RequestHandler) {} async initialize() { await this._canvas.initialize(); this.io.use((socket, next) => this.session(socket.request as any, {} as any, next as any), ); this.io.on('connection', (socket) => { const session = (socket.request as any).session; const user = process.env.SKIP_LOGIN === 'true' ? PLACEHOLDER_USER : (session?.passport?.user as IcyNetUser); this._connections.push(socket); socket.emit( 'me', user ? { username: user.username, display_name: user.display_name, } : null, ); socket.emit('plane', { size: this._canvas.size, canvas: Object.values(this._canvas.getFullPlane()), }); socket.on('color', ({ c, x, y, t }: Placement) => { if (!user || c > 0xffffff || c < 0 || c === null) { return; } this._canvas.setPixelAt(c, x, y, user.username); socket.emit('colorack', { c, x, y, t }); }); socket.on('getplacer', ({ x, y, reqt }) => { this._canvas.history .getPlacerAt(x, y) .then((placer) => { if (placer) { socket.emit('placerat', { ...placer, reqt }); } }) .catch((e) => console.error(e)); }); socket.on('disconnect', () => { this._connections.splice(this._connections.indexOf(socket), 1); }); }); this._canvas.registerChangeHandler((record) => { this._changes.push(record); }); this._interval = setInterval(() => { if (this._changes.length && this._connections.length) { this._connections.forEach((socket) => socket.emit('changes', this._changes), ); this._changes.length = 0; } }, 1000); } }