Attempt to fix performance :(((

This commit is contained in:
Dennis Postma 2025-01-05 07:22:23 +01:00
parent d7982493e1
commit cc1dbe5179
7 changed files with 31 additions and 35 deletions

View File

@ -2,11 +2,8 @@ import { randomUUID } from 'node:crypto'
import { Collection, Entity, OneToMany, PrimaryKey, Property } from '@mikro-orm/core' import { Collection, Entity, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'
import { Character } from './character'
import { Chat } from './chat'
import { MapEffect } from './mapEffect' import { MapEffect } from './mapEffect'
import { MapEventTile } from './mapEventTile' import { MapEventTile } from './mapEventTile'
import { MapEventTileTeleport } from './mapEventTileTeleport'
import { BaseEntity } from '#application/base/baseEntity' import { BaseEntity } from '#application/base/baseEntity'
import { UUID } from '#application/types' import { UUID } from '#application/types'
@ -44,10 +41,7 @@ export class Map extends BaseEntity {
@OneToMany(() => MapEventTile, (tile) => tile.map, { orphanRemoval: true }) @OneToMany(() => MapEventTile, (tile) => tile.map, { orphanRemoval: true })
mapEventTiles = new Collection<MapEventTile>(this) mapEventTiles = new Collection<MapEventTile>(this)
@OneToMany(() => PlacedMapObject, (pmo) => pmo.map, { @OneToMany(() => PlacedMapObject, (placedMapObject) => placedMapObject.map, { orphanRemoval: true })
name: 'placedMapObjects',
orphanRemoval: true
})
placedMapObjects = new Collection<PlacedMapObject>(this) placedMapObjects = new Collection<PlacedMapObject>(this)
setId(id: UUID) { setId(id: UUID) {

View File

@ -25,15 +25,13 @@ export default class MapRequestEvent extends BaseEvent {
const mapRepository = new MapRepository() const mapRepository = new MapRepository()
const map = await mapRepository.getById(data.mapId) const map = await mapRepository.getById(data.mapId)
await mapRepository.getEntityManager().populate(map!, mapRepository.POPULATE_MAP_EDITOR as any)
if (!map) { if (!map) {
this.logger.info(`User ${(await this.getCharacter())!.getId()} tried to request map ${data.mapId} but it does not exist.`) this.logger.info(`User ${(await this.getCharacter())!.getId()} tried to request map ${data.mapId} but it does not exist.`)
return callback(null) return callback(null)
} }
// Populate map with mapEventTiles and placedMapObjects
await mapRepository.getEntityManager().populate(map, ['mapEffects', 'mapEventTiles', 'placedMapObjects', 'placedMapObjects.mapObject'])
return callback(map) return callback(map)
} catch (error: any) { } catch (error: any) {
this.logger.error('gm:map:request error', error.message) this.logger.error('gm:map:request error', error.message)

View File

@ -32,7 +32,6 @@ interface IPayload {
} }
export default class MapUpdateEvent extends BaseEvent { export default class MapUpdateEvent extends BaseEvent {
private readonly populateOptions = ['mapEventTiles', 'placedMapObjects', 'mapEffects'];
public listen(): void { public listen(): void {
this.socket.on('gm:map:update', this.handleEvent.bind(this)) this.socket.on('gm:map:update', this.handleEvent.bind(this))
} }
@ -57,8 +56,7 @@ export default class MapUpdateEvent extends BaseEvent {
return callback(null) return callback(null)
} }
// @ts-ignore await mapRepository.getEntityManager().populate(map, mapRepository.POPULATE_MAP_EDITOR as any)
await mapRepository.getEntityManager().populate(map, this.populateOptions)
// Validation logic remains the same // Validation logic remains the same
if (data.tiles.length > data.height) { if (data.tiles.length > data.height) {
@ -122,9 +120,7 @@ export default class MapUpdateEvent extends BaseEvent {
// Reload map from database to get fresh data // Reload map from database to get fresh data
map = await mapRepository.getById(data.mapId) map = await mapRepository.getById(data.mapId)
await mapRepository.getEntityManager().populate(map!, mapRepository.POPULATE_MAP_EDITOR as any)
// @ts-ignore
await mapRepository.getEntityManager().populate(map!, this.populateOptions)
if (!map) { if (!map) {
this.logger.info(`User ${character!.getId()} tried to update map ${data.mapId} but it does not exist after update.`) this.logger.info(`User ${character!.getId()} tried to update map ${data.mapId} but it does not exist after update.`)

View File

@ -12,6 +12,8 @@ class MapManager {
public async boot(): Promise<void> { public async boot(): Promise<void> {
const mapRepository = new MapRepository() const mapRepository = new MapRepository()
const maps = await mapRepository.getAll() const maps = await mapRepository.getAll()
await mapRepository.getEntityManager().populate(maps, mapRepository.POPULATE_ALL as never[])
await Promise.all(maps.map((map) => this.loadMap(map))) await Promise.all(maps.map((map) => this.loadMap(map)))
this.logger.info(`Map manager loaded with ${Object.keys(this.maps).length} maps`) this.logger.info(`Map manager loaded with ${Object.keys(this.maps).length} maps`)

View File

@ -2,9 +2,12 @@ import { BaseRepository } from '#application/base/baseRepository'
import { UUID } from '#application/types' import { UUID } from '#application/types'
import { Map } from '#entities/map' import { Map } from '#entities/map'
import { MapEventTile } from '#entities/mapEventTile' import { MapEventTile } from '#entities/mapEventTile'
import { MapObject } from '#entities/mapObject'
class MapRepository extends BaseRepository { class MapRepository extends BaseRepository {
public readonly POPULATE_ALL = ['*']
public readonly POPULATE_MAP_EDITOR = ['mapEventTiles', 'placedMapObjects', 'mapEffects']
public readonly POPULATE_TELEPORT = ['placedMapObjects', 'mapEffects']
async getFirst(): Promise<Map | null> { async getFirst(): Promise<Map | null> {
try { try {
const repository = this.getEntityManager().getRepository(Map) const repository = this.getEntityManager().getRepository(Map)

View File

@ -1,20 +1,20 @@
import { Server } from 'socket.io'
import { BaseService } from '#application/base/baseService' import { BaseService } from '#application/base/baseService'
import { TSocket, UUID } from '#application/types' import { UUID } from '#application/types'
import { Chat } from '#entities/chat' import { Chat } from '#entities/chat'
import SocketManager from '#managers/socketManager' import SocketManager from '#managers/socketManager'
import CharacterRepository from '#repositories/characterRepository' import CharacterRepository from '#repositories/characterRepository'
import ChatRepository from '#repositories/chatRepository'
import MapRepository from '#repositories/mapRepository' import MapRepository from '#repositories/mapRepository'
class ChatService extends BaseService { class ChatService extends BaseService {
async sendMapMessage(characterId: UUID, mapId: UUID, message: string): Promise<boolean> { async sendMapMessage(characterId: UUID, mapId: UUID, message: string): Promise<boolean> {
try { try {
const character = await CharacterRepository.getById(characterId) const characterRepository = new CharacterRepository()
const mapRepository = new MapRepository()
const character = await characterRepository.getById(characterId)
if (!character) return false if (!character) return false
const map = await MapRepository.getById(mapId) const map = await mapRepository.getById(mapId)
if (!map) return false if (!map) return false
const chat = new Chat() const chat = new Chat()

View File

@ -4,6 +4,7 @@ import { Character } from '#entities/character'
import MapManager from '#managers/mapManager' import MapManager from '#managers/mapManager'
import SocketManager from '#managers/socketManager' import SocketManager from '#managers/socketManager'
import MapCharacter from '#models/mapCharacter' import MapCharacter from '#models/mapCharacter'
import MapRepository from '#repositories/mapRepository'
interface TeleportOptions { interface TeleportOptions {
targetMapId: UUID targetMapId: UUID
@ -18,24 +19,23 @@ class TeleportService {
private readonly logger = Logger.type(LoggerType.GAME) private readonly logger = Logger.type(LoggerType.GAME)
public async teleportCharacter(characterId: UUID, options: TeleportOptions): Promise<boolean> { public async teleportCharacter(characterId: UUID, options: TeleportOptions): Promise<boolean> {
const { targetMapId, targetX, targetY, rotation = 0, isInitialJoin = false, character } = options const mapRepository = new MapRepository()
const socket = SocketManager.getSocketByCharacterId(characterId) const socket = SocketManager.getSocketByCharacterId(characterId)
const targetMap = MapManager.getMapById(targetMapId) const targetMap = MapManager.getMapById(options.targetMapId)
if (!socket || !targetMap) { if (!socket || !targetMap) {
this.logger.error(`Teleport failed - Missing socket or target map for character ${characterId}`) this.logger.error(`Teleport failed - Missing socket or target map for character ${characterId}`)
return false return false
} }
if (isInitialJoin && !character) { if (options.isInitialJoin && !options.character) {
this.logger.error('Initial join requires character data') this.logger.error('Initial join requires character data')
return false return false
} }
const existingCharacter = !isInitialJoin && MapManager.getCharacterById(characterId) const existingCharacter = !options.isInitialJoin && MapManager.getCharacterById(characterId)
const mapCharacter = isInitialJoin const mapCharacter = options.isInitialJoin
? new MapCharacter(character!) ? new MapCharacter(options.character!)
: existingCharacter || : existingCharacter ||
(() => { (() => {
this.logger.error(`Teleport failed - Character ${characterId} not found in MapManager`) this.logger.error(`Teleport failed - Character ${characterId} not found in MapManager`)
@ -56,16 +56,19 @@ class TeleportService {
} }
// Update character position and map // Update character position and map
await mapCharacter.character.setPositionX(targetX).setPositionY(targetY).setRotation(rotation).setMap(targetMap.getMap()).save() await mapCharacter.getCharacter().setPositionX(options.targetX).setPositionY(options.targetY).setRotation(options.rotation ?? 0).setMap(targetMap.getMap()).save()
// Join new map // Join new map
socket.join(targetMapId) socket.join(options.targetMapId)
targetMap.addCharacter(mapCharacter.character) targetMap.addCharacter(mapCharacter.getCharacter())
const map = await mapRepository.getById(options.targetMapId)
await mapRepository.getEntityManager().populate(map!, mapRepository.POPULATE_TELEPORT as any)
// Notify clients // Notify clients
io.in(targetMapId).emit('map:character:join', mapCharacter) io.in(options.targetMapId).emit('map:character:join', mapCharacter)
socket.emit('map:character:teleport', { socket.emit('map:character:teleport', {
map: targetMap.getMap(), map: map,
characters: targetMap.getCharactersInMap() characters: targetMap.getCharactersInMap()
}) })