137 lines
4.6 KiB
TypeScript
137 lines
4.6 KiB
TypeScript
import { BaseEvent } from '#application/base/baseEvent'
|
|
import { MapEventTileType } from '#application/enums'
|
|
import { UUID } from '#application/types'
|
|
import { Map } from '#entities/map'
|
|
import { MapEffect } from '#entities/mapEffect'
|
|
import { MapEventTile } from '#entities/mapEventTile'
|
|
import { MapEventTileTeleport } from '#entities/mapEventTileTeleport'
|
|
import { PlacedMapObject } from '#entities/placedMapObject'
|
|
import mapManager from '#managers/mapManager'
|
|
import MapRepository from '#repositories/mapRepository'
|
|
|
|
interface IPayload {
|
|
mapId: UUID
|
|
name: string
|
|
width: number
|
|
height: number
|
|
tiles: string[][]
|
|
pvp: boolean
|
|
mapEventTiles: {
|
|
type: MapEventTileType
|
|
positionX: number
|
|
positionY: number
|
|
teleport?: {
|
|
toMapId: UUID
|
|
toPositionX: number
|
|
toPositionY: number
|
|
toRotation: number
|
|
}
|
|
}[]
|
|
mapEffects: {
|
|
effect: string
|
|
strength: number
|
|
}[]
|
|
placedMapObjects: PlacedMapObject[]
|
|
}
|
|
|
|
export default class MapUpdateEvent extends BaseEvent {
|
|
public listen(): void {
|
|
this.socket.on('gm:map:update', this.handleEvent.bind(this))
|
|
}
|
|
|
|
private async handleEvent(data: IPayload, callback: (response: Map | null) => void): Promise<void> {
|
|
try {
|
|
if (!(await this.isCharacterGM())) return
|
|
|
|
const character = await this.getCharacter()
|
|
this.logger.info(`User ${character!.getId()} has updated map via map editor.`)
|
|
|
|
if (!data.mapId) {
|
|
this.logger.info(`User ${character!.getId()} tried to update map but did not provide a map id.`)
|
|
return callback(null)
|
|
}
|
|
|
|
let map = await MapRepository.getById(data.mapId)
|
|
|
|
if (!map) {
|
|
this.logger.info(`User ${character!.getId()} tried to update map ${data.mapId} but it does not exist.`)
|
|
return callback(null)
|
|
}
|
|
|
|
// Validation logic remains the same
|
|
if (data.tiles.length > data.height) {
|
|
data.tiles = data.tiles.slice(0, data.height)
|
|
}
|
|
for (let i = 0; i < data.tiles.length; i++) {
|
|
if (data.tiles[i].length > data.width) {
|
|
data.tiles[i] = data.tiles[i].slice(0, data.width)
|
|
}
|
|
}
|
|
|
|
data.mapEventTiles = data.mapEventTiles.filter((tile) => tile.positionX >= 0 && tile.positionX < data.width && tile.positionY >= 0 && tile.positionY < data.height)
|
|
|
|
data.placedMapObjects = data.placedMapObjects.filter((obj) => obj.positionX >= 0 && obj.positionX < data.width && obj.positionY >= 0 && obj.positionY < data.height)
|
|
|
|
// Clear existing collections
|
|
map.mapEventTiles.removeAll()
|
|
map.placedMapObjects.removeAll()
|
|
map.mapEffects.removeAll()
|
|
|
|
// Create and add new map event tiles
|
|
for (const tile of data.mapEventTiles) {
|
|
const mapEventTile = new MapEventTile().setType(tile.type).setPositionX(tile.positionX).setPositionY(tile.positionY).setMap(map)
|
|
|
|
if (tile.teleport) {
|
|
const teleport = new MapEventTileTeleport()
|
|
.setToMap(await MapRepository.getById(tile.teleport.toMapId))
|
|
.setToPositionX(tile.teleport.toPositionX)
|
|
.setToPositionY(tile.teleport.toPositionY)
|
|
.setToRotation(tile.teleport.toRotation)
|
|
|
|
mapEventTile.setTeleport(teleport)
|
|
}
|
|
|
|
map.mapEventTiles.add(mapEventTile)
|
|
}
|
|
|
|
// Create and add new map objects
|
|
for (const object of data.placedMapObjects) {
|
|
const mapObject = new PlacedMapObject()
|
|
.setMapObject(object.mapObject)
|
|
.setDepth(object.depth)
|
|
.setIsRotated(object.isRotated)
|
|
.setPositionX(object.positionX)
|
|
.setPositionY(object.positionY)
|
|
.setMap(map)
|
|
map.placedMapObjects.add(mapObject)
|
|
}
|
|
|
|
// Create and add new map effects
|
|
for (const effect of data.mapEffects) {
|
|
const mapEffect = new MapEffect().setEffect(effect.effect).setStrength(effect.strength).setMap(map)
|
|
map.mapEffects.add(mapEffect)
|
|
}
|
|
|
|
// Update map properties
|
|
await map.setName(data.name).setWidth(data.width).setHeight(data.height).setTiles(data.tiles).setPvp(data.pvp).setUpdatedAt(new Date()).save()
|
|
|
|
// Reload map from database to get fresh data
|
|
map = await MapRepository.getById(data.mapId)
|
|
|
|
if (!map) {
|
|
this.logger.info(`User ${character!.getId()} tried to update map ${data.mapId} but it does not exist after update.`)
|
|
return callback(null)
|
|
}
|
|
|
|
// Reload map for players
|
|
mapManager.unloadMap(data.mapId)
|
|
await mapManager.loadMap(map)
|
|
|
|
return callback(map)
|
|
} catch (error: any) {
|
|
this.logger.error(`gm:mapObject:update error: ${error instanceof Error ? error.message : String(error)}`)
|
|
return callback(null)
|
|
}
|
|
}
|
|
}
|