feat: Implement MovingState class for turtle state machine to navigate to target positions
This commit is contained in:
78
server/states/MovingState.js
Normal file
78
server/states/MovingState.js
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
/**
|
||||||
|
* 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,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user