Template
156 lines
4.3 KiB
TypeScript
156 lines
4.3 KiB
TypeScript
import {
|
|
Body,
|
|
Controller,
|
|
Get,
|
|
HttpException,
|
|
HttpStatus,
|
|
Param,
|
|
Post,
|
|
Session,
|
|
Sse,
|
|
UseGuards,
|
|
} from '@nestjs/common';
|
|
import { LobbyService } from '../services/lobby.service';
|
|
import { AuthGuard } from '../../users/guards/auth.guard';
|
|
import { ApiBody, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
|
|
import { Game } from '../entities/game.entity';
|
|
import { GamePipe, GameStartedPipe } from '../pipe/game.pipe';
|
|
|
|
import { Observable, fromEvent, map } from 'rxjs';
|
|
import { EventEmitter2 } from '@nestjs/event-emitter';
|
|
import { GameService } from '../services/games.service';
|
|
import { ConfigService } from '@nestjs/config';
|
|
import { SessionData } from 'express-session';
|
|
import { WordResponseDTO } from 'events/dto/wordresponse.dto';
|
|
import { WordRecieveDTO } from 'src/word/dto/wordrecieve.dto';
|
|
|
|
@ApiTags('game')
|
|
@Controller('games/:id')
|
|
export class GamesController {
|
|
constructor(
|
|
private readonly lobbyService: LobbyService,
|
|
private readonly gameService: GameService,
|
|
private eventEmitter: EventEmitter2,
|
|
private configService: ConfigService,
|
|
) {}
|
|
|
|
@Post('/start')
|
|
@ApiOperation({ summary: 'Start game' })
|
|
@ApiResponse({
|
|
status: 201,
|
|
description: 'Game successfully started.',
|
|
})
|
|
@ApiResponse({
|
|
status: 400,
|
|
description: 'Bad Request',
|
|
})
|
|
@ApiResponse({
|
|
status: 403,
|
|
description: 'You can only start games you own',
|
|
})
|
|
@UseGuards(AuthGuard)
|
|
async start(
|
|
@Param('id') id: string,
|
|
@Session() session: SessionData,
|
|
@Param('id', GamePipe) game: Game,
|
|
) {
|
|
if (game.started) {
|
|
throw new HttpException('Game already started', HttpStatus.BAD_REQUEST);
|
|
}
|
|
if (game.players.length < 2 && !this.configService.get('DEV_MODE')) {
|
|
throw new HttpException(
|
|
'Not enough teams to start the game',
|
|
HttpStatus.BAD_REQUEST,
|
|
);
|
|
}
|
|
if (game.ownerId != session.user?.id) {
|
|
throw new HttpException(
|
|
'You can only start games you own',
|
|
HttpStatus.FORBIDDEN,
|
|
);
|
|
}
|
|
await this.gameService.start(game);
|
|
return;
|
|
}
|
|
|
|
@Post('surrender')
|
|
@ApiOperation({ summary: 'Leave a game that has already started' })
|
|
@UseGuards(AuthGuard)
|
|
surrender(
|
|
@Param('id') id: string,
|
|
@Session() session: SessionData,
|
|
@Param('id', GamePipe) game: Game,
|
|
) {
|
|
if (!game.started) {
|
|
throw new HttpException('Game has not started', HttpStatus.BAD_REQUEST);
|
|
}
|
|
return this.lobbyService.leaveGame(game, session.user);
|
|
}
|
|
|
|
@Post('kick/:playerId')
|
|
@ApiOperation({ summary: 'Kick a player' })
|
|
@UseGuards(AuthGuard)
|
|
kick(
|
|
@Session() session: SessionData,
|
|
@Param('id') id: string,
|
|
@Param('id', GamePipe) game: Game,
|
|
@Param('playerId') playerId: string,
|
|
) {
|
|
if (session.user.id != game.ownerId) {
|
|
throw new HttpException(
|
|
'You do do not own this game',
|
|
HttpStatus.FORBIDDEN,
|
|
);
|
|
}
|
|
return this.lobbyService.kickPlayer(game, session.user, playerId);
|
|
}
|
|
|
|
@Get('currentWord')
|
|
@ApiOperation({ summary: 'Read Current Word' })
|
|
@UseGuards(AuthGuard)
|
|
getCurrentWord(
|
|
@Session() session: SessionData,
|
|
@Param('id') id: string,
|
|
@Param('id', GamePipe) game: Game,
|
|
) {
|
|
if (session.user.id != game.currentPlayer.userId) {
|
|
throw new HttpException(
|
|
'It is not your turn to play',
|
|
HttpStatus.FORBIDDEN,
|
|
);
|
|
}
|
|
return new WordResponseDTO(game.currentWord);
|
|
}
|
|
|
|
@Post('/message')
|
|
@ApiOperation({ summary: 'try to guess a word' })
|
|
@ApiBody({ type: WordRecieveDTO })
|
|
@UseGuards(AuthGuard)
|
|
async postMessage(
|
|
@Session() session: SessionData,
|
|
@Param('id') id: string,
|
|
@Param('id', GamePipe) game: Game,
|
|
@Body('value') value: string,
|
|
) {
|
|
const player = game.players.find((p) => p.userId == session.user.id);
|
|
if (!game.started) {
|
|
throw new HttpException('Game not started', HttpStatus.BAD_REQUEST);
|
|
}
|
|
if (!player) {
|
|
throw new HttpException('You are not in this game', HttpStatus.FORBIDDEN);
|
|
}
|
|
await this.gameService.postMessage(game, player, value);
|
|
}
|
|
|
|
@Sse('/subscribe')
|
|
subscribe(@Param('id') id: string): Observable<{ data: string }> {
|
|
return fromEvent(this.eventEmitter, 'sse.game.' + id).pipe(
|
|
map((payload: any) => {
|
|
return {
|
|
data: JSON.stringify(payload),
|
|
};
|
|
}),
|
|
);
|
|
}
|
|
}
|