diff --git a/src/events/map/characterMove.ts b/src/events/map/characterMove.ts index d6db149..028f6de 100644 --- a/src/events/map/characterMove.ts +++ b/src/events/map/characterMove.ts @@ -31,6 +31,12 @@ export default class CharacterMove extends BaseEvent { const currentX = character.getPositionX() const currentY = character.getPositionY() + // Enhanced throttling with position tracking + const throttleKey = `movement_${this.socket.characterId}` + if (this.isThrottled(throttleKey, this.THROTTLE_DELAY)) { + return + } + // Validate current position against last known position const movementValidation = this.characterService.validateMovementDistance(currentX, currentY, this.lastKnownPosition, this.STEP_DELAY, mapCharacter.isMoving) @@ -50,15 +56,17 @@ export default class CharacterMove extends BaseEvent { return } + // If character is already moving to the same target position, ignore the request + if (mapCharacter.isMoving && mapCharacter.currentPath?.length) { + const lastPathPoint = mapCharacter.currentPath[mapCharacter.currentPath.length - 1] + if (lastPathPoint && Math.abs(lastPathPoint.positionX - positionX) < 1 && Math.abs(lastPathPoint.positionY - positionY) < 1) { + return + } + } + // Cancel any ongoing movement this.cancelCurrentMovement(mapCharacter) - // Enhanced throttling with position tracking - const throttleKey = `movement_${this.socket.characterId}` - if (this.isThrottled(throttleKey, this.THROTTLE_DELAY)) { - return - } - // Update last known position this.lastKnownPosition = { x: currentX, y: currentY } @@ -193,15 +201,19 @@ export default class CharacterMove extends BaseEvent { clearTimeout(this.movementTimeout) } - // Set new timeout - this.movementTimeout = setTimeout(() => { - // Only finalize if there are no pending movements - if (mapCharacter.currentPath === null) { - mapCharacter.isMoving = false - this.broadcastMovement(mapCharacter.character, false) - } - }, this.STEP_DELAY) - + // Clear the current path immediately mapCharacter.currentPath = null + + // Set new timeout for movement state cleanup + this.movementTimeout = setTimeout(() => { + // Ensure the character is still in a valid state + if (!mapCharacter.isMoving || !mapCharacter.currentPath) { + mapCharacter.isMoving = false + // Save the final position and broadcast it + mapCharacter.savePosition().then(() => { + this.broadcastMovement(mapCharacter.character, false) + }) + } + }, this.STEP_DELAY * 2) // Increased delay to ensure all movement processing is complete } }