Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- ============================================================
- -- Six-tree automatic tree farm
- -- For a ComputerCraft / CC:Tweaked Felling Turtle
- --
- -- Starting position:
- -- X = 286
- -- Z = 108
- -- Y = 63
- --
- -- IMPORTANT:
- -- Turtle must start facing +Z (toward Z=109,110,...)
- --
- -- Chest must be directly UNDER the turtle's starting position.
- -- ============================================================
- -- ------------------------------------------------------------
- -- CONFIGURATION
- -- ------------------------------------------------------------
- local HOME_X = 286
- local HOME_Z = 108
- -- Tree coordinates, expressed as X/Z because all are at Y=63.
- local trees = {
- { x = 284, z = 110 },
- { x = 288, z = 110 },
- { x = 284, z = 114 },
- { x = 288, z = 114 },
- { x = 284, z = 118 },
- { x = 288, z = 118 }
- }
- -- How long to wait between complete farm checks.
- local CHECK_INTERVAL = 30
- -- Maximum bone-meal attempts before giving up on a sapling.
- local MAX_BONEMEAL_ATTEMPTS = 32
- -- Refuel if below this amount.
- local MIN_FUEL = 250
- -- ------------------------------------------------------------
- -- POSITION TRACKING
- -- ------------------------------------------------------------
- --
- -- Direction:
- -- 0 = +Z
- -- 1 = -X
- -- 2 = -Z
- -- 3 = +X
- --
- -- We start facing +Z.
- -- ------------------------------------------------------------
- local posX = HOME_X
- local posZ = HOME_Z
- local direction = 0
- local function turnLeft()
- turtle.turnLeft()
- direction = (direction + 1) % 4
- end
- local function turnRight()
- turtle.turnRight()
- direction = (direction + 3) % 4
- end
- local function face(target)
- while direction ~= target do
- turnRight()
- end
- end
- local function forward()
- local attempts = 0
- while not turtle.forward() do
- attempts = attempts + 1
- if attempts > 20 then
- error("Unable to move forward.")
- end
- -- Don't automatically destroy random obstacles.
- sleep(0.25)
- end
- if direction == 0 then
- posZ = posZ + 1
- elseif direction == 1 then
- posX = posX - 1
- elseif direction == 2 then
- posZ = posZ - 1
- elseif direction == 3 then
- posX = posX + 1
- end
- end
- local function back()
- local attempts = 0
- while not turtle.back() do
- attempts = attempts + 1
- if attempts > 20 then
- error("Unable to move backward.")
- end
- sleep(0.25)
- end
- if direction == 0 then
- posZ = posZ - 1
- elseif direction == 1 then
- posX = posX + 1
- elseif direction == 2 then
- posZ = posZ + 1
- elseif direction == 3 then
- posX = posX - 1
- end
- end
- -- ------------------------------------------------------------
- -- NAVIGATION
- -- ------------------------------------------------------------
- local function moveTo(x, z)
- -- X movement
- if posX < x then
- face(3) -- +X
- while posX < x do
- forward()
- end
- elseif posX > x then
- face(1) -- -X
- while posX > x do
- forward()
- end
- end
- -- Z movement
- if posZ < z then
- face(0) -- +Z
- while posZ < z do
- forward()
- end
- elseif posZ > z then
- face(2) -- -Z
- while posZ > z do
- forward()
- end
- end
- end
- local function goHome()
- moveTo(HOME_X, HOME_Z)
- face(0)
- end
- -- ------------------------------------------------------------
- -- ITEM IDENTIFICATION
- -- ------------------------------------------------------------
- local function endsWith(text, suffix)
- return text:sub(-#suffix) == suffix
- end
- local function isSaplingName(name)
- if not name then
- return false
- end
- return endsWith(name, "_sapling") or
- name == "minecraft:mangrove_propagule"
- end
- local function isLogName(name)
- if not name then
- return false
- end
- return endsWith(name, "_log") or
- endsWith(name, "_wood") or
- endsWith(name, "_stem") or
- endsWith(name, "_hyphae")
- end
- local function isFuelName(name)
- return name == "minecraft:coal" or
- name == "minecraft:charcoal" or
- name == "minecraft:coal_block"
- end
- local function isBoneMealName(name)
- return name == "minecraft:bone_meal"
- end
- -- ------------------------------------------------------------
- -- INVENTORY SEARCH
- -- ------------------------------------------------------------
- local function findItem(testFunction)
- for slot = 1, 16 do
- local item = turtle.getItemDetail(slot)
- if item and testFunction(item.name) then
- return slot, item
- end
- end
- return nil
- end
- local function findBoneMeal()
- return findItem(isBoneMealName)
- end
- local function findAnySapling()
- return findItem(isSaplingName)
- end
- local function findExactItem(name)
- for slot = 1, 16 do
- local item = turtle.getItemDetail(slot)
- if item and item.name == name then
- return slot
- end
- end
- return nil
- end
- -- ------------------------------------------------------------
- -- FUEL
- -- ------------------------------------------------------------
- local function refuel()
- local fuel = turtle.getFuelLevel()
- if fuel == "unlimited" then
- return true
- end
- if fuel >= MIN_FUEL then
- return true
- end
- print("Fuel low: " .. fuel)
- for slot = 1, 16 do
- local item = turtle.getItemDetail(slot)
- if item and isFuelName(item.name) then
- turtle.select(slot)
- while turtle.getItemCount(slot) > 0 and
- turtle.getFuelLevel() < MIN_FUEL do
- turtle.refuel(1)
- end
- if turtle.getFuelLevel() >= MIN_FUEL then
- print("Refueled: " .. turtle.getFuelLevel())
- return true
- end
- end
- end
- print("WARNING: No fuel available!")
- return false
- end
- -- ------------------------------------------------------------
- -- BLOCK INSPECTION
- -- ------------------------------------------------------------
- local function blockInFront()
- local success, block = turtle.inspect()
- if success then
- return block
- end
- return nil
- end
- local function logInFront()
- local block = blockInFront()
- return block and isLogName(block.name)
- end
- local function logAbove()
- local success, block = turtle.inspectUp()
- return success and isLogName(block.name)
- end
- local function logBelow()
- local success, block = turtle.inspectDown()
- return success and isLogName(block.name)
- end
- -- ------------------------------------------------------------
- -- RECURSIVE TREE HARVEST
- --
- -- Turtle should be standing INSIDE the location of a log which
- -- it has just removed.
- --
- -- Every recursive call returns the turtle to exactly the same
- -- location and orientation from which that call started.
- -- ------------------------------------------------------------
- local function harvestConnectedLogs()
- -- ----- LOG ABOVE -----
- if logAbove() then
- turtle.digUp()
- if turtle.up() then
- harvestConnectedLogs()
- turtle.down()
- end
- end
- -- ----- LOG BELOW -----
- --
- -- Normally the parent log has already been removed, so this
- -- will not cause us to walk back through the tree.
- --
- -- It also catches unusual downward-connected branches.
- --
- if logBelow() then
- turtle.digDown()
- if turtle.down() then
- harvestConnectedLogs()
- turtle.up()
- end
- end
- -- ----- FOUR HORIZONTAL DIRECTIONS -----
- for side = 1, 4 do
- if logInFront() then
- turtle.dig()
- if turtle.forward() then
- harvestConnectedLogs()
- turtle.back()
- end
- end
- turtle.turnRight()
- end
- end
- -- ------------------------------------------------------------
- -- DETERMINE REPLACEMENT SAPLING FROM LOG TYPE
- -- ------------------------------------------------------------
- local function saplingFromLog(logName)
- if not logName then
- return nil
- end
- -- minecraft:oak_log -> minecraft:oak_sapling
- if endsWith(logName, "_log") then
- local prefix = logName:sub(1, #logName - 4)
- return prefix .. "_sapling"
- end
- -- Wood variants
- if endsWith(logName, "_wood") then
- local prefix = logName:sub(1, #logName - 5)
- return prefix .. "_sapling"
- end
- return nil
- end
- -- ------------------------------------------------------------
- -- GROW SAPLING
- -- ------------------------------------------------------------
- local function growSapling()
- for attempt = 1, MAX_BONEMEAL_ATTEMPTS do
- local block = blockInFront()
- -- It grew.
- if block and isLogName(block.name) then
- print("Tree grew after " .. (attempt - 1) ..
- " bone meal attempts.")
- return true, block.name
- end
- -- No longer a sapling and not a log.
- if not block or not isSaplingName(block.name) then
- return false, nil
- end
- local slot = findBoneMeal()
- if not slot then
- print("Out of bone meal.")
- return false, nil
- end
- turtle.select(slot)
- turtle.place()
- sleep(0.15)
- end
- local block = blockInFront()
- if block and isLogName(block.name) then
- return true, block.name
- end
- print("Sapling did not grow.")
- return false, nil
- end
- -- ------------------------------------------------------------
- -- PLANT SAPLING
- -- ------------------------------------------------------------
- local function plantSapling(preferredName)
- local slot = nil
- -- Try to use the same species.
- if preferredName then
- slot = findExactItem(preferredName)
- end
- -- Otherwise use whatever sapling is available.
- if not slot then
- slot = findAnySapling()
- end
- if not slot then
- print("WARNING: No saplings available!")
- return false
- end
- turtle.select(slot)
- if turtle.place() then
- print("Sapling planted.")
- return true
- end
- print("WARNING: Unable to plant sapling.")
- return false
- end
- -- ------------------------------------------------------------
- -- HARVEST A SINGLE TREE
- --
- -- Turtle is standing one block NORTH (-Z) of the planting spot
- -- and facing SOUTH (+Z).
- -- ------------------------------------------------------------
- local function processTree()
- local block = blockInFront()
- if not block then
- print("Planting spot is empty.")
- plantSapling(nil)
- return
- end
- local preferredSapling = nil
- -- --------------------------------------------------------
- -- SAPLING
- -- --------------------------------------------------------
- if isSaplingName(block.name) then
- print("Sapling detected: " .. block.name)
- preferredSapling = block.name
- local grown, logName = growSapling()
- if not grown then
- print("Leaving sapling for next pass.")
- return
- end
- block = blockInFront()
- if not block then
- return
- end
- end
- -- --------------------------------------------------------
- -- TREE
- -- --------------------------------------------------------
- if isLogName(block.name) then
- print("Tree detected: " .. block.name)
- if not preferredSapling then
- preferredSapling = saplingFromLog(block.name)
- end
- -- Remove base trunk.
- turtle.dig()
- -- Move into the space previously occupied by the trunk.
- if not turtle.forward() then
- print("ERROR: Could not enter trunk location.")
- return
- end
- -- Cut every connected log.
- harvestConnectedLogs()
- -- Return to our approach square.
- turtle.back()
- -- Plant replacement.
- plantSapling(preferredSapling)
- print("Tree harvested.")
- return
- end
- print("Not a tree or sapling: " .. block.name)
- end
- -- ------------------------------------------------------------
- -- DROP HARVEST INTO CHEST
- -- ------------------------------------------------------------
- local function dumpHarvest()
- goHome()
- print("Dropping harvest into chest...")
- for slot = 1, 16 do
- local item = turtle.getItemDetail(slot)
- if item then
- local keep =
- isBoneMealName(item.name) or
- isSaplingName(item.name) or
- isFuelName(item.name)
- if not keep then
- turtle.select(slot)
- if not turtle.dropDown() then
- print("Chest may be full!")
- end
- end
- end
- end
- end
- -- ------------------------------------------------------------
- -- VISIT ONE TREE
- -- ------------------------------------------------------------
- local function visitTree(tree)
- refuel()
- -- Stand one block north of the tree.
- local approachX = tree.x
- local approachZ = tree.z - 1
- moveTo(approachX, approachZ)
- -- Face south, toward the tree.
- face(0)
- print("")
- print("---------------------------")
- print("Tree " .. tree.x .. ", " .. tree.z)
- print("---------------------------")
- processTree()
- -- Deposit after EACH tree.
- dumpHarvest()
- end
- -- ------------------------------------------------------------
- -- MAIN PROGRAM
- -- ------------------------------------------------------------
- print("")
- print("================================")
- print(" Six Tree Automatic Tree Farm")
- print("================================")
- print("")
- print("Home: " .. HOME_X .. ", " .. HOME_Z)
- print("Trees: " .. #trees)
- print("")
- refuel()
- while true do
- print("")
- print("Beginning farm sweep...")
- for i, tree in ipairs(trees) do
- print("")
- print("Tree " .. i .. " of " .. #trees)
- visitTree(tree)
- end
- goHome()
- dumpHarvest()
- print("")
- print("Sweep complete.")
- print("Sleeping " .. CHECK_INTERVAL .. " seconds.")
- sleep(CHECK_INTERVAL)
- end
Advertisement