From a2b21688849e1f17609ba8411178ff45666f2e34 Mon Sep 17 00:00:00 2001 From: LuckyLaszlo Date: Sun, 15 Jan 2023 02:00:42 +0100 Subject: [PATCH 1/4] improved fetch in gameServer --- .../game_back/src/server/class/GameSession.ts | 11 ++- .../game_back/src/server/wsServer.ts | 72 ++++++++++++------- .../svelte/api_front/src/pieces/utils.ts | 6 +- 3 files changed, 60 insertions(+), 29 deletions(-) diff --git a/srcs/requirements/game_server/game_back/src/server/class/GameSession.ts b/srcs/requirements/game_server/game_back/src/server/class/GameSession.ts index 8d9c77ea..830d0844 100644 --- a/srcs/requirements/game_server/game_back/src/server/class/GameSession.ts +++ b/srcs/requirements/game_server/game_back/src/server/class/GameSession.ts @@ -279,7 +279,8 @@ export class GameSession { gc.scoreRight = 0; } } - await fetch(c.addressBackEnd + "/game/gameserver/updategame", + + fetch(`${c.addressBackEnd}/game/gameserver/updategame`, { method: "POST", headers: { @@ -290,6 +291,14 @@ export class GameSession { playerOneUsernameResult: gc.scoreLeft, playerTwoUsernameResult: gc.scoreRight, }) + }) + .then((response) => { + if (!response.ok) { + throw new Error("HTTP " + response.status); + } + }) + .catch((error) => { + console.log("catch /game/gameserver/updategame: ", error); }); setTimeout(this.destroy, 15000, this); diff --git a/srcs/requirements/game_server/game_back/src/server/wsServer.ts b/srcs/requirements/game_server/game_back/src/server/wsServer.ts index 8af02ec6..98acb450 100644 --- a/srcs/requirements/game_server/game_back/src/server/wsServer.ts +++ b/srcs/requirements/game_server/game_back/src/server/wsServer.ts @@ -89,7 +89,8 @@ async function clientAnnounceListener(this: WebSocket, data: string) if (announce.privateMatch) { body.playerTwoUsername = announce.playerTwoUsername; } - const response = await fetch(c.addressBackEnd + "/game/gameserver/validate", + + fetch(`${c.addressBackEnd}/game/gameserver/validate`, { method: "POST", headers: { @@ -97,17 +98,17 @@ async function clientAnnounceListener(this: WebSocket, data: string) }, body: JSON.stringify(body) }) - .catch(error => console.log("ERROR : " + error)); - if (!response || !response.ok) - { - let errMessage = "validate token error"; - if (response) { - errMessage = (await response.json()).message; + .then((response) => { + if (!response.ok) { + throw new Error("HTTP " + response.status); } - this.send(JSON.stringify( new ev.EventError(errMessage) )); + }) + .catch((error) => { + console.log("catch /game/gameserver/validate: ", error); + this.send(JSON.stringify( new ev.EventError("validate token error") )); clientTerminate(clientsMap.get(this.id)); - return; - } + }); + player.matchOptions = announce.matchOptions; player.token = announce.token; player.username = announce.username; @@ -232,14 +233,26 @@ function privateMatchmaking(player: ClientPlayer) if (player.socket.OPEN) { player.socket.send(JSON.stringify( new ev.EventMatchAbort() )); } - const response = await fetch(c.addressBackEnd + "/game/gameserver/destroysession",{ + + fetch(`${c.addressBackEnd}/game/gameserver/destroysession`, + { method: "POST", - headers : {"Content-Type": "application/json"}, - body : JSON.stringify({ + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ token : player.token }) }) - .catch(error => console.log("ERROR : " + error)); + .then((response) => { + if (!response.ok) { + throw new Error("HTTP " + response.status); + } + }) + .catch((error) => { + console.log("catch /game/gameserver/destroysession: ", error); + }); + clientTerminate(player); } }, 60000); @@ -315,24 +328,29 @@ async function playerReadyConfirmationListener(this: WebSocket, data: string) playerOneUsernameResult : 0, playerTwoUsernameResult : 0 }; - const response = await fetch(c.addressBackEnd + "/game/gameserver/creategame", + + fetch(`${c.addressBackEnd}/game/gameserver/creategame`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(body) - }); - if (!response.ok) - { + }) + .then((response) => { + if (!response.ok) { + throw new Error("HTTP " + response.status); + } + }) + .catch((error) => { + console.log("catch /game/gameserver/creategame: ", error); gameSessionsMap.delete(gameSession.id); gameSession.playersMap.forEach((client) => { client.socket.send(JSON.stringify( new ev.EventMatchAbort() )); client.gameSession = null; clientTerminate(client); }); - return; - } + }); gameSession.playersMap.forEach( (client) => { client.socket.send(JSON.stringify( new ev.ServerEvent(en.EventTypes.matchStart) )); @@ -445,18 +463,22 @@ export async function clientTerminate(client: Client) if (client.role === en.ClientRole.player) { const player = client as ClientPlayer; - console.log("/resetuserstatus " + player.username); - const response = await fetch(c.addressBackEnd + "/game/gameserver/resetuserstatus", + fetch(`${c.addressBackEnd}/game/gameserver/resetuserstatus`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({username: player.username}) + }) + .then((response) => { + if (!response.ok) { + throw new Error("HTTP " + response.status); + } + }) + .catch((error) => { + console.log("catch /game/gameserver/resetuserstatus: ", error); }); - if (!response.ok) { - console.log("/resetuserstatus " + player.username + " failed"); - } } } diff --git a/srcs/requirements/svelte/api_front/src/pieces/utils.ts b/srcs/requirements/svelte/api_front/src/pieces/utils.ts index 76125f46..bc498c49 100644 --- a/srcs/requirements/svelte/api_front/src/pieces/utils.ts +++ b/srcs/requirements/svelte/api_front/src/pieces/utils.ts @@ -4,7 +4,7 @@ export async function fetchAvatar(username: string) return fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/avatar?username=${username}`) .then((response) => { if (!response.ok) { - throw new Error("Avatar not retrieved"); + throw new Error("HTTP " + response.status); } return response.blob(); }) @@ -22,7 +22,7 @@ export async function fetchUser() return fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user`) .then((response) => { if (!response.ok) { - throw new Error("User not retrieved"); + throw new Error("HTTP " + response.status); } return response.json(); }) @@ -40,7 +40,7 @@ export async function fetchAllUsers() return fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/all`) .then((response) => { if (!response.ok) { - throw new Error("All Users not retrieved"); + throw new Error("HTTP " + response.status); } return response.json(); }) From e3407b8a9d906e5f802d57ab90926278c3b8ae6d Mon Sep 17 00:00:00 2001 From: LuckyLaszlo Date: Sun, 15 Jan 2023 19:02:16 +0100 Subject: [PATCH 2/4] Invitations changes. Now require confirmation from both side to start game. --- .../game_back/src/server/wsServer.ts | 2 + .../src/game/entity/tokenGame.entity.ts | 2 - .../nestjs/api_back/src/game/game.service.ts | 41 +++++-------------- .../api_front/src/pages/game/Game.svelte | 38 +++++++++-------- 4 files changed, 34 insertions(+), 49 deletions(-) diff --git a/srcs/requirements/game_server/game_back/src/server/wsServer.ts b/srcs/requirements/game_server/game_back/src/server/wsServer.ts index 98acb450..e3add956 100644 --- a/srcs/requirements/game_server/game_back/src/server/wsServer.ts +++ b/srcs/requirements/game_server/game_back/src/server/wsServer.ts @@ -107,6 +107,7 @@ async function clientAnnounceListener(this: WebSocket, data: string) console.log("catch /game/gameserver/validate: ", error); this.send(JSON.stringify( new ev.EventError("validate token error") )); clientTerminate(clientsMap.get(this.id)); + return; }); player.matchOptions = announce.matchOptions; @@ -350,6 +351,7 @@ async function playerReadyConfirmationListener(this: WebSocket, data: string) client.gameSession = null; clientTerminate(client); }); + return; }); gameSession.playersMap.forEach( (client) => { diff --git a/srcs/requirements/nestjs/api_back/src/game/entity/tokenGame.entity.ts b/srcs/requirements/nestjs/api_back/src/game/entity/tokenGame.entity.ts index 9481b32e..53f6ad81 100644 --- a/srcs/requirements/nestjs/api_back/src/game/entity/tokenGame.entity.ts +++ b/srcs/requirements/nestjs/api_back/src/game/entity/tokenGame.entity.ts @@ -15,8 +15,6 @@ export class TokenGame { isGameIsWithInvitation : boolean @Column({default: 0, nullable: true}) numberOfRegisteredUser : number - @Column({default : false}) - isSecondUserAcceptedRequest : boolean @Column() token : string } diff --git a/srcs/requirements/nestjs/api_back/src/game/game.service.ts b/srcs/requirements/nestjs/api_back/src/game/game.service.ts index 4e6d4805..37297153 100644 --- a/srcs/requirements/nestjs/api_back/src/game/game.service.ts +++ b/srcs/requirements/nestjs/api_back/src/game/game.service.ts @@ -72,10 +72,11 @@ export class GameService { return encryptedTextToReturn } - async deleteToken(user : User){ + async deletePublicTokens(user : User){ const tokenGame = await this.tokenGameRepository.createQueryBuilder('tokengame') .where('tokengame.playerTwoUsername = :playerTwoUsername', {playerTwoUsername : user.username}) .orWhere('tokengame.playerOneUsername = :playerOneUsername', {playerOneUsername : user.username}) + .where('tokengame.isGameIsWithInvitation = :isGameIsWithInvitation', {isGameIsWithInvitation : false}) .getMany(); if (tokenGame) return this.tokenGameRepository.remove(tokenGame); @@ -86,7 +87,7 @@ export class GameService { console.log(user.status); if (user.status === STATUS.IN_POOL || user.status === STATUS.IN_GAME) { - await this.deleteToken(user); + await this.deletePublicTokens(user); if (user.status === STATUS.IN_POOL) { user.status = STATUS.CONNECTED; } @@ -106,7 +107,6 @@ export class GameService { const encryptedTextToReturn = await this.encryptToken(user.username + '_' + secondUser.username + '_' + grantTicketDto.gameOptions + '_' + grantTicketDto.isGameIsWithInvitation + '_' + new Date()) const tok = this.tokenGameRepository.create(grantTicketDto); - tok.isSecondUserAcceptedRequest = false; tok.numberOfRegisteredUser = 0; tok.token = encryptedTextToReturn; this.tokenGameRepository.save(tok); @@ -130,34 +130,30 @@ export class GameService { async validateToken(validateTicketDto : ValidateTicketDto) { if (validateTicketDto.isGameIsWithInvitation === true) { + console.log("validateToken() PRIVATE"); const tokenGame : TokenGame = await this.tokenGameRepository.createQueryBuilder('tokengame') .where('tokengame.playerOneUsername = :playerOneUsername', {playerOneUsername : validateTicketDto.playerOneUsername}) .andWhere('tokengame.playerTwoUsername = :playerTwoUsername', {playerTwoUsername : validateTicketDto.playerTwoUsername}) .andWhere('tokengame.gameOptions = :gameOption', {gameOption : validateTicketDto.gameOptions}) .andWhere('tokengame.isGameIsWithInvitation = :isGameIsWithInvitation', {isGameIsWithInvitation: true}) - .andWhere('tokengame.isSecondUserAcceptedRequest = :choice', {choice : true}) .andWhere('tokengame.token = :token', {token : validateTicketDto.token}) .getOne(); if (tokenGame) { + console.log("playerOneUsername: " + tokenGame.playerOneUsername + "| playerTwoUsername: " + tokenGame.playerTwoUsername); + tokenGame.numberOfRegisteredUser++; + this.tokenGameRepository.save(tokenGame); if (tokenGame.numberOfRegisteredUser === 2) { this.tokenGameRepository.remove(tokenGame) - const userOne : User = await this.userRepository.createQueryBuilder('user') - .where("user.username = :username", {username : tokenGame.playerOneUsername}) - .getOne(); - const userTwo : User = await this.userRepository.createQueryBuilder('user') - .where("user.username = :username", {username : tokenGame.playerTwoUsername}) - .getOne(); - this.deleteToken(userOne) - this.deleteToken(userTwo) } return true; } } else if (validateTicketDto.isGameIsWithInvitation === false) { + console.log("validateToken() PUBLIC"); const tokenGame : TokenGame = await this.tokenGameRepository.createQueryBuilder('tokengame') .where('tokengame.playerOneUsername = :playerOneUsername', {playerOneUsername : validateTicketDto.playerOneUsername}) .andWhere('tokengame.gameOptions = :gameOption', {gameOption : validateTicketDto.gameOptions}) @@ -168,10 +164,6 @@ export class GameService { { this.tokenGameRepository.remove(tokenGame) console.log("USERNAME : " + tokenGame.playerOneUsername) - const user : User = await this.userRepository.createQueryBuilder('user') - .where("user.username = :username", {username : tokenGame.playerOneUsername}) - .getOne(); - this.deleteToken(user) return true; } } @@ -181,8 +173,8 @@ export class GameService { async findInvitations(user : User, @Res() res : Response) { const game = await this.tokenGameRepository.createQueryBuilder('tokengame') .where('tokengame.playerTwoUsername = :playerTwoUsername', {playerTwoUsername : user.username}) + .orWhere('tokengame.playerOneUsername = :playerOneUsername', {playerOneUsername : user.username}) .andWhere('tokengame.isGameIsWithInvitation = :invit', {invit : true}) - .andWhere('tokengame.isSecondUserAcceptedRequest = :choice', {choice : false}) .getMany(); if (!game) return res.status(HttpStatus.NOT_FOUND).send({message : "No invitation found"}); @@ -200,14 +192,9 @@ export class GameService { async declineInvitation(user : User, token : string, @Res() res : Response) { - /* Luke: le check de user.status n'est pas fonctionnel avec l'implémentation des invitations dans le front. - Ça me semble dispensable, je désactive donc pour le moment plutôt que de refaire l'implémentation front. */ - // if (user.status !== STATUS.CONNECTED) - // return res.status(HttpStatus.FORBIDDEN).json({message : "You must not be in game to decline an invitation"}); console.log("On décline l'invitation") const tokenGame = await this.tokenGameRepository.createQueryBuilder('tokengame') - .andWhere('tokengame.playerTwoUsername = :playerTwoUsername', {playerTwoUsername : user.username}) - .andWhere('tokengame.token = :token', {token : token}) + .where('tokengame.token = :token', {token : token}) .getOne(); if (tokenGame) { @@ -238,17 +225,11 @@ export class GameService { async acceptInvitation(user : User, token : string, @Res() res : Response) { - /* Luke: le check de user.status n'est pas fonctionnel avec l'implémentation des invitations dans le front. - Ça me semble dispensable, je désactive donc pour le moment plutôt que de refaire l'implémentation front. */ - // if (user.status !== STATUS.CONNECTED) - // return res.status(HttpStatus.FORBIDDEN).send("") const tokenGame = await this.tokenGameRepository.createQueryBuilder('tokenGame') - .andWhere('tokenGame.playerTwoUsername = :playerTwoUsername', {playerTwoUsername : user.username}) - .andWhere('tokenGame.token = :token', {token : token}) + .where('tokenGame.token = :token', {token : token}) .getOne(); if (tokenGame) { - tokenGame.isSecondUserAcceptedRequest = true; this.tokenGameRepository.save(tokenGame) return res.status(HttpStatus.OK).json({message : "Invitation accepted."}); } diff --git a/srcs/requirements/svelte/api_front/src/pages/game/Game.svelte b/srcs/requirements/svelte/api_front/src/pages/game/Game.svelte index 87933cc8..62aa8725 100644 --- a/srcs/requirements/svelte/api_front/src/pages/game/Game.svelte +++ b/srcs/requirements/svelte/api_front/src/pages/game/Game.svelte @@ -24,7 +24,6 @@ //boolean for html page let hiddenGame = true; - let optionsAreNotSet = true; let showGameOptions = true; let showInvitations = false; let showError = false; @@ -63,7 +62,6 @@ function resetPage() { hiddenGame = true; - optionsAreNotSet = true; showGameOptions = true; showInvitations = false; showError = false; @@ -74,7 +72,6 @@ const initGame = async() => { - optionsAreNotSet = false; showWaitPage = true; const matchOptions = pong.computeMatchOptions(options); try { @@ -91,13 +88,18 @@ console.log("status : " + response.status); const responseBody = await response.json(); const token : string = responseBody.token; - showWaitPage = false; if (response.ok && token) { - watchMatchStartInterval = setInterval(watchMatchStart, watchMatchStartIntervalRate); - watchGameStateInterval = setInterval(watchGameState, watchGameStateIntervalRate); - pong.init(matchOptions, options, gameAreaId, token); - hiddenGame = false; + if (options.isSomeoneIsInvited) { + options.reset(user.username); + fetchInvitations(); + } + else { + watchMatchStartInterval = setInterval(watchMatchStart, watchMatchStartIntervalRate); + watchGameStateInterval = setInterval(watchGameState, watchGameStateIntervalRate); + pong.init(matchOptions, options, gameAreaId, token); + hiddenGame = false; + } } else { @@ -107,7 +109,6 @@ showError = true; options.reset(user.username); setTimeout(() => { - optionsAreNotSet = true; showError = false; errorMessage = ""; }, 5000); @@ -115,11 +116,11 @@ } catch (e) { console.log(e); } + showWaitPage = false; } - const initGameForInvitedPlayer = async(invitation : any) => + const initInvitationGame = async(invitation : any) => { - optionsAreNotSet = false; showWaitPage = true; console.log("invitation : "); console.log(invitation); @@ -130,7 +131,9 @@ options.playerOneUsername = invitation.playerOneUsername; options.playerTwoUsername = invitation.playerTwoUsername; options.isSomeoneIsInvited = true; - options.isInvitedPerson = true; + if (user.username === invitation.playerTwoUsername) { + options.isInvitedPerson = true; + } pong.init(invitation.gameOptions, options, gameAreaId, invitation.token); showWaitPage = false; hiddenGame = false; @@ -169,10 +172,11 @@ } const fetchInvitations = async() => { - showGameOptions = false; - showInvitations = true; + console.log("fetchInvitations"); invitations = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/game/invitations`) .then(x => x.json()); + showGameOptions = false; + showInvitations = true; } const rejectInvitation = async(invitation) => { @@ -199,7 +203,7 @@ }).catch(error => console.log(error)); if (res && res.ok) { - initGameForInvitedPlayer(invitation); + initInvitationGame(invitation); } } @@ -273,7 +277,7 @@ - {#if optionsAreNotSet} + {#if hiddenGame} {#if showGameOptions}
@@ -332,7 +336,7 @@ {#if invitations.length !== 0} {#each invitations as invitation}
- {invitation.playerOneUsername} has invited you to play a pong ! + {invitation.playerOneUsername} VS {invitation.playerTwoUsername}
From 1a07065f6abf7e9003ffdb8e4c394096ec967044 Mon Sep 17 00:00:00 2001 From: LuckyLaszlo Date: Sun, 15 Jan 2023 20:52:08 +0100 Subject: [PATCH 3/4] CSS smalls changes (headers, ranking colors) + mode "cinema" in Game.svelte --- .../svelte/api_front/public/global.css | 3 ++ .../api_front/src/pages/SplashPage.svelte | 10 ------- .../api_front/src/pages/game/Game.svelte | 30 +++++++++---------- .../src/pages/game/GameSpectator.svelte | 25 ++++++++-------- .../api_front/src/pages/game/Ranking.svelte | 13 +++----- .../svelte/api_front/src/pieces/Header.svelte | 15 ++-------- 6 files changed, 36 insertions(+), 60 deletions(-) diff --git a/srcs/requirements/svelte/api_front/public/global.css b/srcs/requirements/svelte/api_front/public/global.css index b07ffb9c..d949db3b 100644 --- a/srcs/requirements/svelte/api_front/public/global.css +++ b/srcs/requirements/svelte/api_front/public/global.css @@ -1,4 +1,7 @@ +.dim_background { + background-color: #222; +} html, body { position: relative; diff --git a/srcs/requirements/svelte/api_front/src/pages/SplashPage.svelte b/srcs/requirements/svelte/api_front/src/pages/SplashPage.svelte index f3dccddf..c944f34e 100644 --- a/srcs/requirements/svelte/api_front/src/pages/SplashPage.svelte +++ b/srcs/requirements/svelte/api_front/src/pages/SplashPage.svelte @@ -42,16 +42,6 @@
diff --git a/srcs/requirements/svelte/api_front/src/pieces/Header.svelte b/srcs/requirements/svelte/api_front/src/pieces/Header.svelte index 9dfb38f1..35aa8e7d 100644 --- a/srcs/requirements/svelte/api_front/src/pieces/Header.svelte +++ b/srcs/requirements/svelte/api_front/src/pieces/Header.svelte @@ -34,24 +34,13 @@