import { Server } from 'socket.io' import { TSocket } from '#application/types' import ZoneRepository from '#repositories/zoneRepository' import { Zone } from '@prisma/client' import { gameLogger } from '#application/logger' import CharacterRepository from '#repositories/characterRepository' import ZoneManager from '#managers/zoneManager' import zoneCharacter from '#models/zoneCharacter' import zoneManager from '#managers/zoneManager' interface IResponse { zone: Zone characters: zoneCharacter[] } export default class CharacterJoinEvent { constructor( private readonly io: Server, private readonly socket: TSocket ) {} public listen(): void { this.socket.on('zone:character:join', this.handleCharacterJoin.bind(this)) } private async handleCharacterJoin(callback: (response: IResponse) => void): Promise { try { if (!this.socket.characterId) { gameLogger.error('zone:character:join error', 'Zone requested but no character id set') return } const character = await CharacterRepository.getById(this.socket.characterId) if (!character) { gameLogger.error('zone:character:join error', 'Character not found') return } /** * @TODO: If zone is not found, spawn back to the start */ const zone = await ZoneRepository.getById(character.zoneId) if (!zone) { gameLogger.error('zone:character:join error', 'Zone not found') return } /** * @TODO: If zone is not found, spawn back to the start */ const loadedZone = ZoneManager.getZoneById(zone.id) if (!loadedZone) { gameLogger.error('zone:character:join error', 'Loaded zone not found') return } loadedZone.addCharacter(character) this.socket.join(zone.id.toString()) // Let other clients know of new character this.io.to(zone.id.toString()).emit('zone:character:join', zoneManager.getCharacter(character.id)) // Log gameLogger.info(`User ${character.id} joined zone ${zone.id}`) // Send over zone and characters to socket callback({ zone, characters: loadedZone.getCharactersInZone() }) } catch (error: any) { gameLogger.error('zone:character:join error', error.message) this.socket.disconnect() } } }