Fix really weird bug where clients just don't visit / when they visit /, somehow. I worked around it by having new WS connections to non-existent games just create the game.
This commit is contained in:
parent
55b16f6712
commit
fcc2bdd5f0
|
@ -0,0 +1,114 @@
|
|||
import { Elysia, t } from 'elysia';
|
||||
import { html } from '@elysiajs/html';
|
||||
import { staticPlugin } from '@elysiajs/static';
|
||||
import { cookie } from '@elysiajs/cookie';
|
||||
import { WebSocketHandler } from './web-socket-handler';
|
||||
import { ElysiaWS } from 'elysia/dist/ws';
|
||||
import { createStoneSvg } from './view/board-renderer';
|
||||
|
||||
const wsHandler = new WebSocketHandler();
|
||||
export type WS = ElysiaWS<{ query: { playerId: string; gameId: string } }>;
|
||||
|
||||
const app = new Elysia()
|
||||
.use(
|
||||
staticPlugin({
|
||||
assets: './public',
|
||||
prefix: '/',
|
||||
}),
|
||||
)
|
||||
.use(cookie())
|
||||
.use(html())
|
||||
.ws('/ws', {
|
||||
query: t.Object({
|
||||
gameId: t.String(),
|
||||
playerId: t.String(),
|
||||
}),
|
||||
open(ws) {
|
||||
wsHandler.handleConnection(ws);
|
||||
},
|
||||
message(ws, message) {
|
||||
wsHandler.handleMessage(ws, message);
|
||||
},
|
||||
close(ws) {
|
||||
wsHandler.handleDisconnect(ws);
|
||||
},
|
||||
})
|
||||
.get('/', async ({ query, cookie, request: _request }) => {
|
||||
let playerId: string;
|
||||
const existingPlayerId = cookie.playerId?.value;
|
||||
if (existingPlayerId) {
|
||||
playerId = existingPlayerId;
|
||||
console.log(`Using existing playerId from cookie: ${playerId}`);
|
||||
} else {
|
||||
playerId = `player-${Math.random().toString(36).substring(2, 9)}`;
|
||||
cookie.playerId.set({
|
||||
value: playerId,
|
||||
httpOnly: true,
|
||||
path: '/',
|
||||
maxAge: 30 * 24 * 60 * 60,
|
||||
});
|
||||
console.log(`Generated new playerId and set cookie: ${playerId}`);
|
||||
}
|
||||
|
||||
let gameId = query.gameId as string | undefined;
|
||||
let gameIdInitialized = false;
|
||||
if (gameId) {
|
||||
if (!wsHandler.hasGame(gameId)) {
|
||||
wsHandler.createGame(gameId);
|
||||
console.log(`Created new game with provided ID: ${gameId}`);
|
||||
}
|
||||
} else {
|
||||
gameId = wsHandler.createGame();
|
||||
gameIdInitialized = true;
|
||||
console.log(`Created new game without specific ID: ${gameId}`);
|
||||
}
|
||||
|
||||
if (gameIdInitialized) {
|
||||
return new Response(null, {
|
||||
status: 302,
|
||||
headers: { Location: `/?gameId=${gameId}` },
|
||||
});
|
||||
}
|
||||
|
||||
const displayName = wsHandler.getPlayerName(playerId);
|
||||
|
||||
const htmlTemplate = await Bun.file('./public/index.html').text();
|
||||
let finalHtml = htmlTemplate
|
||||
.replace(
|
||||
'<meta name="gameId" content="" />',
|
||||
`<meta name="gameId" content="${gameId}" />`,
|
||||
)
|
||||
.replace(
|
||||
'<meta name="playerId" content="" />',
|
||||
`<meta name="playerId" content="${playerId}" />`,
|
||||
)
|
||||
.replace(
|
||||
'<meta name="displayName" content="" />',
|
||||
`<meta name="displayName" content="${displayName}" />`,
|
||||
);
|
||||
|
||||
return new Response(finalHtml, {
|
||||
headers: { 'Content-Type': 'text/html' },
|
||||
status: 200,
|
||||
});
|
||||
})
|
||||
.get('/black-stone.svg', () => {
|
||||
const stoneSvg = createStoneSvg('black', false);
|
||||
return new Response(String(stoneSvg), {
|
||||
headers: { 'Content-Type': 'image/svg+xml' },
|
||||
status: 200,
|
||||
});
|
||||
})
|
||||
.get('/white-stone.svg', () => {
|
||||
const stoneSvg = createStoneSvg('white', false);
|
||||
return new Response(String(stoneSvg), {
|
||||
headers: { 'Content-Type': 'image/svg+xml' },
|
||||
status: 200,
|
||||
});
|
||||
});
|
||||
|
||||
const port = Number(process.env.PORT || 3000);
|
||||
|
||||
app.listen(port, () => {
|
||||
console.log(`🦊 Elysia is running at ${app.server?.hostname}:${port}`);
|
||||
});
|
11
src/index.ts
11
src/index.ts
|
@ -51,19 +51,18 @@ const app = new Elysia()
|
|||
}
|
||||
|
||||
let gameId = query.gameId as string | undefined;
|
||||
let gameIdInitialized = false;
|
||||
if (gameId) {
|
||||
if (!wsHandler.hasGame(gameId)) {
|
||||
wsHandler.createGame(gameId);
|
||||
console.log(`Created new game with provided ID: ${gameId}`);
|
||||
} else {
|
||||
console.log(`Player ${playerId} visited existing game ${gameId}`);
|
||||
}
|
||||
} else {
|
||||
gameId = wsHandler.createGame();
|
||||
gameIdInitialized = true;
|
||||
console.log(`Created new game without specific ID: ${gameId}`);
|
||||
}
|
||||
|
||||
if (gameIdInitialized) {
|
||||
console.log(
|
||||
`Player ${playerId} came without a gameId. Redirecting them to new game ${gameId}.`,
|
||||
);
|
||||
return new Response(null, {
|
||||
status: 302,
|
||||
headers: { Location: `/?gameId=${gameId}` },
|
||||
|
|
|
@ -13,13 +13,14 @@ export class WebSocketHandler {
|
|||
}
|
||||
|
||||
public handleConnection(ws: WS): void {
|
||||
const { gameId } = ws.data.query;
|
||||
const { gameId, playerId } = ws.data.query;
|
||||
console.log(`Player ${playerId} is opening a connection to game ${gameId}`);
|
||||
if (this.games.has(gameId)) {
|
||||
const game = this.games.get(gameId)!;
|
||||
game.handleConnection(ws);
|
||||
} else {
|
||||
ws.send('Error: game not found');
|
||||
ws.close();
|
||||
this.createGame(gameId);
|
||||
this.games.get(gameId)!.handleConnection(ws);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue