local T = require("lib") --[[ States: - MOVE_TO_TREE - CHECK_TREE - ASCEND_TREE - FINALIZE_TREE - OUTPUT - RESUPPLY_SAPS - RESUPPLY_FUEL Persistent Variables: - current_state - current_tree [1,14] - current_row [1,6] Inventory: 64 + 20 Saplings in Slots 1 and 2 ]] local MAX_TREE = 14 local MAX_ROW = 6 local OUTPUT_TARGET = { x = 2, z = 0, o = "+z" } local SAPS_TARGET = { x = 1, z = 0, o = "+z" } local FUEL_TARGET = { x = 0, z = 0, o = "+z" } local TREE_MAX_HEIGHT = 7 -- Saplings are at y = -1 (and coordinates are zero-based) local TREE_MAX_Y = TREE_MAX_HEIGHT - 2 local LOG_NAME = "minecraft:birch_log" local SAP_SLOT = 1 local BACKUP_SAP_SLOT = 2 local REFUEL_SLOT = 3 local SAP_SLOT_TARGET_COUNT = 64 local BACKUP_SAP_SLOT_TARGET_COUNT = 20 -- Should be enough even if every tree is fully grown local FUEL_LEVEL_TARGET = 1000 local function calculate_tree_position(row_index, tree_index) local x = (row_index - 1) * 5 local z if row_index % 2 == 1 then z = -2 * tree_index else z = -30 + 2 * tree_index end return x, z end local function greedy_move(x, z, o) print("Move Target: " .. x .. "," .. z .. " (" .. o .. ")") if z ~= T.state.z then if z > T.state.z then T.rotateTowards("+z") else T.rotateTowards("-z") end for _ = 1, math.abs(z - T.state.z) do while not T.fwd() do sleep(1) end end end if x ~= T.state.x then if x > T.state.x then T.rotateTowards("+x") else T.rotateTowards("-x") end for _ = 1, math.abs(x - T.state.x) do while not T.fwd() do sleep(1) end end end T.rotateTowards(o) end local function ensure_item_count(count) if turtle.getItemCount() >= count then return end turtle.suck(count - turtle.getItemCount()) -- turtle.suck might not suck enough items if the target container does not have them -- but it won't tell us if this happened... while turtle.getItemCount() ~= count do sleep(1) turtle.suck(count - turtle.getItemCount()) end end local state_machine = { ["MOVE_TO_TREE"] = function() -- get target tree coordinates -- and move such that we are facing it local x, z = calculate_tree_position(T.state.current_row, T.state.current_tree) local o if T.state.current_row ~= 1 and T.state.current_tree == 1 then -- we just turned towards a new row and are approaching in positive x direction x = x - 1 o = "+x" elseif T.state.current_row % 2 == 0 then -- we are in an even row and approaching in positive z direction z = z - 1 o = "+z" else -- we are approaching in negative z direction z = z + 1 o = "-z" end greedy_move(x, z, o) return "CHECK_TREE" end, ["CHECK_TREE"] = function() if not turtle.detect() then -- no tree, so skip ascending T.fwd() return "FINALIZE_TREE" else -- tree present, chop it down turtle.dig() T.fwd() turtle.digDown() return "ASCEND_TREE" end end, ["ASCEND_TREE"] = function() local success, data = turtle.inspectUp() if not success and T.state.y < TREE_MAX_Y - 1 then -- probably reset after chopping a block T.up() end while true do local success, data = turtle.inspectUp() if not success or data.name ~= LOG_NAME then -- chopped all the wood break end turtle.digUp() if T.state.y == TREE_MAX_Y - 1 then -- we are below the last log, no need to move up break end T.up() end return "FINALIZE_TREE" end, ["FINALIZE_TREE"] = function() -- make sure we are directly above the sapling target while T.state.y > 0 do while not T.down() do -- another tree might have spawned leaves below us turtle.digDown() end end turtle.select(SAP_SLOT) -- make sure we have a sapling if turtle.getItemCount() == 0 then turtle.select(BACKUP_SAP_SLOT) turtle.transferTo(SAP_SLOT) turtle.select(SAP_SLOT) end turtle.placeDown() if T.state.current_tree < MAX_TREE then -- go to the next tree in this row T.state.current_tree = T.state.current_tree + 1 return "MOVE_TO_TREE" elseif T.state.current_row < MAX_ROW then -- go to the first tree in the next row T.state.current_tree = 1 T.state.current_row = T.state.current_row + 1 return "MOVE_TO_TREE" else -- went through the entire farm once return "OUTPUT" end end, ["OUTPUT"] = function() greedy_move(OUTPUT_TARGET.x, OUTPUT_TARGET.z, OUTPUT_TARGET.o) -- Drop all logs for slot = 1, 16 do turtle.select(slot) data = turtle.getItemDetail() if data and data.name == LOG_NAME then turtle.drop() end end return "RESUPPLY_SAPS" end, ["RESUPPLY_SAPS"] = function() greedy_move(SAPS_TARGET.x, SAPS_TARGET.z, SAPS_TARGET.o) turtle.select(SAP_SLOT) ensure_item_count(SAP_SLOT_TARGET_COUNT) turtle.select(BACKUP_SAP_SLOT) ensure_item_count(BACKUP_SAP_SLOT_TARGET_COUNT) return "RESUPPLY_FUEL" end, ["RESUPPLY_FUEL"] = function() greedy_move(FUEL_TARGET.x, FUEL_TARGET.z, FUEL_TARGET.o) if turtle.getFuelLevel() < FUEL_LEVEL_TARGET then local fuel_count = math.ceil((FUEL_LEVEL_TARGET - turtle.getFuelLevel()) / 80) turtle.select(REFUEL_SLOT) ensure_item_count(fuel_count) turtle.refuel() end T.state.current_row = 1 T.state.current_tree = 1 return "MOVE_TO_TREE" end, } -- initial setup if not T.state.current_state then T.setPosition(0, 0, 0, "+z") T.state.current_state = "RESUPPLY_FUEL" end -- main loop while true do print("---------------") print("State: " .. T.state.current_state) print("Pos: " .. T.state.x .. "," .. T.state.z .. "(" .. T.getOrientation() .. ")") T.state.current_state = state_machine[T.state.current_state]() end