185 lines
4.8 KiB
JavaScript
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);
|
|
}
|
|
}
|
|
}
|