This commit is contained in:
@@ -14,13 +14,15 @@ import { AuthGuard } from '../guards/auth.guard';
|
|||||||
import { ApiOperation, ApiTags } from '@nestjs/swagger';
|
import { ApiOperation, ApiTags } from '@nestjs/swagger';
|
||||||
import { StartingDeckDto } from '../dto/update-game.dto';
|
import { StartingDeckDto } from '../dto/update-game.dto';
|
||||||
import { Game } from '../schemas/game.schema';
|
import { Game } from '../schemas/game.schema';
|
||||||
import { Document } from 'mongoose';
|
import mongoose, { Document } from 'mongoose';
|
||||||
import { GamePipe, GameStartedPipe } from '../pipe/game.pipe';
|
import { GamePipe, GameStartedPipe } from '../pipe/game.pipe';
|
||||||
|
|
||||||
import { Observable, fromEvent, map } from 'rxjs';
|
import { Observable, fromEvent, map } from 'rxjs';
|
||||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||||
import { GameService } from '../services/games.service';
|
import { GameService } from '../services/games.service';
|
||||||
import { getCurrentTeam, getPlayer, isInTeam } from '../utils';
|
import { getCurrentTeam, getPlayer, isInTeam, WithTransaction } from '../utils';
|
||||||
|
import { User } from 'src/users/schemas/user.entity';
|
||||||
|
import { ReadTeamDto } from '../dto/read-games.dto';
|
||||||
|
|
||||||
@ApiTags('game')
|
@ApiTags('game')
|
||||||
@Controller('games/:id')
|
@Controller('games/:id')
|
||||||
@@ -75,6 +77,41 @@ export class GamesController {
|
|||||||
await this.gameService.endTurn(game);
|
await this.gameService.endTurn(game);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Post(':id/leave')
|
||||||
|
@ApiOperation({ summary: "Leave a game that hasn't already started" })
|
||||||
|
@UseGuards(AuthGuard)
|
||||||
|
async leave(
|
||||||
|
@Param('id') id: string,
|
||||||
|
@Session() session: Record<string, any>,
|
||||||
|
@Param('id', GamePipe) game: Document<Game> & Game,
|
||||||
|
) {
|
||||||
|
if (game.started) {
|
||||||
|
throw new HttpException('Game already started', HttpStatus.BAD_REQUEST);
|
||||||
|
}
|
||||||
|
return await this.gameService.leaveGame(game, session.user);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post(':id/kick/:playerId')
|
||||||
|
@ApiOperation({ summary: 'Kick a player' })
|
||||||
|
@UseGuards(AuthGuard)
|
||||||
|
async kick(
|
||||||
|
@Param('id') id: string,
|
||||||
|
@Session() session: Record<string, any>,
|
||||||
|
@Param('id', GamePipe) game: Document<Game> & Game,
|
||||||
|
@Param('playerId') playerId: string,
|
||||||
|
) {
|
||||||
|
if (game.started) {
|
||||||
|
throw new HttpException('Game already started', HttpStatus.BAD_REQUEST);
|
||||||
|
}
|
||||||
|
if (session.user.userId != game.owner.userId) {
|
||||||
|
throw new HttpException(
|
||||||
|
'You do do not own this game',
|
||||||
|
HttpStatus.FORBIDDEN,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return await this.gameService.kickPlayer(game, session.user, playerId);
|
||||||
|
}
|
||||||
|
|
||||||
@Sse('/subscribe')
|
@Sse('/subscribe')
|
||||||
subscribe(
|
subscribe(
|
||||||
@Param('id') id: string,
|
@Param('id') id: string,
|
||||||
|
|||||||
@@ -180,39 +180,4 @@ export class LobbyController {
|
|||||||
}
|
}
|
||||||
return await this.lobbyService.joinGame(game, session.user);
|
return await this.lobbyService.joinGame(game, session.user);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post(':id/leave')
|
|
||||||
@ApiOperation({ summary: "Leave a game that hasn't already started" })
|
|
||||||
@UseGuards(AuthGuard)
|
|
||||||
async leave(
|
|
||||||
@Param('id') id: string,
|
|
||||||
@Session() session: Record<string, any>,
|
|
||||||
@Param('id', GamePipe) game: Document<Game> & Game,
|
|
||||||
) {
|
|
||||||
if (game.started) {
|
|
||||||
throw new HttpException('Game already started', HttpStatus.BAD_REQUEST);
|
|
||||||
}
|
|
||||||
return await this.lobbyService.leaveGame(game, session.user);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Post(':id/kick/:playerId')
|
|
||||||
@ApiOperation({ summary: 'Kick a player' })
|
|
||||||
@UseGuards(AuthGuard)
|
|
||||||
async kick(
|
|
||||||
@Param('id') id: string,
|
|
||||||
@Session() session: Record<string, any>,
|
|
||||||
@Param('id', GamePipe) game: Document<Game> & Game,
|
|
||||||
@Param('playerId') playerId: string,
|
|
||||||
) {
|
|
||||||
if (game.started) {
|
|
||||||
throw new HttpException('Game already started', HttpStatus.BAD_REQUEST);
|
|
||||||
}
|
|
||||||
if (session.user.userId != game.owner.userId) {
|
|
||||||
throw new HttpException(
|
|
||||||
'You do do not own this game',
|
|
||||||
HttpStatus.FORBIDDEN,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return await this.lobbyService.kickPlayer(game, session.user, playerId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,62 +74,6 @@ export class LobbyService {
|
|||||||
return 'true!';
|
return 'true!';
|
||||||
}
|
}
|
||||||
|
|
||||||
@WithTransaction
|
|
||||||
async leaveGame(
|
|
||||||
game: Document<Game> & Game,
|
|
||||||
user: User,
|
|
||||||
session?: mongoose.mongo.ClientSession,
|
|
||||||
) {
|
|
||||||
const team = game.teams.find((t) =>
|
|
||||||
t.players.find((p) => p.user._id.equals(user._id)),
|
|
||||||
);
|
|
||||||
if (team == undefined) {
|
|
||||||
throw new HttpException('User not in game', HttpStatus.FORBIDDEN);
|
|
||||||
}
|
|
||||||
if (game.owner._id.equals(user._id)) {
|
|
||||||
throw new HttpException(
|
|
||||||
'You cannot leave a game you own',
|
|
||||||
HttpStatus.FORBIDDEN,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const player = team.players.find((p) => p.user._id.equals(user._id));
|
|
||||||
await this.kickPlayer(game, game.owner, player._id.toHexString(), session);
|
|
||||||
}
|
|
||||||
|
|
||||||
@WithTransaction
|
|
||||||
async kickPlayer(
|
|
||||||
game: Document<Game> & Game,
|
|
||||||
user: User,
|
|
||||||
kickedPlayerId: string,
|
|
||||||
session?: mongoose.mongo.ClientSession,
|
|
||||||
) {
|
|
||||||
const team = game.teams.find((t) =>
|
|
||||||
t.players.find((p) => p._id.equals(kickedPlayerId)),
|
|
||||||
);
|
|
||||||
if (team == undefined) {
|
|
||||||
throw new HttpException('User not in game', HttpStatus.FORBIDDEN);
|
|
||||||
}
|
|
||||||
const index = team.players.findIndex((p) => p.user._id.equals(user._id));
|
|
||||||
team.players.splice(index, 1);
|
|
||||||
this.eventEmitter.emit('sse.lobby', {
|
|
||||||
type: 'leaveTeam',
|
|
||||||
playerId: kickedPlayerId,
|
|
||||||
team: new ReadTeamDto(team),
|
|
||||||
game: game._id.toHexString(),
|
|
||||||
});
|
|
||||||
this.eventEmitter.emit('sse.game.' + game._id.toHexString(), {
|
|
||||||
type: 'leaveTeam',
|
|
||||||
team: new ReadTeamDto(team),
|
|
||||||
playerId: kickedPlayerId,
|
|
||||||
});
|
|
||||||
if (team.players.length == 0) {
|
|
||||||
const teamIndex = game.teams.indexOf(team);
|
|
||||||
game.teams.splice(teamIndex, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
await game.save({ session });
|
|
||||||
}
|
|
||||||
|
|
||||||
async findAll(): Promise<ReadGameDto[]> {
|
async findAll(): Promise<ReadGameDto[]> {
|
||||||
const games = await this.gameModel.find().exec();
|
const games = await this.gameModel.find().exec();
|
||||||
return await Promise.all(
|
return await Promise.all(
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import { EventEmitter2 } from '@nestjs/event-emitter';
|
|||||||
import { WithTransaction, getCurrentTeam, shuffle } from '../utils';
|
import { WithTransaction, getCurrentTeam, shuffle } from '../utils';
|
||||||
import { TurnService } from './turn.service';
|
import { TurnService } from './turn.service';
|
||||||
import { CardRole, CardType } from 'src/cards/schemas/cards.types';
|
import { CardRole, CardType } from 'src/cards/schemas/cards.types';
|
||||||
|
import { User } from 'src/users/schemas/user.entity';
|
||||||
|
import { ReadTeamDto } from '../dto/read-games.dto';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class GameService {
|
export class GameService {
|
||||||
@@ -290,6 +292,62 @@ export class GameService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@WithTransaction
|
||||||
|
async leaveGame(
|
||||||
|
game: Document<Game> & Game,
|
||||||
|
user: User,
|
||||||
|
session?: mongoose.mongo.ClientSession,
|
||||||
|
) {
|
||||||
|
const team = game.teams.find((t) =>
|
||||||
|
t.players.find((p) => p.user._id.equals(user._id)),
|
||||||
|
);
|
||||||
|
if (team == undefined) {
|
||||||
|
throw new HttpException('User not in game', HttpStatus.FORBIDDEN);
|
||||||
|
}
|
||||||
|
if (game.owner._id.equals(user._id)) {
|
||||||
|
throw new HttpException(
|
||||||
|
'You cannot leave a game you own',
|
||||||
|
HttpStatus.FORBIDDEN,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const player = team.players.find((p) => p.user._id.equals(user._id));
|
||||||
|
await this.kickPlayer(game, game.owner, player._id.toHexString(), session);
|
||||||
|
}
|
||||||
|
|
||||||
|
@WithTransaction
|
||||||
|
async kickPlayer(
|
||||||
|
game: Document<Game> & Game,
|
||||||
|
user: User,
|
||||||
|
kickedPlayerId: string,
|
||||||
|
session?: mongoose.mongo.ClientSession,
|
||||||
|
) {
|
||||||
|
const team = game.teams.find((t) =>
|
||||||
|
t.players.find((p) => p._id.equals(kickedPlayerId)),
|
||||||
|
);
|
||||||
|
if (team == undefined) {
|
||||||
|
throw new HttpException('User not in game', HttpStatus.FORBIDDEN);
|
||||||
|
}
|
||||||
|
const index = team.players.findIndex((p) => p.user._id.equals(user._id));
|
||||||
|
team.players.splice(index, 1);
|
||||||
|
this.eventEmitter.emit('sse.lobby', {
|
||||||
|
type: 'leaveTeam',
|
||||||
|
playerId: kickedPlayerId,
|
||||||
|
team: new ReadTeamDto(team),
|
||||||
|
game: game._id.toHexString(),
|
||||||
|
});
|
||||||
|
this.eventEmitter.emit('sse.game.' + game._id.toHexString(), {
|
||||||
|
type: 'leaveTeam',
|
||||||
|
team: new ReadTeamDto(team),
|
||||||
|
playerId: kickedPlayerId,
|
||||||
|
});
|
||||||
|
if (team.players.length == 0) {
|
||||||
|
const teamIndex = game.teams.indexOf(team);
|
||||||
|
game.teams.splice(teamIndex, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
await game.save({ session });
|
||||||
|
}
|
||||||
|
|
||||||
@WithTransaction
|
@WithTransaction
|
||||||
async endGame(
|
async endGame(
|
||||||
game: Document<Game> & Game,
|
game: Document<Game> & Game,
|
||||||
|
|||||||
Reference in New Issue
Block a user