feat: Implement FarmingState class for turtle state machine to automate farming operations

This commit is contained in:
MayaTheShy
2026-02-20 01:45:46 -05:00
parent fa98e86055
commit d2185ac493

View File

@@ -0,0 +1,124 @@
/**
* FarmingState - Automated farming (plant, harvest, replant)
* Works with wheat, carrots, potatoes, beetroot, etc.
*/
import { BaseState } from './BaseState.js';
const CROP_SEEDS = {
'minecraft:wheat': 'minecraft:wheat_seeds',
'minecraft:carrots': 'minecraft:carrot',
'minecraft:potatoes': 'minecraft:potato',
'minecraft:beetroots': 'minecraft:beetroot_seeds',
};
export class FarmingState extends BaseState {
constructor(turtle, data = {}) {
super(turtle, data);
this.area = data.area || null; // {minX, minZ, maxX, maxZ, y}
this.harvestCount = 0;
}
get name() {
return 'farming';
}
get description() {
return `Farming - ${this.harvestCount} harvested`;
}
async *act() {
console.log(`[${this.turtle.id}] Starting farming operation`);
if (!this.area) {
console.log(`[${this.turtle.id}] No farming area defined`);
this.turtle.setState('idle');
return;
}
// Farm in a zigzag pattern over the area
const { minX, minZ, maxX, maxZ, y } = this.area;
let direction = 1; // 1 = positive Z, -1 = negative Z
for (let x = minX; x <= maxX; x++) {
const zStart = direction === 1 ? minZ : maxZ;
const zEnd = direction === 1 ? maxZ : minZ;
const zStep = direction;
for (let z = zStart; direction === 1 ? z <= zEnd : z >= zEnd; z += zStep) {
if (this.cancelled) return;
// Navigate to position above the crop
const target = { x, y: y + 1, z };
const navGen = this.navigateTo(target);
for await (const _ of navGen) {
if (this.cancelled) return;
yield;
}
// Check the block below
const blockBelow = await this.exec(`
local hasBlock, data = turtle.inspectDown()
if hasBlock then
return {name = data.name, state = data.state}
end
return nil
`);
if (blockBelow) {
// Check if crop is mature (age = 7 for most crops)
const isMature = blockBelow.state && blockBelow.state.age === 7;
if (isMature) {
// Harvest
await this.exec('turtle.digDown()');
this.harvestCount++;
// Replant
const seedName = CROP_SEEDS[blockBelow.name];
if (seedName) {
await this.exec(`
for slot = 1, 16 do
local item = turtle.getItemDetail(slot)
if item and item.name == "${seedName}" then
turtle.select(slot)
turtle.placeDown()
turtle.select(1)
return true
end
end
return false
`);
}
}
}
yield;
}
direction *= -1; // Zigzag
}
// Done farming one pass - check inventory
const isFull = await this.isInventoryFull();
if (isFull) {
this.turtle.setState('goHome', {
reason: 'inventory_full',
returnState: 'farming',
returnData: this.data
});
} else {
// Start another pass
console.log(`[${this.turtle.id}] Farm pass complete, ${this.harvestCount} harvested`);
yield* this.act(); // Loop
}
}
getRecoveryData() {
return {
...super.getRecoveryData(),
data: {
area: this.area,
},
};
}
}