forked from noxious/server
#174: Refactor character manager into zoneManager for better DX, major refactor of time and weather system (data is stored in DB now instead of JSON file), npm update, npm format, many other improvements
This commit is contained in:
@ -3,7 +3,7 @@ import { TSocket } from '../../utilities/types'
|
||||
import CharacterRepository from '../../repositories/characterRepository'
|
||||
|
||||
type SocketResponseT = {
|
||||
character_id: number
|
||||
characterId: number
|
||||
}
|
||||
|
||||
export default class CharacterConnectEvent {
|
||||
@ -19,7 +19,7 @@ export default class CharacterConnectEvent {
|
||||
private async handleCharacterConnect(data: SocketResponseT): Promise<void> {
|
||||
console.log('character:connect requested', data)
|
||||
try {
|
||||
const character = await CharacterRepository.getByUserAndId(this.socket?.user?.id as number, data.character_id)
|
||||
const character = await CharacterRepository.getByUserAndId(this.socket?.userId!, data.characterId!)
|
||||
if (!character) return
|
||||
|
||||
this.socket.characterId = character.id
|
||||
|
@ -23,7 +23,7 @@ export default class CharacterCreateEvent {
|
||||
try {
|
||||
data = ZCharacterCreate.parse(data)
|
||||
|
||||
const user_id = this.socket.user?.id as number
|
||||
const user_id = this.socket.userId!
|
||||
|
||||
// Check if character name already exists
|
||||
const characterExists = await CharacterRepository.getByName(data.name)
|
||||
|
@ -4,7 +4,7 @@ import { Character, Zone } from '@prisma/client'
|
||||
import CharacterRepository from '../../repositories/characterRepository'
|
||||
|
||||
type TypePayload = {
|
||||
character_id: number
|
||||
characterId: number
|
||||
}
|
||||
|
||||
type TypeResponse = {
|
||||
@ -23,12 +23,10 @@ export default class CharacterDeleteEvent {
|
||||
}
|
||||
|
||||
private async handleCharacterDelete(data: TypePayload, callback: (response: TypeResponse) => void): Promise<any> {
|
||||
// zod validate
|
||||
try {
|
||||
await CharacterRepository.deleteByUserIdAndId(this.socket.user?.id as number, data.character_id as number)
|
||||
await CharacterRepository.deleteByUserIdAndId(this.socket.userId!, data.characterId!)
|
||||
|
||||
const user_id = this.socket.user?.id as number
|
||||
const characters: Character[] = (await CharacterRepository.getByUserId(user_id)) as Character[]
|
||||
const characters: Character[] = (await CharacterRepository.getByUserId(this.socket.userId!)) as Character[]
|
||||
|
||||
this.socket.emit('character:list', characters)
|
||||
} catch (error: any) {
|
||||
|
@ -2,6 +2,7 @@ import { Socket, Server } from 'socket.io'
|
||||
import { TSocket } from '../../utilities/types'
|
||||
import { Character } from '@prisma/client'
|
||||
import CharacterRepository from '../../repositories/characterRepository'
|
||||
import { gameLogger } from '../../utilities/logger'
|
||||
|
||||
export default class CharacterListEvent {
|
||||
constructor(
|
||||
@ -15,12 +16,10 @@ export default class CharacterListEvent {
|
||||
|
||||
private async handleCharacterList(data: any): Promise<void> {
|
||||
try {
|
||||
console.log('character:list requested')
|
||||
const user_id = this.socket.user?.id as number
|
||||
const characters: Character[] = (await CharacterRepository.getByUserId(user_id)) as Character[]
|
||||
const characters: Character[] = (await CharacterRepository.getByUserId(this.socket.userId!)) as Character[]
|
||||
this.socket.emit('character:list', characters)
|
||||
} catch (error: any) {
|
||||
console.log('character:list error', error)
|
||||
gameLogger.error('character:list error', error.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ export default class AlertCommandEvent {
|
||||
}
|
||||
|
||||
// Check if character exists
|
||||
const character = await CharacterRepository.getByUserAndId(this.socket.user?.id as number, this.socket.characterId as number)
|
||||
const character = await CharacterRepository.getByUserAndId(this.socket.userId!, this.socket.characterId!)
|
||||
if (!character) {
|
||||
gameLogger.error('chat:alert_command error', 'Character not found')
|
||||
callback(false)
|
||||
|
@ -26,7 +26,7 @@ export default class SetTimeCommand {
|
||||
}
|
||||
|
||||
// Check if character exists
|
||||
const character = await CharacterRepository.getByUserAndId(this.socket.user?.id as number, this.socket.characterId as number)
|
||||
const character = await CharacterRepository.getByUserAndId(this.socket.userId!, this.socket.characterId!)
|
||||
if (!character) {
|
||||
gameLogger.error('chat:alert_command error', 'Character not found')
|
||||
callback(false)
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { Server } from 'socket.io'
|
||||
import { ExtendedCharacter, TSocket } from '../../../utilities/types'
|
||||
import { TSocket } from '../../../utilities/types'
|
||||
import { getArgs, isCommand } from '../../../utilities/chat'
|
||||
import ZoneRepository from '../../../repositories/zoneRepository'
|
||||
import CharacterManager from '../../../managers/characterManager'
|
||||
import { gameLogger, gameMasterLogger } from '../../../utilities/logger'
|
||||
import CharacterRepository from '../../../repositories/characterRepository'
|
||||
import ZoneManager from '../../../managers/zoneManager'
|
||||
import ZoneCharacter from '../../../models/zoneCharacter'
|
||||
|
||||
type TypePayload = {
|
||||
message: string
|
||||
@ -23,13 +23,15 @@ export default class TeleportCommandEvent {
|
||||
private async handleTeleportCommand(data: TypePayload, callback: (response: boolean) => void): Promise<void> {
|
||||
try {
|
||||
// Check if character exists
|
||||
const character = (await CharacterRepository.getByUserAndId(this.socket.user?.id as number, this.socket.characterId as number)) as ExtendedCharacter
|
||||
if (!character) {
|
||||
gameLogger.error('chat:alert_command error', 'Character not found')
|
||||
const zoneCharacter = ZoneManager.getCharacter(this.socket.characterId!)
|
||||
if (!zoneCharacter) {
|
||||
gameLogger.error('chat:send_message error', 'Character not found')
|
||||
callback(false)
|
||||
return
|
||||
}
|
||||
|
||||
const character = zoneCharacter.character
|
||||
|
||||
// Check if the user is the GM
|
||||
if (character.role !== 'gm') {
|
||||
gameLogger.info(`User ${character.id} tried to set time but is not a game master.`)
|
||||
@ -75,11 +77,11 @@ export default class TeleportCommandEvent {
|
||||
character.positionX = 0
|
||||
character.positionY = 0
|
||||
|
||||
character.resetMovement = true
|
||||
zoneCharacter.isMoving = false
|
||||
|
||||
this.socket.emit('zone:character:teleport', {
|
||||
zone,
|
||||
characters: CharacterManager.getCharactersInZone(zone)
|
||||
characters: ZoneManager.getZoneById(zone.id)?.getCharactersInZone()
|
||||
})
|
||||
|
||||
this.socket.emit('notification', { title: 'Server message', message: `You have been teleported to ${zone.name}` })
|
||||
|
@ -26,7 +26,7 @@ export default class ToggleFogCommand {
|
||||
}
|
||||
|
||||
// Check if character exists
|
||||
const character = await CharacterRepository.getByUserAndId(this.socket.user?.id as number, this.socket.characterId as number)
|
||||
const character = await CharacterRepository.getByUserAndId(this.socket.userId!, this.socket.characterId!)
|
||||
if (!character) {
|
||||
gameLogger.error('chat:alert_command error', 'Character not found')
|
||||
callback(false)
|
||||
|
@ -26,7 +26,7 @@ export default class ToggleRainCommand {
|
||||
}
|
||||
|
||||
// Check if character exists
|
||||
const character = await CharacterRepository.getByUserAndId(this.socket.user?.id as number, this.socket.characterId as number)
|
||||
const character = await CharacterRepository.getByUserAndId(this.socket.userId!, this.socket.characterId!)
|
||||
if (!character) {
|
||||
gameLogger.error('chat:alert_command error', 'Character not found')
|
||||
callback(false)
|
||||
|
@ -3,7 +3,7 @@ import { TSocket } from '../../utilities/types'
|
||||
import ZoneRepository from '../../repositories/zoneRepository'
|
||||
import { isCommand } from '../../utilities/chat'
|
||||
import { gameLogger } from '../../utilities/logger'
|
||||
import CharacterManager from '../../managers/characterManager'
|
||||
import ZoneManager from '../../managers/zoneManager'
|
||||
|
||||
type TypePayload = {
|
||||
message: string
|
||||
@ -26,13 +26,15 @@ export default class ChatMessageEvent {
|
||||
return
|
||||
}
|
||||
|
||||
const character = CharacterManager.getCharacterFromSocket(this.socket)
|
||||
if (!character) {
|
||||
const zoneCharacter = ZoneManager.getCharacter(this.socket.characterId!)
|
||||
if (!zoneCharacter) {
|
||||
gameLogger.error('chat:send_message error', 'Character not found')
|
||||
callback(false)
|
||||
return
|
||||
}
|
||||
|
||||
const character = zoneCharacter.character
|
||||
|
||||
const zone = await ZoneRepository.getById(character.zoneId)
|
||||
if (!zone) {
|
||||
gameLogger.error('chat:send_message error', 'Zone not found')
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Server } from 'socket.io'
|
||||
import { TSocket } from '../utilities/types'
|
||||
import CharacterManager from '../managers/characterManager'
|
||||
import { gameLogger } from '../utilities/logger'
|
||||
import ZoneManager from '../managers/zoneManager'
|
||||
|
||||
export default class DisconnectEvent {
|
||||
constructor(
|
||||
@ -10,31 +10,34 @@ export default class DisconnectEvent {
|
||||
) {}
|
||||
|
||||
public listen(): void {
|
||||
this.socket.on('disconnect', this.handleDisconnect.bind(this))
|
||||
this.socket.on('disconnect', this.handleEvent.bind(this))
|
||||
}
|
||||
|
||||
private async handleDisconnect(data: any): Promise<void> {
|
||||
private async handleEvent(data: any): Promise<void> {
|
||||
try {
|
||||
if (!this.socket.user) {
|
||||
if (!this.socket.userId) {
|
||||
gameLogger.info('User disconnected but had no user set')
|
||||
return
|
||||
}
|
||||
|
||||
this.io.emit('user:disconnect', this.socket.user.id)
|
||||
this.io.emit('user:disconnect', this.socket.userId)
|
||||
|
||||
const character = CharacterManager.getCharacterFromSocket(this.socket)
|
||||
|
||||
if (!character) {
|
||||
const zoneCharacter = ZoneManager.getCharacter(this.socket.characterId!)
|
||||
if (!zoneCharacter) {
|
||||
gameLogger.info('User disconnected but had no character set')
|
||||
return
|
||||
}
|
||||
|
||||
character.resetMovement = true
|
||||
const character = zoneCharacter.character
|
||||
|
||||
// Save character position and remove from zone
|
||||
zoneCharacter.isMoving = false
|
||||
await zoneCharacter.savePosition()
|
||||
ZoneManager.removeCharacter(this.socket.characterId!)
|
||||
|
||||
gameLogger.info('User disconnected along with their character')
|
||||
|
||||
await CharacterManager.removeCharacter(character)
|
||||
|
||||
// Inform other clients that the character has left
|
||||
this.io.in(character.zoneId.toString()).emit('zone:character:leave', character.id)
|
||||
this.io.emit('character:disconnect', character.id)
|
||||
} catch (error: any) {
|
||||
|
@ -17,7 +17,7 @@ export default class SpriteCreateEvent {
|
||||
|
||||
private async handleSpriteCreate(data: undefined, callback: (response: boolean) => void): Promise<void> {
|
||||
try {
|
||||
const character = await characterRepository.getById(this.socket.characterId as number)
|
||||
const character = await characterRepository.getById(this.socket.characterId!)
|
||||
if (!character) return callback(false)
|
||||
|
||||
if (character.role !== 'gm') {
|
||||
|
@ -2,9 +2,9 @@ import { Server } from 'socket.io'
|
||||
import { TSocket } from '../../../../utilities/types'
|
||||
import fs from 'fs'
|
||||
import prisma from '../../../../utilities/prisma'
|
||||
import CharacterManager from '../../../../managers/characterManager'
|
||||
import { gameMasterLogger } from '../../../../utilities/logger'
|
||||
import { getPublicPath } from '../../../../utilities/storage'
|
||||
import CharacterRepository from '../../../../repositories/characterRepository'
|
||||
|
||||
type Payload = {
|
||||
id: string
|
||||
@ -25,7 +25,7 @@ export default class GMSpriteDeleteEvent {
|
||||
}
|
||||
|
||||
private async handleSpriteDelete(data: Payload, callback: (response: boolean) => void): Promise<void> {
|
||||
const character = CharacterManager.getCharacterFromSocket(this.socket)
|
||||
const character = await CharacterRepository.getById(this.socket.characterId!)
|
||||
if (character?.role !== 'gm') {
|
||||
return callback(false)
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ export default class SpriteListEvent {
|
||||
}
|
||||
|
||||
private async handleSpriteList(data: any, callback: (response: Sprite[]) => void): Promise<void> {
|
||||
const character = await characterRepository.getById(this.socket.characterId as number)
|
||||
const character = await characterRepository.getById(this.socket.characterId!)
|
||||
if (!character) return callback([])
|
||||
|
||||
if (character.role !== 'gm') {
|
||||
|
@ -4,8 +4,8 @@ import prisma from '../../../../utilities/prisma'
|
||||
import type { Prisma, SpriteAction } from '@prisma/client'
|
||||
import { writeFile, mkdir } from 'node:fs/promises'
|
||||
import sharp from 'sharp'
|
||||
import CharacterManager from '../../../../managers/characterManager'
|
||||
import { getPublicPath } from '../../../../utilities/storage'
|
||||
import CharacterRepository from '../../../../repositories/characterRepository'
|
||||
|
||||
type SpriteActionInput = Omit<SpriteAction, 'id' | 'spriteId' | 'frameWidth' | 'frameHeight'> & {
|
||||
sprites: string[]
|
||||
@ -38,7 +38,7 @@ export default class SpriteUpdateEvent {
|
||||
}
|
||||
|
||||
private async handleSpriteUpdate(data: Payload, callback: (success: boolean) => void): Promise<void> {
|
||||
const character = CharacterManager.getCharacterFromSocket(this.socket)
|
||||
const character = await CharacterRepository.getById(this.socket.characterId!)
|
||||
if (character?.role !== 'gm') {
|
||||
return callback(false)
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { Server } from 'socket.io'
|
||||
import { TSocket } from '../utilities/types'
|
||||
import { gameLogger } from '../utilities/logger'
|
||||
import UserRepository from '../repositories/userRepository'
|
||||
|
||||
export default class LoginEvent {
|
||||
constructor(
|
||||
@ -14,13 +15,13 @@ export default class LoginEvent {
|
||||
|
||||
private handleLogin(): void {
|
||||
try {
|
||||
if (!this.socket.user) {
|
||||
if (!this.socket.userId) {
|
||||
gameLogger.warn('Login attempt without user data')
|
||||
return
|
||||
}
|
||||
|
||||
this.socket.emit('logged_in', { user: this.socket.user })
|
||||
gameLogger.info(`User logged in: ${this.socket.user.id}`)
|
||||
this.socket.emit('logged_in', { user: UserRepository.getById(this.socket.userId) })
|
||||
gameLogger.info(`User logged in: ${this.socket.userId}`)
|
||||
} catch (error: any) {
|
||||
gameLogger.error('login error', error.message)
|
||||
}
|
||||
|
@ -1,14 +1,16 @@
|
||||
import { Server } from 'socket.io'
|
||||
import { ExtendedCharacter, TSocket } from '../../utilities/types'
|
||||
import { TSocket } from '../../utilities/types'
|
||||
import ZoneRepository from '../../repositories/zoneRepository'
|
||||
import { Character, Zone } from '@prisma/client'
|
||||
import CharacterManager from '../../managers/characterManager'
|
||||
import { Zone } from '@prisma/client'
|
||||
import { gameLogger } from '../../utilities/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: Character[]
|
||||
characters: zoneCharacter[]
|
||||
}
|
||||
|
||||
export default class CharacterJoinEvent {
|
||||
@ -28,30 +30,42 @@ export default class CharacterJoinEvent {
|
||||
return
|
||||
}
|
||||
|
||||
const character = await CharacterRepository.getById(this.socket.characterId as number)
|
||||
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
|
||||
}
|
||||
|
||||
CharacterManager.initCharacter(character as ExtendedCharacter)
|
||||
/**
|
||||
* @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', character)
|
||||
// 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: CharacterManager.getCharactersInZone(zone) })
|
||||
// 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()
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { Server } from 'socket.io'
|
||||
import { TSocket } from '../../utilities/types'
|
||||
import ZoneRepository from '../../repositories/zoneRepository'
|
||||
import CharacterManager from '../../managers/characterManager'
|
||||
import { gameLogger } from '../../utilities/logger'
|
||||
import ZoneManager from '../../managers/zoneManager'
|
||||
import CharacterRepository from '../../repositories/characterRepository'
|
||||
|
||||
export default class ZoneLeaveEvent {
|
||||
constructor(
|
||||
@ -16,31 +17,41 @@ export default class ZoneLeaveEvent {
|
||||
|
||||
private async handleZoneLeave(): Promise<void> {
|
||||
try {
|
||||
const character = CharacterManager.getCharacterFromSocket(this.socket)
|
||||
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:leave error', 'Character not found')
|
||||
return
|
||||
}
|
||||
|
||||
if (!character.zoneId) {
|
||||
gameLogger.error('zone:character:leave error', 'Character not in a zone')
|
||||
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:leave error', 'Zone not found')
|
||||
gameLogger.error('zone:character:join error', 'Zone not found')
|
||||
return
|
||||
}
|
||||
|
||||
const loadedZone = ZoneManager.getZoneById(zone.id)
|
||||
if (!loadedZone) {
|
||||
gameLogger.error('zone:character:join error', 'Loaded zone not found')
|
||||
return
|
||||
}
|
||||
|
||||
console.log('awee')
|
||||
|
||||
this.socket.leave(zone.id.toString())
|
||||
|
||||
// let other clients know of character leaving
|
||||
this.io.to(zone.id.toString()).emit('zone:character:leave', character.id)
|
||||
|
||||
// remove character from zone manager
|
||||
await CharacterManager.removeCharacter(character)
|
||||
await loadedZone.removeCharacter(character.id)
|
||||
|
||||
gameLogger.info('zone:character:leave', `Character ${character.id} left zone ${zone.id}`)
|
||||
} catch (error: any) {
|
||||
|
@ -1,77 +1,53 @@
|
||||
import { Server } from 'socket.io'
|
||||
import { TSocket, ExtendedCharacter } from '../../utilities/types'
|
||||
import { TSocket, ZoneEventTileWithTeleport } from '../../utilities/types'
|
||||
import { CharacterMoveService } from '../../services/character/characterMoveService'
|
||||
import { ZoneEventTileService } from '../../services/zoneEventTileService'
|
||||
import prisma from '../../utilities/prisma'
|
||||
import { ZoneEventTile, ZoneEventTileTeleport } from '@prisma/client'
|
||||
import Rotation from '../../utilities/character/rotation'
|
||||
import CharacterManager from '../../managers/characterManager'
|
||||
import { gameLogger } from '../../utilities/logger'
|
||||
import QueueManager from '../../managers/queueManager'
|
||||
|
||||
export type ZoneEventTileWithTeleport = ZoneEventTile & {
|
||||
teleport: ZoneEventTileTeleport
|
||||
}
|
||||
import ZoneManager from '../../managers/zoneManager'
|
||||
import ZoneCharacter from '../../models/zoneCharacter'
|
||||
|
||||
export default class CharacterMove {
|
||||
private characterMoveService: CharacterMoveService
|
||||
private zoneEventTileService: ZoneEventTileService
|
||||
private nextPath: { [index: number]: { x: number; y: number }[] } = []
|
||||
private currentZoneId: { [index: number]: number } = []
|
||||
private readonly characterMoveService = new CharacterMoveService()
|
||||
private readonly zoneEventTileService = new ZoneEventTileService()
|
||||
private nextPath = new Map<number, { x: number; y: number }[]>()
|
||||
|
||||
constructor(
|
||||
private readonly io: Server,
|
||||
private readonly socket: TSocket
|
||||
) {
|
||||
this.characterMoveService = new CharacterMoveService()
|
||||
this.zoneEventTileService = new ZoneEventTileService()
|
||||
}
|
||||
) {}
|
||||
|
||||
public listen(): void {
|
||||
this.socket.on('character:initMove', this.handleCharacterMove.bind(this))
|
||||
this.socket.on('character:move', this.handleCharacterMove.bind(this))
|
||||
}
|
||||
|
||||
private async handleCharacterMove({ positionX, positionY }: { positionX: number; positionY: number }): Promise<void> {
|
||||
let character = CharacterManager.getCharacterFromSocket(this.socket)
|
||||
if (!character) {
|
||||
gameLogger.error('character:move error', 'Character not found')
|
||||
const zoneCharacter = ZoneManager.getCharacter(this.socket.characterId!)
|
||||
if (!zoneCharacter?.character) {
|
||||
gameLogger.error('character:move error', 'Character not found or not initialized')
|
||||
return
|
||||
}
|
||||
|
||||
if (!character) {
|
||||
gameLogger.error('character:move error', 'character has not been initialized?')
|
||||
return
|
||||
}
|
||||
|
||||
const path = await this.characterMoveService.calculatePath(character, positionX, positionY)
|
||||
const path = await this.characterMoveService.calculatePath(zoneCharacter.character, positionX, positionY)
|
||||
if (!path) {
|
||||
this.io.in(character.zoneId.toString()).emit('character:moveError', 'No valid path found')
|
||||
this.io.in(zoneCharacter.character.zoneId.toString()).emit('character:moveError', 'No valid path found')
|
||||
return
|
||||
}
|
||||
|
||||
if (!character.isMoving && character.resetMovement) {
|
||||
character.resetMovement = false
|
||||
}
|
||||
if (character.isMoving && !character.resetMovement) {
|
||||
character.resetMovement = true
|
||||
this.nextPath[character.id] = path
|
||||
}
|
||||
if (!character.isMoving && !character.resetMovement) {
|
||||
character.isMoving = true
|
||||
this.currentZoneId[character.id] = character.zoneId
|
||||
await this.moveAlongPath(character, path)
|
||||
if (!zoneCharacter.isMoving) {
|
||||
zoneCharacter.isMoving = true
|
||||
await this.moveAlongPath(zoneCharacter, path)
|
||||
} else {
|
||||
this.nextPath.set(zoneCharacter.character.id, path)
|
||||
}
|
||||
}
|
||||
|
||||
private async moveAlongPath(character: ExtendedCharacter, path: Array<{ x: number; y: number }>): Promise<void> {
|
||||
private async moveAlongPath(zoneCharacter: ZoneCharacter, path: Array<{ x: number; y: number }>): Promise<void> {
|
||||
const { character } = zoneCharacter
|
||||
|
||||
for (let i = 0; i < path.length - 1; i++) {
|
||||
const start = path[i]
|
||||
const end = path[i + 1]
|
||||
|
||||
if (CharacterManager.hasResetMovement(character)) {
|
||||
break
|
||||
}
|
||||
|
||||
const [start, end] = [path[i], path[i + 1]]
|
||||
character.rotation = Rotation.calculate(start.x, start.y, end.x, end.y)
|
||||
|
||||
const zoneEventTile = await prisma.zoneEventTile.findFirst({
|
||||
@ -79,62 +55,44 @@ export default class CharacterMove {
|
||||
zoneId: character.zoneId,
|
||||
positionX: Math.floor(end.x),
|
||||
positionY: Math.floor(end.y)
|
||||
}
|
||||
},
|
||||
include: { teleport: true }
|
||||
})
|
||||
|
||||
if (zoneEventTile) {
|
||||
if (zoneEventTile.type === 'BLOCK') {
|
||||
break
|
||||
}
|
||||
|
||||
if (zoneEventTile.type === 'TELEPORT') {
|
||||
const teleportTile = (await prisma.zoneEventTile.findFirst({
|
||||
where: { id: zoneEventTile.id },
|
||||
include: { teleport: true }
|
||||
})) as ZoneEventTileWithTeleport
|
||||
|
||||
if (teleportTile) {
|
||||
await this.handleZoneEventTile(teleportTile)
|
||||
break
|
||||
}
|
||||
}
|
||||
if (zoneEventTile?.type === 'BLOCK') break
|
||||
if (zoneEventTile?.type === 'TELEPORT' && zoneEventTile.teleport) {
|
||||
await this.handleZoneEventTile(zoneEventTile as ZoneEventTileWithTeleport)
|
||||
break
|
||||
}
|
||||
|
||||
this.characterMoveService.updatePosition(character, end)
|
||||
this.io.in(character.zoneId.toString()).emit('character:move', character)
|
||||
|
||||
this.io.in(character.zoneId.toString()).emit('character:move', zoneCharacter)
|
||||
await this.characterMoveService.applyMovementDelay()
|
||||
}
|
||||
|
||||
if (CharacterManager.hasResetMovement(character)) {
|
||||
character.resetMovement = false
|
||||
if (this.currentZoneId[character.id] === character.zoneId) {
|
||||
await this.moveAlongPath(character, this.nextPath[character.id])
|
||||
} else {
|
||||
delete this.currentZoneId[character.id]
|
||||
character.isMoving = false
|
||||
}
|
||||
const nextPath = this.nextPath.get(character.id)
|
||||
if (nextPath) {
|
||||
this.nextPath.delete(character.id)
|
||||
await this.moveAlongPath(zoneCharacter, nextPath)
|
||||
} else {
|
||||
this.finalizeMovement(character)
|
||||
this.finalizeMovement(zoneCharacter)
|
||||
}
|
||||
}
|
||||
|
||||
private async handleZoneEventTile(zoneEventTile: ZoneEventTileWithTeleport): Promise<void> {
|
||||
const character = CharacterManager.getCharacterFromSocket(this.socket)
|
||||
if (!character) {
|
||||
const zoneCharacter = ZoneManager.getCharacter(this.socket.characterId!)
|
||||
if (!zoneCharacter) {
|
||||
gameLogger.error('character:move error', 'Character not found')
|
||||
return
|
||||
}
|
||||
|
||||
const teleport = zoneEventTile.teleport
|
||||
if (teleport) {
|
||||
await this.zoneEventTileService.handleTeleport(this.io, this.socket, character, teleport)
|
||||
return
|
||||
if (zoneEventTile.teleport) {
|
||||
await this.zoneEventTileService.handleTeleport(this.io, this.socket, zoneCharacter.character, zoneEventTile.teleport)
|
||||
}
|
||||
}
|
||||
|
||||
private finalizeMovement(character: ExtendedCharacter): void {
|
||||
character.isMoving = false
|
||||
this.io.in(character.zoneId.toString()).emit('character:move', character)
|
||||
private finalizeMovement(zoneCharacter: ZoneCharacter): void {
|
||||
zoneCharacter.isMoving = false
|
||||
this.io.in(zoneCharacter.character.zoneId.toString()).emit('character:move', zoneCharacter)
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Server } from 'socket.io'
|
||||
import { TSocket } from '../utilities/types'
|
||||
import { gameLogger } from '../utilities/logger'
|
||||
import WeatherManager from '../managers/weatherManager'
|
||||
import { TSocket } from '../../utilities/types'
|
||||
import { gameLogger } from '../../utilities/logger'
|
||||
import WeatherManager from '../../managers/weatherManager'
|
||||
|
||||
export default class Weather {
|
||||
constructor(
|
Reference in New Issue
Block a user