GameSpectator nearly done (missing fetch matchlist from Nest)

+ matchEnded/matchAbort proper reset (replace setTimeout)
+ abort window.addEventListener('keydown/keyup', ...)
+ refactoring Game.svelte and others
+ fix $POSTGRES_PASSWORD in make_env.sh
+ Wip bug audio
This commit is contained in:
LuckyLaszlo
2023-01-01 22:13:22 +01:00
parent 941b0ea7ea
commit eae5b70194
21 changed files with 233 additions and 186 deletions

View File

@@ -154,11 +154,12 @@ export class GameSession {
else if (ball.pos.x < 0 - ball.width) {
++gc.scoreRight;
}
const scoreUpdate = new ev.EventScoreUpdate(gc.scoreLeft, gc.scoreRight);
this.playersMap.forEach( (client) => {
client.socket.send(JSON.stringify(new ev.EventScoreUpdate(gc.scoreLeft, gc.scoreRight)));
client.socket.send(JSON.stringify(scoreUpdate));
});
this.spectatorsMap.forEach( (client) => {
client.socket.send(JSON.stringify(new ev.EventScoreUpdate(gc.scoreLeft, gc.scoreRight)));
client.socket.send(JSON.stringify(scoreUpdate));
});
}
private _playersUpdate(s: GameSession) {
@@ -167,9 +168,9 @@ export class GameSession {
s.lastStateSnapshot.lastInputId = client.lastInputId;
client.socket.send(JSON.stringify(s.lastStateSnapshot));
});
s.lastStateSnapshot.lastInputId = 0;
}
private _spectatorsUpdate(s: GameSession) {
s.lastStateSnapshot.lastInputId = 0;
s.spectatorsMap.forEach( (client) => {
client.socket.send(JSON.stringify(s.lastStateSnapshot));
});
@@ -251,8 +252,7 @@ export class GameSession {
private async _matchEnd(winner: en.PlayerSide, forfeit_flag: boolean = false)
{
this.matchEnded = true;
let eventEnd: ev.EventMatchEnd;
eventEnd = new ev.EventMatchEnd(winner, forfeit_flag);
const eventEnd = new ev.EventMatchEnd(winner, forfeit_flag);
this.playersMap.forEach( (client) => {
client.socket.send(JSON.stringify(eventEnd));
});
@@ -260,6 +260,7 @@ export class GameSession {
client.socket.send(JSON.stringify(eventEnd));
});
// TODO: mettre à jour la route pour gerer les forfaits (actuellement le plus haut score gagne par defaut)
const gc = this.components;
await fetch(c.addressBackEnd + "/game/gameserver/updategame",
{

View File

@@ -14,7 +14,6 @@ import * as c from "./constants.js"
import { Client, ClientPlayer, ClientSpectator } from "./class/Client.js"
import { GameSession } from "./class/GameSession.js"
import { shortId } from "./utils.js";
import { gameSessionIdPLACEHOLDER } from "./constants.js";
const wsPort = 8042;
export const wsServer = new WebSocketServer<WebSocket>({host: "0.0.0.0", port: wsPort, path: "/pong"});
@@ -23,12 +22,12 @@ const matchmakingMap: Map<string, ClientPlayer> = new Map; // socket.id/ClientPl
const privateMatchmakingMap: Map<string, ClientPlayer> = new Map; // socket.id/ClientPlayer (duplicates with clientsMap)
const gameSessionsMap: Map<string, GameSession> = new Map; // GameSession.id(url)/GameSession
wsServer.on("connection", connectionListener);
wsServer.on("error", errorListener);
wsServer.on("close", closeListener);
wsServer.on("connection", serverConnectionListener);
wsServer.on("error", serverErrorListener);
wsServer.on("close", serverCloseListener);
function connectionListener(socket: WebSocket, request: IncomingMessage)
function serverConnectionListener(socket: WebSocket, request: IncomingMessage)
{
const id = uuidv4();
const client = new Client(socket, id);
@@ -40,7 +39,11 @@ function connectionListener(socket: WebSocket, request: IncomingMessage)
console.log(`client ${shortId(client.id)} is alive`);
});
socket.on("error", function errorPrint(this: WebSocket, err: Error) {
socket.on("close", function removeClient() {
clientTerminate(client);
});
socket.on("error", function errorLog(this: WebSocket, err: Error) {
console.log(`error socket ${shortId(this.id)}:`);
console.log(`${err.name}: ${err.message}`);
if (err.stack) {
@@ -48,7 +51,7 @@ function connectionListener(socket: WebSocket, request: IncomingMessage)
}
});
socket.on("message", function log(data: string) {
socket.on("message", function messageLog(data: string) {
try {
const event: ev.ClientEvent = JSON.parse(data);
if (event.type === en.EventTypes.clientInput) {
@@ -69,13 +72,11 @@ async function clientAnnounceListener(this: WebSocket, data: string)
const msg : ev.ClientAnnounce = JSON.parse(data);
if (msg.type === en.EventTypes.clientAnnounce)
{
// TODO: reconnection with msg.clientId ?
// "/pong" to play, "/pong?ID_OF_A_GAMESESSION" to spectate (or something like that)
// BONUS: reconnection with msg.clientId ?
if (msg.role === en.ClientRole.player)
{
const announce: ev.ClientAnnouncePlayer = <ev.ClientAnnouncePlayer>msg;
// WIP nest, fetch token validation
const body = {
playerOneUsername: announce.username,
playerTwoUsername: "",
@@ -96,7 +97,7 @@ async function clientAnnounceListener(this: WebSocket, data: string)
});
if (!response.ok)
{
this.send(JSON.stringify( new ev.EventError((await response.json()).message)));
this.send(JSON.stringify( new ev.EventError((await response.json()).message) ));
clientTerminate(clientsMap.get(this.id));
return;
}
@@ -122,13 +123,14 @@ async function clientAnnounceListener(this: WebSocket, data: string)
const announce: ev.ClientAnnounceSpectator = <ev.ClientAnnounceSpectator>msg;
const gameSession = gameSessionsMap.get(announce.gameSessionId);
if (!gameSession) {
this.send(JSON.stringify( new ev.EventError("invalid gameSessionId")));
this.send(JSON.stringify( new ev.EventError("invalid gameSessionId") ));
clientTerminate(clientsMap.get(this.id));
return;
}
const spectator = clientsMap.get(this.id) as ClientSpectator;
spectator.gameSession = gameSession;
gameSession.spectatorsMap.set(spectator.id, spectator);
spectator.socket.once("message", spectatorReadyConfirmationListener);
this.send(JSON.stringify( new ev.ServerEvent(en.EventTypes.matchStart) ));
}
}
@@ -224,7 +226,7 @@ function privateMatchmaking(player: ClientPlayer)
function createGameSession(playersArr: ClientPlayer[], matchOptions: en.MatchOptions)
{
// const id = gameSessionIdPLACEHOLDER; // Force ID, TESTING SPECTATOR
// const id = c.gameSessionIdPLACEHOLDER; // Force ID, TESTING SPECTATOR
const id = uuidv4();
const gameSession = new GameSession(id, matchOptions);
gameSessionsMap.set(id, gameSession);
@@ -274,7 +276,6 @@ async function playerReadyConfirmationListener(this: WebSocket, data: string)
gameSession.unreadyPlayersMap.delete(this.id);
if (gameSession.unreadyPlayersMap.size === 0)
{
// WIP nest , send gameSession.id
const gameSessionPlayersIterator = gameSession.playersMap.values();
const body = {
gameServerIdOfTheMatch : gameSession.id,
@@ -341,6 +342,28 @@ export function clientInputListener(this: WebSocket, data: string)
}
}
function spectatorReadyConfirmationListener(this: WebSocket, data: string)
{
try {
const msg : ev.ClientEvent = JSON.parse(data);
if (msg.type === en.EventTypes.clientSpectatorReady)
{
const client = clientsMap.get(this.id);
const gameSession = client.gameSession;
const scoreUpdate = new ev.EventScoreUpdate(gameSession.components.scoreLeft, gameSession.components.scoreRight);
this.send(JSON.stringify(scoreUpdate));
}
else {
console.log("Invalid spectatorReadyConfirmation");
}
return;
}
catch (e) {
console.log("Invalid JSON (spectatorReadyConfirmationListener)");
}
this.once("message", spectatorReadyConfirmationListener);
}
////////////
////////////
@@ -390,13 +413,13 @@ export function clientTerminate(client: Client)
}
function closeListener()
function serverCloseListener()
{
clearInterval(pingInterval);
}
function errorListener(error: Error)
function serverErrorListener(error: Error)
{
console.log("Error: " + JSON.stringify(error));
}

View File

@@ -26,5 +26,5 @@ export const movingWallPosMax = Math.floor(w*0.12);
export const movingWallSpeed = Math.floor(w*0.08);
export const gameSessionIdPLACEHOLDER = "42"; // TESTING SPECTATOR PLACEHOLDER
// for testing, force gameSession.id in wsServer.ts->matchmaking()
export const gameSessionIdPLACEHOLDER = "match-id-test-42"; // TESTING SPECTATOR PLACEHOLDER
// for testing, force gameSession.id in wsServer.ts->createGameSession()

View File

@@ -19,6 +19,7 @@ export enum EventTypes {
// Client
clientAnnounce,
clientPlayerReady,
clientSpectatorReady,
clientInput,
}