Walk improvements
This commit is contained in:
parent
ba96ae7dd4
commit
765a0468bc
@ -8,6 +8,8 @@ import TeleportService from '#services/characterTeleportService'
|
|||||||
|
|
||||||
export default class CharacterMove extends BaseEvent {
|
export default class CharacterMove extends BaseEvent {
|
||||||
private readonly characterService = CharacterService
|
private readonly characterService = CharacterService
|
||||||
|
private readonly MOVEMENT_CANCEL_DELAY = 100
|
||||||
|
private movementTimeouts: Map<string, NodeJS.Timeout> = new Map()
|
||||||
|
|
||||||
public listen(): void {
|
public listen(): void {
|
||||||
this.socket.on('map:character:move', this.handleEvent.bind(this))
|
this.socket.on('map:character:move', this.handleEvent.bind(this))
|
||||||
@ -20,34 +22,65 @@ export default class CharacterMove extends BaseEvent {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// If already moving, cancel current movement and wait for it to fully stop
|
// Clear any existing movement timeout
|
||||||
|
const existingTimeout = this.movementTimeouts.get(this.socket.characterId!)
|
||||||
|
if (existingTimeout) {
|
||||||
|
clearTimeout(existingTimeout)
|
||||||
|
this.movementTimeouts.delete(this.socket.characterId!)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If already moving, cancel current movement
|
||||||
if (mapCharacter.isMoving) {
|
if (mapCharacter.isMoving) {
|
||||||
mapCharacter.isMoving = false
|
mapCharacter.isMoving = false
|
||||||
mapCharacter.currentPath = null
|
mapCharacter.currentPath = null
|
||||||
await new Promise((resolve) => setTimeout(resolve, 10))
|
|
||||||
|
// Add small delay before starting new movement
|
||||||
|
await new Promise((resolve) => {
|
||||||
|
const timeout = setTimeout(resolve, this.MOVEMENT_CANCEL_DELAY)
|
||||||
|
this.movementTimeouts.set(this.socket.characterId!, timeout)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate target position is within reasonable range
|
||||||
|
const currentX = mapCharacter.character.positionX
|
||||||
|
const currentY = mapCharacter.character.positionY
|
||||||
|
const distance = Math.sqrt(Math.pow(positionX - currentX, 2) + Math.pow(positionY - currentY, 2))
|
||||||
|
|
||||||
|
if (distance > 20) {
|
||||||
|
// Maximum allowed distance
|
||||||
|
this.io.in(mapCharacter.character.map.id).emit('map:character:moveError', 'Target position too far')
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const path = await this.characterService.calculatePath(mapCharacter.character, positionX, positionY)
|
const path = await this.characterService.calculatePath(mapCharacter.character, positionX, positionY)
|
||||||
if (!path) {
|
if (!path?.length) {
|
||||||
this.io.in(mapCharacter.character.map.id).emit('map:character:moveError', 'No valid path found')
|
this.io.in(mapCharacter.character.map.id).emit('map:character:moveError', 'No valid path found')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start new movement
|
// Start new movement
|
||||||
mapCharacter.isMoving = true
|
mapCharacter.isMoving = true
|
||||||
mapCharacter.currentPath = path // Add this property to MapCharacter class
|
mapCharacter.currentPath = path
|
||||||
await this.moveAlongPath(mapCharacter, path)
|
await this.moveAlongPath(mapCharacter, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
private async moveAlongPath(mapCharacter: MapCharacter, path: Array<{ positionX: number; positionY: number }>): Promise<void> {
|
private async moveAlongPath(mapCharacter: MapCharacter, path: Array<{ positionX: number; positionY: number }>): Promise<void> {
|
||||||
const character = mapCharacter.getCharacter()
|
const character = mapCharacter.getCharacter()
|
||||||
|
|
||||||
|
try {
|
||||||
for (let i = 0; i < path.length - 1; i++) {
|
for (let i = 0; i < path.length - 1; i++) {
|
||||||
if (!mapCharacter.isMoving || mapCharacter.currentPath !== path) {
|
if (!mapCharacter.isMoving || mapCharacter.currentPath !== path) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const [start, end] = [path[i], path[i + 1]]
|
const [start, end] = [path[i], path[i + 1]]
|
||||||
|
|
||||||
|
// Validate each step
|
||||||
|
if (Math.abs(end.positionX - start.positionX) > 1 || Math.abs(end.positionY - start.positionY) > 1) {
|
||||||
|
this.logger.error('Invalid path step detected')
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
character.setRotation(CharacterService.calculateRotation(start.positionX, start.positionY, end.positionX, end.positionY))
|
character.setRotation(CharacterService.calculateRotation(start.positionX, start.positionY, end.positionX, end.positionY))
|
||||||
|
|
||||||
const mapEventTileRepository = new MapEventTileRepository()
|
const mapEventTileRepository = new MapEventTileRepository()
|
||||||
@ -73,11 +106,12 @@ export default class CharacterMove extends BaseEvent {
|
|||||||
|
|
||||||
await this.characterService.applyMovementDelay()
|
await this.characterService.applyMovementDelay()
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
if (mapCharacter.isMoving && mapCharacter.currentPath === path) {
|
if (mapCharacter.isMoving && mapCharacter.currentPath === path) {
|
||||||
this.finalizeMovement(mapCharacter)
|
this.finalizeMovement(mapCharacter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async handleTeleportMapEventTile(mapEventTile: MapEventTileWithTeleport): Promise<void> {
|
private async handleTeleportMapEventTile(mapEventTile: MapEventTileWithTeleport): Promise<void> {
|
||||||
if (mapEventTile.getTeleport()) {
|
if (mapEventTile.getTeleport()) {
|
||||||
|
@ -8,6 +8,7 @@ export type Node = Position & { parent?: Node; g: number; h: number; f: number }
|
|||||||
|
|
||||||
class CharacterMoveService extends BaseService {
|
class CharacterMoveService extends BaseService {
|
||||||
private readonly MOVEMENT_DELAY_MS = 260
|
private readonly MOVEMENT_DELAY_MS = 260
|
||||||
|
private readonly MAX_PATH_LENGTH = 20 // Limit maximum path length
|
||||||
|
|
||||||
private readonly DIRECTIONS = [
|
private readonly DIRECTIONS = [
|
||||||
{ x: 0, y: -1 }, // Up
|
{ x: 0, y: -1 }, // Up
|
||||||
@ -45,7 +46,21 @@ class CharacterMoveService extends BaseService {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.findPath(start, end, grid)
|
// Add maximum distance check
|
||||||
|
const directDistance = Math.sqrt(Math.pow(targetX - character.positionX, 2) + Math.pow(targetY - character.positionY, 2))
|
||||||
|
|
||||||
|
if (directDistance > this.MAX_PATH_LENGTH) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const path = this.findPath(start, end, grid)
|
||||||
|
|
||||||
|
// Validate path length
|
||||||
|
if (path.length > this.MAX_PATH_LENGTH) {
|
||||||
|
return path.slice(0, this.MAX_PATH_LENGTH)
|
||||||
|
}
|
||||||
|
|
||||||
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
public calculateRotation(X1: number, Y1: number, X2: number, Y2: number): number {
|
public calculateRotation(X1: number, Y1: number, X2: number, Y2: number): number {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user