[wip] added socket shape for join game + started working on front handling of game param in url

This commit is contained in:
bgoulard 2026-01-11 17:03:12 +01:00 committed by Nigel
parent a435afb48f
commit b862dc27f1
4 changed files with 60 additions and 9 deletions

View file

@ -7,7 +7,7 @@ import {
} from "@app/routing"; } from "@app/routing";
import authHtml from "./pong.html?raw"; import authHtml from "./pong.html?raw";
import io from "socket.io-client"; import io from "socket.io-client";
import type { CSocket, GameMove, GameUpdate, TourInfo } from "./socket"; import { JoinRes, type CSocket, type GameMove, type GameUpdate, type TourInfo } from "./socket";
import { showError, showInfo, showSuccess } from "@app/toast"; import { showError, showInfo, showSuccess } from "@app/toast";
import { getUser as getSelfUser, type User } from "@app/auth"; import { getUser as getSelfUser, type User } from "@app/auth";
import { isNullish } from "@app/utils"; import { isNullish } from "@app/utils";
@ -79,12 +79,11 @@ function pongClient(
): RouteHandlerReturn { ): RouteHandlerReturn {
setTitle("Pong Game Page"); setTitle("Pong Game Page");
const urlParams = new URLSearchParams(window.location.search); const urlParams = new URLSearchParams(window.location.search);
const game_req_join = urlParams.get("game"); let game_req_join = urlParams.get("game");
if (game_req_join) { // todo:
showError( // [ ] shape sock
"currently not supporting the act of joining game (even as a spectator)", // - [ ] joinGame (guid) -> ["ok"|"no, dont ever talk to my kid or me ever again you creep"];
); // - [ ] launch newgame evt?
}
return { return {
html: authHtml, html: authHtml,
@ -240,6 +239,30 @@ function pongClient(
// keys end // keys end
// --- // ---
// ---
// join game
// ---
if (game_req_join != null) {
socket.emit('joinGame', game_req_join,
(res : JoinRes) => {
switch (res) {
case JoinRes.yes :
showInfo('JoinRes = yes');
break;
case JoinRes.no :
showInfo('JoinRes = no');
break;
default:
showError('JoinRes switch fail:' + res);
}
}
)
game_req_join = null;
}
// ---
// join game end
// ---
// --- // ---
// position logic (client) // position logic (client)
// --- // ---

View file

@ -37,6 +37,12 @@ export type TourInfo = {
remainingMatches: number | null, remainingMatches: number | null,
}; };
export enum JoinRes {
yes = 'yes',
no = 'dont ever talk to me or my kid ever again',
dev = 'yaaaaaaaaaaaaaaaaaaaaaaaa',
};
export interface ClientToServer { export interface ClientToServer {
enqueue: () => void; enqueue: () => void;
dequeue: () => void; dequeue: () => void;
@ -46,6 +52,8 @@ export interface ClientToServer {
connectedToGame: (gameId: string) => void; connectedToGame: (gameId: string) => void;
localGame: () => void; localGame: () => void;
joinGame: (guid : string, ack:(result:JoinRes) => void) => void;
hello: () => void; hello: () => void;
// TOURNAMENT // TOURNAMENT

View file

@ -37,6 +37,12 @@ export type TourInfo = {
remainingMatches: number | null, remainingMatches: number | null,
}; };
export enum JoinRes {
yes = 'yes',
no = 'dont ever talk to me or my kid ever again',
dev = 'yaaaaaaaaaaaaaaaaaaaaaaaa',
};
export interface ClientToServer { export interface ClientToServer {
enqueue: () => void; enqueue: () => void;
dequeue: () => void; dequeue: () => void;
@ -46,6 +52,8 @@ export interface ClientToServer {
connectedToGame: (gameId: string) => void; connectedToGame: (gameId: string) => void;
localGame: () => void; localGame: () => void;
joinGame: (guid : string, ack:(result:JoinRes) => void) => void;
hello: () => void; hello: () => void;
// TOURNAMENT // TOURNAMENT

View file

@ -2,7 +2,7 @@ import { UserId } from '@shared/database/mixin/user';
import { newUUID } from '@shared/utils/uuid'; import { newUUID } from '@shared/utils/uuid';
import { FastifyInstance } from 'fastify'; import { FastifyInstance } from 'fastify';
import { Pong } from './game'; import { Pong } from './game';
import { GameMove, GameUpdate, SSocket, TourInfo } from './socket'; import { GameMove, GameUpdate, JoinRes, SSocket, TourInfo } from './socket';
import { isNullish, shuffle } from '@shared/utils'; import { isNullish, shuffle } from '@shared/utils';
import { PongGameId, PongGameOutcome } from '@shared/database/mixin/pong'; import { PongGameId, PongGameOutcome } from '@shared/database/mixin/pong';
import { Tournament } from './tour'; import { Tournament } from './tour';
@ -385,6 +385,18 @@ class StateI {
this.cleanupUser(sock); this.cleanupUser(sock);
} }
private tryJoinGame(g_id : string, sock : SSocket) : JoinRes {
const game_id : PongGameId = g_id as PongGameId;
let game : Pong;
if (this.games.has(game_id) === false)
return (JoinRes.no);
game = this.games.get(game_id)!;
if (game.local || game.userLeft !== sock.authUser.id || game.userRight !== sock.authUser.id)
return (JoinRes.no);
return (JoinRes.dev);
}
public registerUser(socket: SSocket): void { public registerUser(socket: SSocket): void {
this.fastify.log.info('Registering new user'); this.fastify.log.info('Registering new user');
if (this.users.has(socket.authUser.id)) { if (this.users.has(socket.authUser.id)) {
@ -415,7 +427,7 @@ class StateI {
socket.on('gameMove', (e) => this.gameMove(socket, e)); socket.on('gameMove', (e) => this.gameMove(socket, e));
socket.on('localGame', () => this.newLocalGame(socket)); socket.on('localGame', () => this.newLocalGame(socket));
socket.on('joinGame', (g_id, ack) => {return (ack(this.tryJoinGame(g_id, socket)));});
// todo: allow passing nickname // todo: allow passing nickname
socket.on('tourRegister', () => socket.on('tourRegister', () =>
this.registerForTournament(socket, null), this.registerForTournament(socket, null),