-- Created by Jef Roosens local logger = require('jlib.log').Logger:new{level=3, filename="treefarm.log"} local fuel = require('jlib.fuel') fuel.logger = logger local move = require('jlib.move').move -- Chop a 1x1 tree -- -- @param max_height height of tallest known tree -- -- @return height of chopped tree if greater than known highest, otherwise -- known highest local function chop(max_height, log_name) logger:log(3, "Chopping tree") -- Make sure we have enough fuel for the largest known tree fuel.check(2 * max_height + 1, { log_name }) -- Move one forward move('f') turtle.digDown() -- Chop up until we no longer find logs local _, data = turtle.inspectUp() local height = 0 while data.name == log_name do -- These checks most likely always succeed instantly thanks to the -- tallest tree system fuel.check(height, { log_name }) move('u', 1) _, data = turtle.inspectUp() height = height + 1 end -- Move back down move('d', height) -- Return the new height if it's greater than the old max_height = math.max(max_height, height) logger:debug("Max height: " .. max_height) return max_height end -- Select given item -- -- @param item_name name of item to select -- -- @return wether or not the item could be selected local function select_item(item_name) for i = 1, 16 do local data = turtle.getItemDetail(i) if data and data.name == item_name then turtle.select(i) return true end end return false end -- Do one cycle through the farm -- -- @param max_height height of tallest known tree -- -- @return new height of tallest known tree local function cycle(width, depth, max_height, sapling_name, log_name, spacing) logger:info("Starting cycle") for i = 1, width do -- Check for fuel to go through entire row fuel.check((spacing + 1) * (depth - 1) + 2, { log_name }) for j = 1, depth do local _, data = turtle.inspect() -- Chop down the tree, or move forward if data.name == log_name then -- Gotta re-do the check from the beginning of this row fuel.check( 2 * max_height + 1 + (spacing + 1) * (depth - j) + 2, { log_name }) max_height = chop(max_height, log_name) else move('f') end -- Place down a sapling, if possible if select_item(sapling_name) then turtle.placeDown() end -- Pick up any dropped saplings turtle.suckDown() -- Move forward if j < depth then move('f', spacing) else move('f') end end -- Turn if i < width then if i % 2 == 0 then turtle.turnLeft() else turtle.turnRight() end fuel.check(spacing + 1, { log_name }) move('f', spacing + 1) if i % 2 == 0 then turtle.turnLeft() else turtle.turnRight() end end end return max_height end -- Do maintenance stuff: drop off items, and restock on saplings local function maintenance(width, depth, sapling_name, log_name) logger:info("Doing maintenance") fuel.check(6, { log_name }) -- Move towards sapling chest move('f') turtle.turnLeft() move('f') -- Deposite all saplings while select_item(sapling_name) do turtle.drop(64) end -- Get enough saplings turtle.select(1) turtle.suck(width * depth) -- Move towards log chest turtle.turnRight() move('f') turtle.turnLeft() -- Deposite all logs -- First, find all spots with logs in them local slots, count = {}, 0 for i = 1, 16 do local data = turtle.getItemDetail(i) if data and data.name == log_name then count = count + data.count slots[i] = count end end -- Then, deposit logs as long as we have more than 10 logs left for slot, slot_count in pairs(slots) do -- Exit the loop if we have 10 or less logs if count <= 20 then break end -- Refuel with 64 unless count says otherwise turtle.select(slot) local c = math.min(slot_count, count - 20) turtle.drop(c) count = count - c end -- Keep 10 logs for refueling turtle.select(2) turtle.suck(20 - count) -- Get back to start block turtle.turnRight() turtle.turnRight() move('f') turtle.turnRight() move('f', 2) logger:info("Maintenance finished") end local function main() -- Load the settings, or quit if it fails if not settings.load(".treefarm.conf") then return logger:critical("Couldn't load configuration file. Please make sure it exists and doesn't contain syntax errors.") end -- Get all variables (API calls are slow) local width, depth, spacing, border_width, log_name, sapling_name, delay = settings.get("width"), settings.get("depth"), settings.get("spacing"), settings.get("border_width"), settings.get("log_name"), settings.get("sapling_name"), settings.get("delay") local max_height = 0 logger:info("Settings loaded") -- Start the main loop logger:info("Starting main loop") while true do -- Get into start position for cycle fuel.check(2, { log_name }) move('f', 2) -- Run through two cycles max_height = cycle(width, depth, max_height, sapling_name, log_name, spacing) turtle.turnRight() turtle.turnRight() sleep(delay) max_height = cycle(width, depth, max_height, sapling_name, log_name, spacing) -- Do maintenance and subtract maintenance time from delay fuel.check(border_width, { log_name }) move('f', border_width) local seconds = os.clock() maintenance(width, depth, sapling_name, log_name) sleep(math.max(0, delay - os.clock() + seconds)) end end main()