From 04203f4f9d392c34b936ad327c0b49bc6ed1ac49 Mon Sep 17 00:00:00 2001 From: LuckyLaszlo Date: Mon, 21 Nov 2022 21:04:41 +0100 Subject: [PATCH] matchmaking OK --- src/server/class/GameSession.ts | 5 +-- src/server/gameUpdate.ts | 26 ------------ src/server/wsServer.ts | 71 +++++++++++++++++++++++---------- src/shared_js/class/Event.ts | 1 + 4 files changed, 52 insertions(+), 51 deletions(-) delete mode 100644 src/server/gameUpdate.ts diff --git a/src/server/class/GameSession.ts b/src/server/class/GameSession.ts index aaf7b611..0fba43bc 100644 --- a/src/server/class/GameSession.ts +++ b/src/server/class/GameSession.ts @@ -1,5 +1,4 @@ import { ClientPlayer } from "./Client"; -import {gameUpdate} from "../gameUpdate.js" import { GameComponents } from "../../shared_js/class/GameComponents.js"; import { clientInputListener } from "../wsServer.js"; import * as c from "../constants.js" @@ -106,8 +105,8 @@ class GameSession { private _newRound(s: GameSession) { const gc = s.components; // https://fr.wikipedia.org/wiki/Tennis_de_table#Nombre_de_manches - if (gc.scoreLeft >= 11 - || gc.scoreRight >= 11) + if (gc.scoreLeft >= 11 || gc.scoreRight >= 11) + // if (gc.scoreLeft >= 2 || gc.scoreRight >= 2) // WIP: for testing { if (Math.abs(gc.scoreLeft - gc.scoreRight) >= 2) { diff --git a/src/server/gameUpdate.ts b/src/server/gameUpdate.ts deleted file mode 100644 index a7672922..00000000 --- a/src/server/gameUpdate.ts +++ /dev/null @@ -1,26 +0,0 @@ - -import {EventTypes} from "../shared_js/enums.js" -import {EventGameUpdate} from "../shared_js/class/Event.js" -import { random } from "../shared_js/utils.js"; // temp - -/* -import {Rectangle, MovingRectangle, Racket, Ball, Line} from "../shared_js/class/Rectangle.js"; -import { Vector } from "../shared_js/class/Vector.js"; -class CanvasRenderingContext2D {} // Empty object replacement to the web-API (web-API useless on server-side) -const mockCtx = new CanvasRenderingContext2D; - // @ts-ignore -const playerLeft = new Racket(mockCtx, new Vector(), "white", 1, 1, 1); - */ - -function gameUpdate() : EventGameUpdate -{ - const update: EventGameUpdate = { - type: EventTypes.gameUpdate, - playerLeft: {y: random(50, 650)}, - playerRight: {y: random(50, 650)}, - ball: {x: 0, y: 0, speed: 0} - }; - return update; -} - -export {gameUpdate} \ No newline at end of file diff --git a/src/server/wsServer.ts b/src/server/wsServer.ts index 54e5eddf..b20989cb 100644 --- a/src/server/wsServer.ts +++ b/src/server/wsServer.ts @@ -18,6 +18,7 @@ const wsPort = 8042; export const wsServer = new WebSocketServer({port: wsPort, path: "/pong"}); const clientsMap: Map = new Map; // socket.id/Client +const matchmakingPlayersMap: Map = new Map; // socket.id/ClientPlayer (duplicates with clientsMap) const gameSessionsMap: Map = new Map; // GameSession.id(url)/GameSession wsServer.on("connection", connectionListener); @@ -38,6 +39,13 @@ function connectionListener(socket: WebSocket, request: IncomingMessage) }); socket.on("message", function log(data: string) { + try { + const event: ev.ClientEvent = JSON.parse(data); + if (event.type === en.EventTypes.clientInput) { + return; + } + } + catch (e) {} console.log("data: " + data); }); @@ -50,8 +58,8 @@ function clientAnnounceListener(this: WebSocket, data: string) try { const msg : ev.ClientAnnounce = JSON.parse(data); if (msg.type === en.EventTypes.clientAnnounce) { - // TODO: reconnection with msg.id - // TODO: spectator/player distinction with msg.type + // TODO: reconnection with msg.id ? + // TODO: spectator/player distinction with msg.type ? this.send(JSON.stringify( new ev.EventAssignId(this.id) )) this.send(JSON.stringify( new ev.ServerEvent(en.EventTypes.matchmakingInProgress) )) @@ -63,7 +71,7 @@ function clientAnnounceListener(this: WebSocket, data: string) return; } catch (e) { - console.log("Invalid JSON"); + console.log("Invalid JSON (clientAnnounceListener)"); } this.once("message", clientAnnounceListener); } @@ -71,25 +79,41 @@ function clientAnnounceListener(this: WebSocket, data: string) function matchmaking(socket: WebSocket) { - // TODO Actual Matchmaking - - // TODO: Only once - const id = uuidv4(); - const gameSession = new GameSession(id); - gameSessionsMap.set(id, gameSession); - - // TODO: Per player const player: ClientPlayer = clientsMap.get(socket.id) as ClientPlayer; - player.gameSession = gameSession; - gameSession.playersMap.set(socket.id, player); - gameSession.unreadyPlayersMap.set(socket.id, player); + if (matchmakingPlayersMap.size < 1) + { + matchmakingPlayersMap.set(socket.id, player); + return; + } + else + { + const id = uuidv4(); + const gameSession = new GameSession(id); + gameSessionsMap.set(id, gameSession); - player.racket = gameSession.components.playerLeft; - socket.send(JSON.stringify( new ev.EventMatchmakingComplete(en.PlayerSide.left) )); + // for player + gameSession.playersMap.set(player.id, player); + player.racket = gameSession.components.playerRight; + socket.send(JSON.stringify( new ev.EventMatchmakingComplete(en.PlayerSide.right) )); + // for opponent + const opponent: ClientPlayer = matchmakingPlayersMap.values().next().value; + gameSession.playersMap.set(opponent.id, opponent); + matchmakingPlayersMap.delete(opponent.id); + opponent.racket = gameSession.components.playerLeft; + opponent.socket.send(JSON.stringify( new ev.EventMatchmakingComplete(en.PlayerSide.left) )); - socket.once("message", playerReadyConfirmationListener); - + // for both + gameSession.playersMap.forEach( (client) => { + gameSession.unreadyPlayersMap.set(client.id, client); + client.gameSession = gameSession; + }); + gameSession.playersMap.forEach( (client) => { + /* set listener last to be absolutly sure there no early game launch + (unlikely, but theoretically possible) */ + client.socket.once("message", playerReadyConfirmationListener); + }); + } } @@ -109,12 +133,12 @@ function playerReadyConfirmationListener(this: WebSocket, data: string) } } else { - console.log("Invalid PlayerReady confirmation"); + console.log("Invalid playerReadyConfirmation"); } return; } catch (e) { - console.log("Invalid JSON"); + console.log("Invalid JSON (playerReadyConfirmationListener)"); } this.once("message", playerReadyConfirmationListener); } @@ -130,11 +154,11 @@ export function clientInputListener(this: WebSocket, data: string) client.gameSession.handleInput(client as ClientPlayer, input.input); } else { - console.log("Invalid EventInput"); + console.log("Invalid clientInput"); } } catch (e) { - console.log("Invalid JSON"); + console.log("Invalid JSON (clientInputListener)"); } } @@ -146,6 +170,9 @@ const pingInterval = setInterval( () => { if (client.isAlive === false) { client.socket.terminate(); map.delete(key); + if (matchmakingPlayersMap.has(key)) { + matchmakingPlayersMap.delete(key); + } console.log("%i: client %s is no more :'(", Date.now(), key); return; } diff --git a/src/shared_js/class/Event.ts b/src/shared_js/class/Event.ts index 3d27ebb6..ec214460 100644 --- a/src/shared_js/class/Event.ts +++ b/src/shared_js/class/Event.ts @@ -48,6 +48,7 @@ class EventMatchEnd extends ServerEvent { winner: en.PlayerSide; constructor(winner: en.PlayerSide) { super(en.EventTypes.matchEnd); + this.winner = winner; } }