import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; import { Game, Player } from '../schemas/game.schema'; import mongoose, { Document, Model } from 'mongoose'; import { Card } from 'src/cards/schemas/cards.schema'; import { EventEmitter2 } from '@nestjs/event-emitter'; import { Effect } from 'src/cards/schemas/effect.schema'; import { CardEffects, EffectType } from 'src/cards/schemas/cards.types'; import { WithTransaction } from '../utils'; import { effectMappings } from './effect.functions'; import { InjectConnection, InjectModel } from '@nestjs/mongoose'; @Injectable() export class TurnService { constructor( private eventEmitter: EventEmitter2, @InjectModel(Game.name) private gameModel: Model, @InjectConnection() private readonly connection: mongoose.Connection, ) {} @WithTransaction async lockCard( game: Document & Game, player: Player, cardId: string, session?: mongoose.mongo.ClientSession, ) { const card = player.board.cards.find((c) => c._id.toHexString() == cardId); if (!card) { throw new HttpException( 'Card not found in player board', HttpStatus.NOT_FOUND, ); } game.currentTurn.cardsLocked.push(card); this.eventEmitter.emit('sse.game.' + game._id.toHexString(), { type: 'lockCard', card: card._id.toHexString(), }); for (const effect of card.effects) { if ( [, CardEffects.HEAL, CardEffects.GOLD, CardEffects.DAMAGE].includes( effect.effect, ) && !effect.mutex && !effect.per && (!effect.condition || effect.condition.effectId == EffectType.CHAMPION_ACTION) ) { await this.useEffect(game, player, effect, card, session); } } await game.save({ session }); } @WithTransaction async useEffect( game: Document & Game, player: Player, effect: Effect, card: Card, session?: mongoose.mongo.ClientSession, ) { const effectRunner = effectMappings[effect.effect]; if (!effectMappings[effect.effect]) { console.warn(`Effect ${effect.effect} not implemented`); return; throw new HttpException( `Effect ${effect.effect} not implemented`, HttpStatus.NOT_IMPLEMENTED, ); } const effectUUID = effect._id.toHexString(); if (game.currentTurn.effectsUsed.includes(effectUUID)) { console.error(`Effect ${effectUUID} already used this turn`); throw new HttpException( `Effect ${effectUUID} already used this turn`, HttpStatus.CONFLICT, ); } this.eventEmitter.emit('sse.game.' + game._id.toHexString(), { type: 'useEffect', effect: effectUUID, }); game.currentTurn.effectsUsed.push(effectUUID); await effectRunner(game, effect, player, card, this.eventEmitter); await game.save({ session }); } @WithTransaction async buyCard( game: Document & Game, player: Player, card: Card, session?: mongoose.mongo.ClientSession, ) { return; } }