import { BaseEvent } from '@/application/base/baseEvent' import { SocketEvent } from '@/application/enums' import { ZCharacterCreate } from '@/application/zodTypes' import { Character } from '@/entities/character' import CharacterRepository from '@/repositories/characterRepository' import CharacterTypeRepository from '@/repositories/characterTypeRepository' import MapRepository from '@/repositories/mapRepository' import UserRepository from '@/repositories/userRepository' import { z, ZodError } from 'zod' const MAX_CHARACTERS = 4 export default class CharacterCreateEvent extends BaseEvent { private readonly userRepository: UserRepository = new UserRepository() private readonly characterRepository: CharacterRepository = new CharacterRepository() private readonly characterTypeRepository: CharacterTypeRepository = new CharacterTypeRepository() private readonly mapRepository: MapRepository = new MapRepository() public listen(): void { this.socket.on(SocketEvent.CHARACTER_CREATE, this.handleEvent.bind(this)) } private async handleEvent(data: z.infer, callback: (success: boolean) => void): Promise { try { const validatedData = ZCharacterCreate.parse(data) await this.createCharacter(validatedData) callback(true) } catch (error: unknown) { this.returnError(error) callback(false) } } private async createCharacter(data: z.infer): Promise { const user = await this.userRepository.getById(this.socket.userId) if (!user) { throw new Error('You are not logged in') } const characterExists = await this.characterRepository.getByName(data.name) if (characterExists) { throw new Error('Character name already exists') } let characters = await this.characterRepository.getByUserId(user.getId()) if (characters.length >= MAX_CHARACTERS) { throw new Error(`You can only create ${MAX_CHARACTERS} characters`) } const map = await this.mapRepository.getFirst() if (!map) { throw new Error('No default map found') } const characterType = await this.characterTypeRepository.getFirst() if (!characterType) { throw new Error('No character type found') } const newCharacter = new Character() await newCharacter.setName(data.name).setUser(user).setMap(map).setCharacterType(characterType).save() characters = await this.characterRepository.getByUserId(user.getId()) this.socket.emit(SocketEvent.CHARACTER_LIST, characters) this.logger.info('character:create success') } private returnError(error: unknown): void { this.logger.error(`character:create error: ${error instanceof Error ? error.message : 'Unknown error'}`) let errorMessage = 'Could not create character. Please try again later.' if (error instanceof ZodError) { errorMessage = error.issues[0]?.message || errorMessage } else if (error instanceof Error) { errorMessage = error.message } this.socket.emit(SocketEvent.NOTIFICATION, { title: 'Error', message: errorMessage }) } }