Show authenticated unique online player count on home screen

This commit is contained in:
2026-10-15 00:07:41 +09:00
parent 7c414655c8
commit 32d32a6ebc
9 changed files with 99 additions and 0 deletions
+33
View File
@@ -0,0 +1,33 @@
import type { Server } from 'socket.io';
import type { GameSessionStore } from './game-session-store.js';
import { PRESENCE_AUTH_REFRESH_MS } from '../../constants/presence.js';
// The application is deployed as one process, as is the ranked match service.
export function registerPresence(io: Server, sessions: GameSessionStore) {
const namespace = io.of('/presence');
let count = 0;
function publish() {
const next = new Set([...namespace.sockets.values()].filter(socket => socket.connected).map(socket => socket.data.playerId)).size;
if (next !== count) { count = next; namespace.emit('presence:count', count); }
}
namespace.use((socket, next) => {
const { gameSessionId, token } = socket.handshake.auth;
void sessions.get({ gameSessionId, token }).then(session => {
socket.data.playerId = session.playerId ?? session.gameSessionId;
next();
}, () => next(new Error('INVALID_SESSION')));
});
namespace.on('connection', socket => {
const before = count; publish();
if (before === count) socket.emit('presence:count', count);
let checking = false;
const timer = setInterval(() => {
if (checking) return;
checking = true;
const { gameSessionId, token } = socket.handshake.auth;
void sessions.get({ gameSessionId, token }).catch(() => socket.disconnect(true)).finally(() => { checking = false; });
}, PRESENCE_AUTH_REFRESH_MS);
timer.unref();
socket.on('disconnect', () => { clearInterval(timer); publish(); });
});
}