import { Server } from 'socket.io' import { TSocket } from '../../../utilities/types' import ZoneRepository from '../../../repositories/zoneRepository' import { Zone, ZoneEventTile, ZoneEventTileType, ZoneObject } from '@prisma/client' import prisma from '../../../utilities/prisma' import zoneManager from '../../../managers/zoneManager' import logger from '../../../utilities/logger' interface IPayload { zoneId: number name: string width: number height: number tiles: string[][] pvp: boolean zoneEventTiles: { type: ZoneEventTileType positionX: number positionY: number teleport?: { toZoneId: number toPositionX: number toPositionY: number } }[] zoneObjects: ZoneObject[] } /** * Handle game master zone update event * @param socket * @param io */ export default function (socket: TSocket, io: Server) { socket.on('gm:zone_editor:zone:update', async (data: IPayload, callback: (response: Zone) => void) => { if (socket.character?.role !== 'gm') { logger.info(`User ${socket.character?.id} tried to update zone but is not a game master.`) return } logger.info(`User ${socket.character?.id} has updated zone via zone editor.`) if (!data.zoneId) { logger.info(`User ${socket.character?.id} tried to update zone but did not provide a zone id.`) return } try { let zone = await ZoneRepository.getById(data.zoneId) if (!zone) { logger.info(`User ${socket.character?.id} tried to update zone ${data.zoneId} but it does not exist.`) return } await prisma.zone.update({ where: { id: data.zoneId }, data: { name: data.name, width: data.width, height: data.height, tiles: data.tiles, pvp: data.pvp, zoneEventTiles: { deleteMany: { zoneId: data.zoneId // Ensure only event tiles related to the zone are deleted }, // Save new zone event tiles create: data.zoneEventTiles.map((zoneEventTile) => ({ type: zoneEventTile.type, positionX: zoneEventTile.positionX, positionY: zoneEventTile.positionY, ...(zoneEventTile.type === 'TELEPORT' && zoneEventTile.teleport ? { teleport: { create: { toZoneId: zoneEventTile.teleport.toZoneId, toPositionX: zoneEventTile.teleport.toPositionX, toPositionY: zoneEventTile.teleport.toPositionY } } } : {}) })) }, zoneObjects: { deleteMany: { zoneId: data.zoneId // Ensure only objects related to the zone are deleted }, // Save new zone objects create: data.zoneObjects.map((zoneObject) => ({ objectId: zoneObject.objectId, depth: zoneObject.depth, positionX: zoneObject.positionX, positionY: zoneObject.positionY })) } } }) zone = await ZoneRepository.getById(data.zoneId) if (!zone) { logger.info(`User ${socket.character?.id} tried to update zone ${data.zoneId} but it does not exist.`) return } callback(zone) zoneManager.unloadZone(data.zoneId) await zoneManager.loadZone(zone) } catch (error: any) { logger.error(`Error updating zone: ${error.message}`) } }) }