|
@ -1,5 +1,5 @@ |
|
|
import { UsePipes, ValidationPipe } from '@nestjs/common' |
|
|
import { UsePipes, ValidationPipe } from '@nestjs/common' |
|
|
import { type WebSocket } from 'ws' |
|
|
import { Socket } from 'socket.io' |
|
|
import { |
|
|
import { |
|
|
ConnectedSocket, |
|
|
ConnectedSocket, |
|
|
MessageBody, |
|
|
MessageBody, |
|
@ -8,10 +8,8 @@ import { |
|
|
SubscribeMessage, |
|
|
SubscribeMessage, |
|
|
WebSocketGateway |
|
|
WebSocketGateway |
|
|
} from '@nestjs/websockets' |
|
|
} from '@nestjs/websockets' |
|
|
import { randomUUID } from 'crypto' |
|
|
|
|
|
|
|
|
|
|
|
import { Games } from './game/Games' |
|
|
import { Games } from './game/Games' |
|
|
import { formatWebsocketData } from './game/utils' |
|
|
|
|
|
import { GAME_EVENTS } from './game/constants' |
|
|
import { GAME_EVENTS } from './game/constants' |
|
|
import { GameCreationDtoValidated } from './dtos/GameCreationDtoValidated' |
|
|
import { GameCreationDtoValidated } from './dtos/GameCreationDtoValidated' |
|
|
import { type Game } from './game/Game' |
|
|
import { type Game } from './game/Game' |
|
@ -23,11 +21,9 @@ import { MatchmakingDtoValidated } from './dtos/MatchmakingDtoValidated' |
|
|
import { PongService } from './pong.service' |
|
|
import { PongService } from './pong.service' |
|
|
import { UsersService } from 'src/users/users.service' |
|
|
import { UsersService } from 'src/users/users.service' |
|
|
|
|
|
|
|
|
interface WebSocketWithId extends WebSocket { |
|
|
@WebSocketGateway({ |
|
|
id: string |
|
|
cors: { origin: /^(http|ws):\/\/localhost(:\d+)?$/ } |
|
|
} |
|
|
}) |
|
|
|
|
|
|
|
|
@WebSocketGateway() |
|
|
|
|
|
export class PongGateway implements OnGatewayConnection, OnGatewayDisconnect { |
|
|
export class PongGateway implements OnGatewayConnection, OnGatewayDisconnect { |
|
|
constructor ( |
|
|
constructor ( |
|
|
private readonly pongService: PongService, |
|
|
private readonly pongService: PongService, |
|
@ -35,25 +31,18 @@ export class PongGateway implements OnGatewayConnection, OnGatewayDisconnect { |
|
|
) {} |
|
|
) {} |
|
|
|
|
|
|
|
|
private readonly games: Games = new Games(this.pongService) |
|
|
private readonly games: Games = new Games(this.pongService) |
|
|
private readonly socketToPlayerName = new Map<WebSocketWithId, string>() |
|
|
private readonly socketToPlayerName = new Map<Socket, string>() |
|
|
private readonly matchmakingQueue = new MatchmakingQueue(this.games) |
|
|
private readonly matchmakingQueue = new MatchmakingQueue(this.games) |
|
|
|
|
|
|
|
|
playerIsRegistered (name: string): boolean { |
|
|
playerIsRegistered (name: string): boolean { |
|
|
return Array.from(this.socketToPlayerName.values()).includes(name) |
|
|
return Array.from(this.socketToPlayerName.values()).includes(name) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@UsePipes(new ValidationPipe({ whitelist: true })) |
|
|
handleConnection (): void {} |
|
|
handleConnection ( |
|
|
|
|
|
@ConnectedSocket() |
|
|
|
|
|
client: WebSocketWithId |
|
|
|
|
|
): void { |
|
|
|
|
|
const uuid = randomUUID() |
|
|
|
|
|
client.id = uuid |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
handleDisconnect ( |
|
|
handleDisconnect ( |
|
|
@ConnectedSocket() |
|
|
@ConnectedSocket() |
|
|
client: WebSocketWithId |
|
|
client: Socket |
|
|
): void { |
|
|
): void { |
|
|
const name: string | undefined = this.socketToPlayerName.get(client) |
|
|
const name: string | undefined = this.socketToPlayerName.get(client) |
|
|
const game: Game | undefined = this.games.playerGame(name) |
|
|
const game: Game | undefined = this.games.playerGame(name) |
|
@ -71,7 +60,7 @@ export class PongGateway implements OnGatewayConnection, OnGatewayDisconnect { |
|
|
@SubscribeMessage(GAME_EVENTS.REGISTER_PLAYER) |
|
|
@SubscribeMessage(GAME_EVENTS.REGISTER_PLAYER) |
|
|
async registerPlayer ( |
|
|
async registerPlayer ( |
|
|
@ConnectedSocket() |
|
|
@ConnectedSocket() |
|
|
client: WebSocketWithId, |
|
|
client: Socket, |
|
|
@MessageBody('playerName') playerName: StringDtoValidated, |
|
|
@MessageBody('playerName') playerName: StringDtoValidated, |
|
|
@MessageBody('socketKey') socketKey: StringDtoValidated |
|
|
@MessageBody('socketKey') socketKey: StringDtoValidated |
|
|
): Promise<{ event: string, data: boolean }> { |
|
|
): Promise<{ event: string, data: boolean }> { |
|
@ -92,15 +81,10 @@ export class PongGateway implements OnGatewayConnection, OnGatewayDisconnect { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@SubscribeMessage(GAME_EVENTS.GET_GAME_INFO) |
|
|
@SubscribeMessage(GAME_EVENTS.GET_GAME_INFO) |
|
|
getPlayerCount (@ConnectedSocket() client: WebSocketWithId): void { |
|
|
getPlayerCount (@ConnectedSocket() client: Socket): void { |
|
|
const name: string | undefined = this.socketToPlayerName.get(client) |
|
|
const name: string | undefined = this.socketToPlayerName.get(client) |
|
|
if (name !== undefined) { |
|
|
if (name !== undefined) { |
|
|
client.send( |
|
|
client.emit(GAME_EVENTS.GET_GAME_INFO, this.games.getGameInfo(name)) |
|
|
formatWebsocketData( |
|
|
|
|
|
GAME_EVENTS.GET_GAME_INFO, |
|
|
|
|
|
this.games.getGameInfo(name) |
|
|
|
|
|
) |
|
|
|
|
|
) |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -108,7 +92,7 @@ export class PongGateway implements OnGatewayConnection, OnGatewayDisconnect { |
|
|
@SubscribeMessage(GAME_EVENTS.PLAYER_MOVE) |
|
|
@SubscribeMessage(GAME_EVENTS.PLAYER_MOVE) |
|
|
movePlayer ( |
|
|
movePlayer ( |
|
|
@ConnectedSocket() |
|
|
@ConnectedSocket() |
|
|
client: WebSocketWithId, |
|
|
client: Socket, |
|
|
@MessageBody() position: PointDtoValidated |
|
|
@MessageBody() position: PointDtoValidated |
|
|
): void { |
|
|
): void { |
|
|
const realPosition: PointDtoValidated = plainToClass( |
|
|
const realPosition: PointDtoValidated = plainToClass( |
|
@ -123,7 +107,7 @@ export class PongGateway implements OnGatewayConnection, OnGatewayDisconnect { |
|
|
@SubscribeMessage(GAME_EVENTS.CREATE_GAME) |
|
|
@SubscribeMessage(GAME_EVENTS.CREATE_GAME) |
|
|
createGame ( |
|
|
createGame ( |
|
|
@ConnectedSocket() |
|
|
@ConnectedSocket() |
|
|
client: WebSocketWithId, |
|
|
client: Socket, |
|
|
@MessageBody() gameCreationDto: GameCreationDtoValidated |
|
|
@MessageBody() gameCreationDto: GameCreationDtoValidated |
|
|
): { event: string, data: boolean } { |
|
|
): { event: string, data: boolean } { |
|
|
const realGameCreationDto: GameCreationDtoValidated = plainToClass( |
|
|
const realGameCreationDto: GameCreationDtoValidated = plainToClass( |
|
@ -132,14 +116,14 @@ export class PongGateway implements OnGatewayConnection, OnGatewayDisconnect { |
|
|
) |
|
|
) |
|
|
|
|
|
|
|
|
if (this.socketToPlayerName.size >= 2) { |
|
|
if (this.socketToPlayerName.size >= 2) { |
|
|
const player1Socket: WebSocketWithId | undefined = Array.from( |
|
|
const player1Socket: Socket | undefined = Array.from( |
|
|
this.socketToPlayerName.keys() |
|
|
this.socketToPlayerName.keys() |
|
|
).find( |
|
|
).find( |
|
|
(key) => |
|
|
(key) => |
|
|
this.socketToPlayerName.get(key) === |
|
|
this.socketToPlayerName.get(key) === |
|
|
realGameCreationDto.playerNames[0] |
|
|
realGameCreationDto.playerNames[0] |
|
|
) |
|
|
) |
|
|
const player2Socket: WebSocketWithId | undefined = Array.from( |
|
|
const player2Socket: Socket | undefined = Array.from( |
|
|
this.socketToPlayerName.keys() |
|
|
this.socketToPlayerName.keys() |
|
|
).find( |
|
|
).find( |
|
|
(key) => |
|
|
(key) => |
|
@ -153,6 +137,9 @@ export class PongGateway implements OnGatewayConnection, OnGatewayDisconnect { |
|
|
(client.id === player1Socket.id || client.id === player2Socket.id) && |
|
|
(client.id === player1Socket.id || client.id === player2Socket.id) && |
|
|
player1Socket.id !== player2Socket.id |
|
|
player1Socket.id !== player2Socket.id |
|
|
) { |
|
|
) { |
|
|
|
|
|
this.matchmakingQueue.removePlayer(realGameCreationDto.playerNames[0]) |
|
|
|
|
|
this.matchmakingQueue.removePlayer(realGameCreationDto.playerNames[1]) |
|
|
|
|
|
|
|
|
const ranked = false |
|
|
const ranked = false |
|
|
this.games.newGame( |
|
|
this.games.newGame( |
|
|
[player1Socket, player2Socket], |
|
|
[player1Socket, player2Socket], |
|
@ -169,7 +156,7 @@ export class PongGateway implements OnGatewayConnection, OnGatewayDisconnect { |
|
|
@SubscribeMessage(GAME_EVENTS.READY) |
|
|
@SubscribeMessage(GAME_EVENTS.READY) |
|
|
ready ( |
|
|
ready ( |
|
|
@ConnectedSocket() |
|
|
@ConnectedSocket() |
|
|
client: WebSocketWithId |
|
|
client: Socket |
|
|
): { event: string, data: boolean } { |
|
|
): { event: string, data: boolean } { |
|
|
let succeeded: boolean = false |
|
|
let succeeded: boolean = false |
|
|
const name: string | undefined = this.socketToPlayerName.get(client) |
|
|
const name: string | undefined = this.socketToPlayerName.get(client) |
|
@ -184,7 +171,7 @@ export class PongGateway implements OnGatewayConnection, OnGatewayDisconnect { |
|
|
@SubscribeMessage(GAME_EVENTS.MATCHMAKING) |
|
|
@SubscribeMessage(GAME_EVENTS.MATCHMAKING) |
|
|
updateMatchmaking ( |
|
|
updateMatchmaking ( |
|
|
@ConnectedSocket() |
|
|
@ConnectedSocket() |
|
|
client: WebSocketWithId, |
|
|
client: Socket, |
|
|
@MessageBody() matchmakingUpdateData: MatchmakingDtoValidated |
|
|
@MessageBody() matchmakingUpdateData: MatchmakingDtoValidated |
|
|
): { event: string, data: MatchmakingDtoValidated } { |
|
|
): { event: string, data: MatchmakingDtoValidated } { |
|
|
let matchmaking: boolean = false |
|
|
let matchmaking: boolean = false |
|
@ -207,7 +194,7 @@ export class PongGateway implements OnGatewayConnection, OnGatewayDisconnect { |
|
|
@SubscribeMessage(GAME_EVENTS.LEAVE_GAME) |
|
|
@SubscribeMessage(GAME_EVENTS.LEAVE_GAME) |
|
|
leaveGame ( |
|
|
leaveGame ( |
|
|
@ConnectedSocket() |
|
|
@ConnectedSocket() |
|
|
client: WebSocketWithId |
|
|
client: Socket |
|
|
): void { |
|
|
): void { |
|
|
const name: string | undefined = this.socketToPlayerName.get(client) |
|
|
const name: string | undefined = this.socketToPlayerName.get(client) |
|
|
if (name !== undefined) { |
|
|
if (name !== undefined) { |
|
|