forked from noxious/server
Move bug fixes
This commit is contained in:
parent
cd538bc4db
commit
5ce844c919
@ -5,14 +5,12 @@ import prisma from '../../utilities/Prisma'
|
|||||||
import { AStar, type Node } from '../../utilities/Player/AStar'
|
import { AStar, type Node } from '../../utilities/Player/AStar'
|
||||||
import Rotation from '../../utilities/Player/Rotation'
|
import Rotation from '../../utilities/Player/Rotation'
|
||||||
import { ExtendedCharacter as Character } from '../../utilities/Types'
|
import { ExtendedCharacter as Character } from '../../utilities/Types'
|
||||||
import { start } from 'node:repl'
|
|
||||||
|
|
||||||
interface SocketResponse {
|
interface SocketResponse {
|
||||||
position_x: number
|
position_x: number
|
||||||
position_y: number
|
position_y: number
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map to store movement tokens for each character
|
|
||||||
const characterMoveTokens = new Map<number, Symbol>()
|
const characterMoveTokens = new Map<number, Symbol>()
|
||||||
|
|
||||||
export default function setupCharacterMove(socket: TSocket, io: Server) {
|
export default function setupCharacterMove(socket: TSocket, io: Server) {
|
||||||
@ -25,19 +23,26 @@ export default function setupCharacterMove(socket: TSocket, io: Server) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cancel any ongoing movement for this character
|
const oldMoveToken = characterMoveTokens.get(socket.character.id)
|
||||||
|
if (oldMoveToken) {
|
||||||
|
characterMoveTokens.delete(socket.character.id)
|
||||||
|
}
|
||||||
|
|
||||||
const moveToken = Symbol('moveToken')
|
const moveToken = Symbol('moveToken')
|
||||||
characterMoveTokens.set(socket.character.id, moveToken)
|
characterMoveTokens.set(socket.character.id, moveToken)
|
||||||
|
|
||||||
const grid = await ZoneManager.getGrid(socket.character.zoneId)
|
const grid = await ZoneManager.getGrid(socket.character.zoneId)
|
||||||
|
|
||||||
if (grid.length === 0) {
|
if (!grid || grid.length === 0) {
|
||||||
console.error('character:move error', 'Grid not found')
|
console.error('character:move error', 'Grid not found or empty')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const start = { x: socket.character.position_x, y: socket.character.position_y }
|
const start = { x: Math.floor(socket.character.position_x), y: Math.floor(socket.character.position_y) }
|
||||||
const end = { x: data.position_x, y: data.position_y }
|
const end = { x: Math.floor(data.position_x), y: Math.floor(data.position_y) }
|
||||||
|
|
||||||
|
console.log('Pathfinding from', start, 'to', end)
|
||||||
|
console.log('Grid dimensions:', grid.length, 'x', grid[0].length)
|
||||||
|
|
||||||
const path = AStar.findPath(start, end, grid)
|
const path = AStar.findPath(start, end, grid)
|
||||||
|
|
||||||
@ -45,10 +50,10 @@ export default function setupCharacterMove(socket: TSocket, io: Server) {
|
|||||||
socket.character.isMoving = true
|
socket.character.isMoving = true
|
||||||
io.in(socket.character.zoneId.toString()).emit('character:moved', socket.character)
|
io.in(socket.character.zoneId.toString()).emit('character:moved', socket.character)
|
||||||
|
|
||||||
// Start movement in a non-blocking manner
|
|
||||||
moveAlongPath(socket, io, path, grid, moveToken).catch(console.error)
|
moveAlongPath(socket, io, path, grid, moveToken).catch(console.error)
|
||||||
} else {
|
} else {
|
||||||
console.log('character:move error', 'No valid path found')
|
console.log('character:move error', 'No valid path found')
|
||||||
|
socket.emit('character:moveError', 'No valid path found')
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('character:move error', error)
|
console.error('character:move error', error)
|
||||||
@ -65,18 +70,23 @@ async function moveAlongPath(socket: TSocket, io: Server, path: Node[], grid: nu
|
|||||||
|
|
||||||
const totalSteps = path.length
|
const totalSteps = path.length
|
||||||
const updateInterval = 50 // milliseconds between updates
|
const updateInterval = 50 // milliseconds between updates
|
||||||
const totalDuration = totalSteps * 250 // total duration of movement
|
|
||||||
|
|
||||||
for (let step = 0; step < totalSteps; step++) {
|
for (let step = 0; step < totalSteps; step++) {
|
||||||
const startTime = Date.now()
|
|
||||||
|
|
||||||
while (Date.now() - startTime < 250) { // 250ms per tile
|
|
||||||
if (characterMoveTokens.get(socket.character.id) !== moveToken) {
|
if (characterMoveTokens.get(socket.character.id) !== moveToken) {
|
||||||
console.log('Movement cancelled for character', socket.character.id)
|
console.log('Movement cancelled for character', socket.character.id)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const progress = (Date.now() - startTime) / 250
|
const startTime = Date.now()
|
||||||
|
const stepDuration = 250 // 250ms per tile
|
||||||
|
|
||||||
|
while (Date.now() - startTime < stepDuration) {
|
||||||
|
if (characterMoveTokens.get(socket.character.id) !== moveToken) {
|
||||||
|
console.log('Movement cancelled for character', socket.character.id)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const progress = (Date.now() - startTime) / stepDuration
|
||||||
const currentPosition = interpolatePosition(path[step], path[step + 1] || path[step], progress)
|
const currentPosition = interpolatePosition(path[step], path[step + 1] || path[step], progress)
|
||||||
|
|
||||||
if (isObstacle(currentPosition, grid)) {
|
if (isObstacle(currentPosition, grid)) {
|
||||||
@ -97,8 +107,9 @@ async function moveAlongPath(socket: TSocket, io: Server, path: Node[], grid: nu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (socket.character) {
|
if (socket.character && characterMoveTokens.get(socket.character.id) === moveToken) {
|
||||||
socket.character.isMoving = false
|
socket.character.isMoving = false
|
||||||
|
characterMoveTokens.delete(socket.character.id)
|
||||||
io.in(socket.character.zoneId.toString()).emit('character:moved', socket.character)
|
io.in(socket.character.zoneId.toString()).emit('character:moved', socket.character)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,9 +10,6 @@ export interface Node extends Position {
|
|||||||
f: number
|
f: number
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* A* pathfinding algorithm.
|
|
||||||
*/
|
|
||||||
export class AStar {
|
export class AStar {
|
||||||
private static readonly ORTHOGONAL_DIRECTIONS: Position[] = [
|
private static readonly ORTHOGONAL_DIRECTIONS: Position[] = [
|
||||||
{ x: 0, y: -1 }, { x: 0, y: 1 }, { x: -1, y: 0 }, { x: 1, y: 0 }
|
{ x: 0, y: -1 }, { x: 0, y: 1 }, { x: -1, y: 0 }, { x: 1, y: 0 }
|
||||||
@ -22,14 +19,6 @@ export class AStar {
|
|||||||
{ x: -1, y: -1 }, { x: -1, y: 1 }, { x: 1, y: -1 }, { x: 1, y: 1 }
|
{ x: -1, y: -1 }, { x: -1, y: 1 }, { x: 1, y: -1 }, { x: 1, y: 1 }
|
||||||
]
|
]
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds the shortest path from start to end on the given grid.
|
|
||||||
* @param start - Start position.
|
|
||||||
* @param end - End position.
|
|
||||||
* @param grid - The grid representing the map (0 = open space, 1 = obstacle).
|
|
||||||
* @param allowDiagonal - Whether diagonal movements are allowed.
|
|
||||||
* @returns Array of `Node` representing the path from start to end.
|
|
||||||
*/
|
|
||||||
static findPath(start: Position, end: Position, grid: number[][], allowDiagonal: boolean = false): Node[] {
|
static findPath(start: Position, end: Position, grid: number[][], allowDiagonal: boolean = false): Node[] {
|
||||||
const openList: Node[] = []
|
const openList: Node[] = []
|
||||||
const closedSet = new Set<string>()
|
const closedSet = new Set<string>()
|
||||||
@ -103,8 +92,16 @@ export class AStar {
|
|||||||
|
|
||||||
private static isValidPosition(pos: Position, grid: number[][], end: Position): boolean {
|
private static isValidPosition(pos: Position, grid: number[][], end: Position): boolean {
|
||||||
const { x, y } = pos
|
const { x, y } = pos
|
||||||
return x >= 0 && y >= 0 && x < grid.length && y < grid[0].length &&
|
|
||||||
(grid[y][x] === 0 || (x === end.x && y === end.y))
|
if (!grid || grid.length === 0 || !Array.isArray(grid[0])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const height = grid.length;
|
||||||
|
const width = grid[0].length;
|
||||||
|
|
||||||
|
return x >= 0 && x < width && y >= 0 && y < height &&
|
||||||
|
(grid[y][x] === 0 || (x === end.x && y === end.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static isInOpenList(openList: Node[], node: Position): boolean {
|
private static isInOpenList(openList: Node[], node: Position): boolean {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user