From 77857a873d3b6dfa1d7d4308a230150182e382f9 Mon Sep 17 00:00:00 2001 From: batche Date: Tue, 20 Dec 2022 20:23:15 +0100 Subject: [PATCH] Vive le rouge ! --- .../game_back/src/server/class/GameSession.ts | 7 +- .../game_back/src/server/constants.ts | 2 +- .../game_back/src/server/wsServer.ts | 13 +- .../api_back/src/game/dto/createGame.dto.ts | 15 ++ .../api_back/src/game/dto/updateGame.dto.ts | 12 ++ .../api_back/src/game/entity/game.entity.ts | 6 +- .../api_back/src/game/game.controller.ts | 17 +- .../nestjs/api_back/src/game/game.service.ts | 31 ++- .../api_front/src/pages/game/Game.Luke.svelte | 186 ++++++++++++++++++ .../api_front/src/pages/game/Game.svelte | 99 ++++------ .../src/pages/game/client/class/GameArea.ts | 9 +- 11 files changed, 311 insertions(+), 86 deletions(-) create mode 100644 srcs/requirements/nestjs/api_back/src/game/dto/createGame.dto.ts create mode 100644 srcs/requirements/nestjs/api_back/src/game/dto/updateGame.dto.ts create mode 100644 srcs/requirements/svelte/api_front/src/pages/game/Game.Luke.svelte 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 78e645f5..92680332 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 @@ -82,7 +82,7 @@ export class GameSession { else if (input === en.InputEnum.down) { client.racket.dir.y = 1; } - + if (input !== en.InputEnum.noInput) { client.racket.moveAndCollide(delta, [gc.wallTop, gc.wallBottom]); } @@ -220,7 +220,7 @@ export class GameSession { } return false; } - private async _matchEnd(winner: en.PlayerSide, forfeit_flag: boolean = false) + private async _matchEnd(winner: en.PlayerSide, forfeit_flag: boolean = false) { this.matchEnded = true; let eventEnd: ev.EventMatchEnd; @@ -232,7 +232,6 @@ export class GameSession { client.socket.send(JSON.stringify(eventEnd)); }); - /* // WIP nest , send match result const gc = this.components; await fetch(c.addressBackEnd + "/game/matchEnd", { @@ -245,7 +244,7 @@ export class GameSession { scoreLeft: gc.scoreLeft, scoreRight: gc.scoreRight, }) - }); */ + }); // logs if (winner === en.PlayerSide.left) { diff --git a/srcs/requirements/game_server/game_back/src/server/constants.ts b/srcs/requirements/game_server/game_back/src/server/constants.ts index 3ab0ce0b..3ae3e722 100644 --- a/srcs/requirements/game_server/game_back/src/server/constants.ts +++ b/srcs/requirements/game_server/game_back/src/server/constants.ts @@ -9,4 +9,4 @@ export const fixedDeltaTime = serverGameLoopIntervalMS/1000; // second export const playersUpdateIntervalMS = 1000/30; // millisecond export const spectatorsUpdateIntervalMS = 1000/30; // millisecond -export const addressBackEnd = "http://backend_dev:3000"; +export const addressBackEnd = "http://backend_dev:3000/api/v2"; 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 0001b002..1bfb3761 100644 --- a/srcs/requirements/game_server/game_back/src/server/wsServer.ts +++ b/srcs/requirements/game_server/game_back/src/server/wsServer.ts @@ -66,7 +66,7 @@ async function clientAnnounceListener(this: WebSocket, data: string) if (msg.role === en.ClientRole.player) { const announce: ev.ClientAnnouncePlayer = msg; - + // WIP nest, fetch token validation const body = { playerOneUsername: announce.username, @@ -78,7 +78,7 @@ async function clientAnnounceListener(this: WebSocket, data: string) if (announce.privateMatch) { body.playerTwoUsername = announce.playerTwoUsername; } - const response = await fetch(c.addressBackEnd + "/game/validateToken", + const response = await fetch(c.addressBackEnd + "/game/gameserver/validate", { method: "POST", headers: { @@ -163,12 +163,12 @@ function publicMatchmaking(player: ClientPlayer) function privateMatchmaking(player: ClientPlayer) -{ +{ const minPlayersNumber = 2; const maxPlayersNumber = 2; privateMatchmakingMap.set(player.id, player); const matchOptions = player.matchOptions; - + const token = player.token; const compatiblePlayers: ClientPlayer[] = []; for (const [id, client] of privateMatchmakingMap) @@ -243,17 +243,18 @@ async function playerReadyConfirmationListener(this: WebSocket, data: string) { // WIP nest , send gameSession.id const gameSessionPlayersIterator = gameSession.playersMap.values(); - const response = await fetch(c.addressBackEnd + "/game/newGameSession", + const response = await fetch(c.addressBackEnd + "/game/gameserver/creategame", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ - id: gameSession.id, + gameServerIdOfTheMatch : gameSession.id, gameOptions: gameSession.matchOptions, playerOneUsername: (gameSessionPlayersIterator.next().value).username, playerTwoUsername: (gameSessionPlayersIterator.next().value).username, + }) }); if (!response.ok) diff --git a/srcs/requirements/nestjs/api_back/src/game/dto/createGame.dto.ts b/srcs/requirements/nestjs/api_back/src/game/dto/createGame.dto.ts new file mode 100644 index 00000000..86931237 --- /dev/null +++ b/srcs/requirements/nestjs/api_back/src/game/dto/createGame.dto.ts @@ -0,0 +1,15 @@ +import { IsBoolean, IsNotEmpty, IsNumber, IsString } from "class-validator"; + +export class CreateGameDto { + @IsString() + @IsNotEmpty() + gameServerIdOfTheMatch : string + @IsNumber() + @IsNotEmpty() + gameOptions: number + @IsString() + @IsNotEmpty() + playerOneUsername : string + @IsString() + playerTwoUsername : string +} diff --git a/srcs/requirements/nestjs/api_back/src/game/dto/updateGame.dto.ts b/srcs/requirements/nestjs/api_back/src/game/dto/updateGame.dto.ts new file mode 100644 index 00000000..54c89757 --- /dev/null +++ b/srcs/requirements/nestjs/api_back/src/game/dto/updateGame.dto.ts @@ -0,0 +1,12 @@ +import { IsBoolean, IsNotEmpty, IsNumber, IsString } from "class-validator"; + +export class UpdateGameDto { + @IsNumber() + @IsNotEmpty() + playerOneUsernameResult : number + @IsNumber() + @IsNotEmpty() + playerTwoUsernameResult : number + @IsBoolean() + isMatchIsFinished : boolean +} diff --git a/srcs/requirements/nestjs/api_back/src/game/entity/game.entity.ts b/srcs/requirements/nestjs/api_back/src/game/entity/game.entity.ts index edd4e673..44257efe 100644 --- a/srcs/requirements/nestjs/api_back/src/game/entity/game.entity.ts +++ b/srcs/requirements/nestjs/api_back/src/game/entity/game.entity.ts @@ -11,15 +11,15 @@ export class Game { @Column() playerTwoUsername: string - @Column() + @Column({default : 0, nullable : true}) playerOneUsernameResult : number - @Column() + @Column({default : 0, nullable : true}) playerTwoUsernameResult : number @Column() gameServerIdOfTheMatch: string - @Column({default: false}) //éric pourra trouver un meilleur mot : ongoing ? + @Column({default: false, nullable : true}) //éric pourra trouver un meilleur mot : ongoing ? isMatchIsFinished: boolean } diff --git a/srcs/requirements/nestjs/api_back/src/game/game.controller.ts b/srcs/requirements/nestjs/api_back/src/game/game.controller.ts index ff3c3ce3..da476766 100644 --- a/srcs/requirements/nestjs/api_back/src/game/game.controller.ts +++ b/srcs/requirements/nestjs/api_back/src/game/game.controller.ts @@ -1,9 +1,11 @@ import { Body, Controller, Get, HttpException, HttpStatus, Post, Req, UseGuards } from '@nestjs/common'; +import { Console } from 'console'; import { request } from 'http'; import { use } from 'passport'; import { AuthenticateGuard, TwoFactorGuard } from 'src/auth/42/guards/42guards'; import { User } from 'src/users/entities/user.entity'; import { UsersService } from 'src/users/users.service'; +import { CreateGameDto } from './dto/createGame.dto'; import { GrantTicketDto } from './dto/grantTicket.dto'; import { ValidateTicketDto } from './dto/validateTicket.dto'; import { TokenGame } from './entity/tokenGame.entity'; @@ -21,8 +23,8 @@ export class GameController { const user : User = req.user if (grantTicketDto.playerOneUsername != user.username) return new HttpException('You can\'t request a game for another person.', 403 ) - else if (user.status !== "connected") - return new HttpException('You must not be in game...', HttpStatus.FORBIDDEN ) + // else if (user.status !== "connected") + // return new HttpException('You must not be in game...', HttpStatus.FORBIDDEN ) return this.gameService.generateToken(user, grantTicketDto); } @@ -37,11 +39,12 @@ export class GameController { //N'est valable que pour le game-serveur. - @Post('gameServer/validate') + @Post('gameserver/validate') async validateTicket(@Body() validateTicketDto : ValidateTicketDto, @Req() request) { if (await this.gameService.validateToken(validateTicketDto) === false) return new HttpException("The token is not valid", HttpStatus.NOT_FOUND); + console.log("200 retourné côté nest") return HttpStatus.OK; } @@ -72,4 +75,12 @@ export class GameController { return this.gameService.findInvitations(user); } + @Post('gameserver/creategame') + async createGame(@Body() creategameDto : CreateGameDto) + { + return this.gameService.createGame(creategameDto); + } + + + } 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 2f556387..e6bb953c 100644 --- a/srcs/requirements/nestjs/api_back/src/game/game.service.ts +++ b/srcs/requirements/nestjs/api_back/src/game/game.service.ts @@ -9,6 +9,7 @@ import { Game } from './entity/game.entity'; import { ValidateTicketDto } from './dto/validateTicket.dto'; import { TokenGame } from './entity/tokenGame.entity'; import { UsersService } from 'src/users/users.service'; +import { CreateGameDto } from './dto/createGame.dto'; @Injectable() export class GameService { @@ -37,9 +38,10 @@ export class GameService { async generateToken(user : User, grantTicketDto : GrantTicketDto) { - if (user.status === "In Game") - return new HttpException("You can't play two games", HttpStatus.FORBIDDEN); - else if (grantTicketDto.isGameIsWithInvitation === true) + // if (user.status === "In Game") + // return new HttpException("You can't play two games", HttpStatus.FORBIDDEN); + // else + if (grantTicketDto.isGameIsWithInvitation === true) { const secondUser : Partial = await this.userService.findOneByUsername(user.id.toString(), grantTicketDto.playerTwoUsername) if (!secondUser) @@ -141,8 +143,8 @@ export class GameService { async declineInvitation(user : User, token : string) { - if (user.status === "In Game") - return new HttpException("You must finish your game before decline.", HttpStatus.FORBIDDEN) + // if (user.status === "In Game") + // return new HttpException("You must finish your game before decline.", HttpStatus.FORBIDDEN) const tokenGame = await this.tokenGameRepository.createQueryBuilder('tokengame') .andWhere('tokengame.playerTwoUsername = :playerTwoUsername', {playerTwoUsername : user.username}) .andWhere('tokengame.token = :token', {token : token}) @@ -154,8 +156,8 @@ export class GameService { async acceptInvitation(user : User, token : string) { - if (user.status === "In Game") - return new HttpException("You must finish your game before accept.", HttpStatus.FORBIDDEN) + // if (user.status === "In Game") + // return new HttpException("You must finish your game before accept.", HttpStatus.FORBIDDEN) const tokenGame = await this.tokenGameRepository.createQueryBuilder('tokenGame') .andWhere('tokenGame.playerTwoUsername = :playerTwoUsername', {playerTwoUsername : user.username}) .andWhere('tokenGame.token = :token', {token : token}) @@ -170,8 +172,8 @@ export class GameService { } async requestIfAnotherUserHasRespondToquestForGame(user : User, token : string) { - if (user.status === "In Game") - return new HttpException("You can't do that.", HttpStatus.BAD_REQUEST) + // if (user.status === "In Game") + // return new HttpException("You can't do that.", HttpStatus.BAD_REQUEST) const tokenGame = await this.tokenGameRepository.createQueryBuilder('tokenGame') .where('tokenGame.token = :token', {token : token}) .andWhere('tokenGame.isSecondUserAcceptedRequest = :isSecondUserAcceptedRequest', {isSecondUserAcceptedRequest : true}) @@ -183,5 +185,16 @@ export class GameService { else if (!tokenGame) return new HttpException("Not Found", HttpStatus.NOT_FOUND) } + + + async createGame(creategameDto : CreateGameDto) + { + const game = this.gameRepository.create(creategameDto) + this.gameRepository.save(game); + if (!game) + return HttpStatus.INTERNAL_SERVER_ERROR + console.log("200 retourné pour la création de partie") + return HttpStatus.OK + } } diff --git a/srcs/requirements/svelte/api_front/src/pages/game/Game.Luke.svelte b/srcs/requirements/svelte/api_front/src/pages/game/Game.Luke.svelte new file mode 100644 index 00000000..dd096e4c --- /dev/null +++ b/srcs/requirements/svelte/api_front/src/pages/game/Game.Luke.svelte @@ -0,0 +1,186 @@ + + + + + + + + +{#if optionsAreNotSet} +
+
+
+ game options +
+ + +
+
+ + +
+
+ + + + + + +
+
+ +
+
+
+
+
+

--- keys ---

+

move up: 'w' or 'up arrow'

+

move down: 's' OR 'down arrow'

+

grid on/off: 'g'

+
+{/if} + +
+ +
+ + + 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 091a3741..759d1eba 100644 --- a/srcs/requirements/svelte/api_front/src/pages/game/Game.svelte +++ b/srcs/requirements/svelte/api_front/src/pages/game/Game.svelte @@ -20,21 +20,13 @@ let user; let allUsers; - - //init function - let isSecondPlayerAnsweredYes = false; - let isSecondPlayerRefused = false; - let isSomethingWentWrong = true; - - //Game's stuff nest side let optionsAreNotSet = true; - let invite_someone = false; + let isSomeoneIsIvited = false; let playerTwoUsername = ""; - let token = ""; //Game's stuff gameserver side - let sound = ""; + let sound = "on"; let multi_balls = false; let moving_walls = false; let matchOption : enumeration.MatchOptions = enumeration.MatchOptions.noOption; @@ -44,6 +36,7 @@ let showInvitations = false; let showGameOption = true; let showError = false; + let showCanvas = false; let isThereAnyInvitation = false; let invitations; @@ -51,8 +44,6 @@ let waitingMessage = "Please wait..." let errorMessageWhenAttemptingToGetATicket = ""; - let responseToCheckIfOtherUserHasAnswered; - onMount( async() => { user = await fetch('http://transcendance:8080/api/v2/user') .then( x => x.json() ); @@ -68,23 +59,24 @@ matchOption |= enumeration.MatchOptions.multiBalls if (moving_walls === true ) matchOption |= enumeration.MatchOptions.movingWalls - const res = await fetch("http://transcendance:8080/api/v2/game/ticket", { + + const responseWhenGrantToken = fetch("http://transcendance:8080/api/v2/game/ticket", { method : "POST", headers : {'Content-Type': 'application/json'}, body : JSON.stringify({ playerOneUsername : user.username, playerTwoUsername : playerTwoUsername, gameOptions : matchOption, - isGameIsWithInvitation : invite_someone + isGameIsWithInvitation : isSomeoneIsIvited }) }) - .then(x => x.json()) - .catch(error => { - console.log(error) - }) - if (res.status === 403 || res.status === 404 || res.status === 500) + const responseFromServer = await responseWhenGrantToken; + console.log("Response.ok : " + responseFromServer.ok ) + console.log("//") + const responseInjson = await responseFromServer.json() + if (!responseFromServer.ok || !responseInjson.token) { - errorMessageWhenAttemptingToGetATicket = res.message; + errorMessageWhenAttemptingToGetATicket = responseInjson.message; showError = true; setTimeout(() => { showError = false; @@ -92,40 +84,27 @@ optionsAreNotSet = true playerTwoUsername = ""; matchOption = 0; - token = "" }, 5000) - return ; } - else if (res.status === 200) + else { - initAudio(sound) + showError = false + showWaitPage = false + const token = responseInjson.token + console.log("Token === " + token) + if (sound === "off") { + initAudio(true); + } + else if (sound === "on") { + initAudio(false); + } initMatchOptions(matchOption) initPong(new GameArea()) initGc(new GameComponentsClient(matchOption, pong.ctx)) initStartFunction(start) - initWebSocket(matchOption) + console.log("Avant init websocket") + initWebSocket(matchOption, token, user.username) } - // const fetch = await fetch("http://transcendance:8080/api/v2/game/gameServer/validate", { - // method : "POST", - // headers : {'Content-Type': 'application/json'}, - // body : JSON.stringify({ - // playerOneUsername : user.username, - // playerTwoUsername : playerTwoUsername, - // gameOptions : matchOption, - // isGameIsWithInvitation : invite_someone, - // token : token - // }) - // }) - // .then(x => x.json()) - // .catch(error => { - // console.log(error) - // }) - // if (res.status !== 200) - // { - // showError = true; - // errorMessageWhenAttemptingToGetATicket = "Your session is not valid. Please try again." - // return ; - // } } function start() : void { @@ -134,10 +113,10 @@ gc.text1.clear(); gc.text1.text = `${count}`; gc.text1.update(); - }, resume); + }, responseWhenGrantTokenume); } - function resume(): void { + function responseWhenGrantTokenume(): void { gc.text1.text = ""; window.addEventListener('keydown', function (e) { pong.addKey(e.key); @@ -160,6 +139,7 @@ showInvitations = true; invitations = await fetch("http://transcendance:8080/api/v2/game/invitations") .then(x => x.json()) + console.log(...invitations) } const rejectInvitation = async() => { @@ -188,12 +168,13 @@
.
+ {#if showError === true}
Error

{errorMessageWhenAttemptingToGetATicket}

- +
{/if} @@ -223,14 +204,18 @@
- - + + + + + +
- +
- {#if invite_someone === true} + {#if isSomeoneIsIvited === true}