sCCripts/treefarm.lua

234 lines
6.0 KiB
Lua

-- 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()