feat: Implement RefuelingState class for turtle state machine to manage fuel replenishment
This commit is contained in:
126
server/states/RefuelingState.js
Normal file
126
server/states/RefuelingState.js
Normal file
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
* RefuelingState - Refuel the turtle from inventory or nearby containers
|
||||
* Prioritizes fuel sources: lava buckets > coal blocks > coal > logs > sticks
|
||||
*/
|
||||
import { BaseState } from './BaseState.js';
|
||||
|
||||
const FUEL_PRIORITY = [
|
||||
'minecraft:lava_bucket',
|
||||
'minecraft:coal_block',
|
||||
'minecraft:charcoal',
|
||||
'minecraft:coal',
|
||||
'minecraft:oak_log', 'minecraft:birch_log', 'minecraft:spruce_log',
|
||||
'minecraft:dark_oak_log', 'minecraft:jungle_log', 'minecraft:acacia_log',
|
||||
'minecraft:mangrove_log', 'minecraft:cherry_log',
|
||||
'minecraft:oak_planks', 'minecraft:birch_planks', 'minecraft:spruce_planks',
|
||||
'minecraft:stick',
|
||||
];
|
||||
|
||||
export class RefuelingState extends BaseState {
|
||||
constructor(turtle, data = {}) {
|
||||
super(turtle, data);
|
||||
this.returnState = data.returnState || null;
|
||||
this.returnData = data.returnData || {};
|
||||
this.targetFuel = data.targetFuel || 5000;
|
||||
}
|
||||
|
||||
get name() {
|
||||
return 'refueling';
|
||||
}
|
||||
|
||||
get description() {
|
||||
return 'Refueling turtle';
|
||||
}
|
||||
|
||||
async *act() {
|
||||
console.log(`[${this.turtle.id}] Starting refueling, target: ${this.targetFuel}`);
|
||||
|
||||
// First try to refuel from own inventory using priority order
|
||||
const refueled = await this.exec(`
|
||||
local fuelPriority = ${this._luaFuelTable()}
|
||||
local targetFuel = ${this.targetFuel}
|
||||
local refueled = false
|
||||
|
||||
for _, fuelName in ipairs(fuelPriority) do
|
||||
for slot = 1, 16 do
|
||||
local item = turtle.getItemDetail(slot)
|
||||
if item and item.name == fuelName then
|
||||
turtle.select(slot)
|
||||
turtle.refuel()
|
||||
refueled = true
|
||||
if turtle.getFuelLevel() >= targetFuel then
|
||||
turtle.select(1)
|
||||
return {success = true, fuel = turtle.getFuelLevel()}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
turtle.select(1)
|
||||
return {success = refueled, fuel = turtle.getFuelLevel()}
|
||||
`);
|
||||
|
||||
if (refueled) {
|
||||
this.turtle.fuel = refueled.fuel;
|
||||
console.log(`[${this.turtle.id}] Refueled to ${refueled.fuel}`);
|
||||
}
|
||||
|
||||
yield;
|
||||
|
||||
// Try to refuel from nearby containers (chests, barrels)
|
||||
if (!refueled || !refueled.success || refueled.fuel < this.targetFuel) {
|
||||
console.log(`[${this.turtle.id}] Trying nearby containers for fuel`);
|
||||
|
||||
const containerResult = await this.exec(`
|
||||
local directions = {"front", "top", "bottom"}
|
||||
local suckFns = {turtle.suck, turtle.suckUp, turtle.suckDown}
|
||||
|
||||
for i, dir in ipairs(directions) do
|
||||
-- Try to suck items from container
|
||||
for attempt = 1, 16 do
|
||||
if suckFns[i]() then
|
||||
-- Check if it's fuel
|
||||
local slot = turtle.getSelectedSlot()
|
||||
if turtle.refuel(0) then
|
||||
turtle.refuel()
|
||||
end
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return {fuel = turtle.getFuelLevel()}
|
||||
`);
|
||||
|
||||
if (containerResult) {
|
||||
this.turtle.fuel = containerResult.fuel;
|
||||
}
|
||||
}
|
||||
|
||||
yield;
|
||||
|
||||
// Transition to next state
|
||||
if (this.returnState) {
|
||||
this.turtle.setState(this.returnState, this.returnData);
|
||||
} else {
|
||||
this.turtle.setState('idle');
|
||||
}
|
||||
}
|
||||
|
||||
_luaFuelTable() {
|
||||
const items = FUEL_PRIORITY.map(name => `"${name}"`).join(', ');
|
||||
return `{${items}}`;
|
||||
}
|
||||
|
||||
getRecoveryData() {
|
||||
return {
|
||||
...super.getRecoveryData(),
|
||||
data: {
|
||||
returnState: this.returnState,
|
||||
returnData: this.returnData,
|
||||
targetFuel: this.targetFuel,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user