Files
remoteturtle/server/states/ScanState.js

185 lines
4.8 KiB
JavaScript

/**
* ScanState - Systematic scanning of surroundings using peripheral scanners
*
* Supports multiple scanner types:
* - geoScanner (Advanced Peripherals)
* - universal_scanner
* - plethora:scanner (Plethora mod)
* - Native turtle.inspect() fallback (6-directional scan)
*/
import { BaseState } from './BaseState.js';
export class ScanState extends BaseState {
constructor(turtle, data = {}) {
super(turtle, data);
this.scanRadius = data.scanRadius || 16;
this.blocksScanned = 0;
this.scannerType = null;
}
get name() {
return 'scanning';
}
get description() {
return `Scanning (${this.scannerType || 'detecting'}) - ${this.blocksScanned} blocks`;
}
async *act() {
console.log(`[${this.turtle.id}] Starting scan`);
// Detect available scanner peripheral
this.scannerType = await this._detectScanner();
yield;
if (this.scannerType === 'geoScanner') {
yield* this._geoScan();
} else if (this.scannerType === 'universal_scanner') {
yield* this._universalScan();
} else if (this.scannerType === 'plethora:scanner') {
yield* this._plethuraScan();
} else {
// Fallback to native inspect-based scanning
yield* this._nativeScan();
}
console.log(`[${this.turtle.id}] Scan complete: ${this.blocksScanned} blocks`);
this.turtle.setState('idle');
}
async _detectScanner() {
// Check for geoScanner
const geoResult = await this.exec(`
local names = peripheral.getNames()
for _, name in ipairs(names) do
local types = {peripheral.getType(name)}
for _, t in ipairs(types) do
if t == "geoScanner" then return "geoScanner" end
end
end
return nil
`);
if (geoResult) return geoResult;
// Check for universal_scanner
const uniResult = await this.exec(`
local names = peripheral.getNames()
for _, name in ipairs(names) do
local types = {peripheral.getType(name)}
for _, t in ipairs(types) do
if t == "universal_scanner" then return "universal_scanner" end
end
end
return nil
`);
if (uniResult) return uniResult;
// Check for plethora scanner
const plResult = await this.exec(`
local names = peripheral.getNames()
for _, name in ipairs(names) do
local types = {peripheral.getType(name)}
for _, t in ipairs(types) do
if t == "plethora:scanner" then return "plethora:scanner" end
end
end
return nil
`);
if (plResult) return plResult;
return 'native';
}
async *_geoScan() {
// Wait for cooldown
yield;
await this._sleep(500);
const result = await this.exec(`
local scanner = peripheral.find("geoScanner")
if not scanner then return nil end
local ok, blocks = pcall(scanner.scan, ${this.scanRadius})
if ok then return blocks end
return nil
`);
if (result && Array.isArray(result)) {
this._processScannedBlocks(result);
}
yield;
}
async *_universalScan() {
yield;
await this._sleep(500);
const result = await this.exec(`
local scanner = peripheral.find("universal_scanner")
if not scanner then return nil end
local ok, blocks = pcall(scanner.scan, "block", ${this.scanRadius})
if ok then return blocks end
return nil
`);
if (result && Array.isArray(result)) {
this._processScannedBlocks(result);
}
yield;
}
async *_plethuraScan() {
yield;
const result = await this.exec(`
local scanner = peripheral.find("plethora:scanner")
if not scanner then return nil end
local ok, blocks = pcall(scanner.scan)
if ok then return blocks end
return nil
`);
if (result && Array.isArray(result)) {
this._processScannedBlocks(result);
}
yield;
}
async *_nativeScan() {
// Fallback: scan all 6 directions using turtle.inspect
const scanResult = await this.scanSurroundings();
if (scanResult) {
this.blocksScanned += Object.keys(scanResult).length;
}
yield;
}
_processScannedBlocks(blocks) {
const pos = this.turtle.position;
if (!pos) return;
const discoveredBlocks = [];
for (const block of blocks) {
if (!block || !block.name) continue;
if (block.name === 'minecraft:air') continue;
if (block.x === 0 && block.y === 0 && block.z === 0) continue;
discoveredBlocks.push({
x: pos.x + (block.x || 0),
y: pos.y + (block.y || 0),
z: pos.z + (block.z || 0),
name: block.name,
metadata: block.metadata || 0,
state: block.state || {},
tags: block.tags || {},
discoveredBy: this.turtle.id,
});
}
this.blocksScanned = discoveredBlocks.length;
if (discoveredBlocks.length > 0) {
this.turtle.emit('blocksDiscovered', discoveredBlocks);
}
}
}