Files
remoteturtle/server/states/MovingState.js

79 lines
2.0 KiB
JavaScript

/**
* MovingState - Navigate the turtle to a target position using D* Lite
*/
import { BaseState } from './BaseState.js';
export class MovingState extends BaseState {
constructor(turtle, data = {}) {
super(turtle, data);
this.target = data.target; // {x, y, z}
this.onArrival = data.onArrival || null; // Callback/next state when arrived
this.canMine = data.canMine !== false;
}
get name() {
return 'moving';
}
get description() {
const pos = this.target;
if (pos) {
return `Moving to (${pos.x}, ${pos.y}, ${pos.z})`;
}
return 'Moving to target';
}
async *act() {
if (!this.target) {
console.log(`[${this.turtle.id}] MovingState: No target set`);
this.turtle.setState('idle');
return;
}
console.log(`[${this.turtle.id}] Moving to ${this.target.x},${this.target.y},${this.target.z}`);
// Use the navigateTo generator from BaseState
const nav = this.navigateTo(this.target, { canMine: this.canMine });
for await (const _ of nav) {
if (this.cancelled) return;
yield;
}
// Check if we actually arrived
const pos = this.turtle.position;
if (pos) {
const { Point } = await import('../pathfinding/index.js');
const current = Point.from(pos);
const goal = Point.from(this.target);
if (current.distanceTo(goal) <= 1) {
console.log(`[${this.turtle.id}] Arrived at destination`);
if (this.onArrival === 'idle') {
this.turtle.setState('idle');
} else if (this.onArrival === 'mine') {
this.turtle.setState('mining', this.data);
} else {
this.turtle.setState('idle');
}
return;
}
}
console.log(`[${this.turtle.id}] Failed to reach destination`);
this.turtle.setState('idle');
}
getRecoveryData() {
return {
...super.getRecoveryData(),
data: {
target: this.target,
onArrival: this.onArrival,
canMine: this.canMine,
},
};
}
}