local MINFUELLEVEL = 4000 local tunnelLength = 0 local torches = false local garbage = { ["minecraft:cobblestone"] = true, ["minecraft:dirt"] = true, ["minecraft:gravel"] = true, ["minecraft:stone"] = true, ["minecraft:sand"] = true } local args = {...} local sides = {"left", "right"} local equipment = {left = nil, right = nil} local tools = {["minecraft:compass"] = true, ["plethora:module"] = true, ["minecraft:diamond_pickaxe"] = true} local inventory = {} -- {itemName = {slot1, slot2, slot3}} local pos = vector.new(0, 0, 0) local heading = vector.new(1, 0, 0) local directions = {NORTH = vector.new(0, 0, -1), EAST = vector.new(1, 0, 0), SOUTH = vector.new(0, 0, 1), WEST = vector.new(-1, 0, 0)} local orientations = {[vector.new(0, 0, -1):tostring()] = 0, [vector.new(1, 0, 0):tostring()] = 1, [vector.new(0, 0, 1):tostring()] = 2, [vector.new(-1, 0, 0):tostring()] = 3} local home = vector.new(0, 0, 0) local startingHeading -- init function init() if args then if args[1] then tunnelLength = args[1] end if args[2] then torches = args[2] end end heading = getFacing() startingHeading = heading print(heading) for _, side in pairs(sides) do local tool = peripheral.getType(side) if tool then equipment[side] = tool end end for side, tool in pairs(equipment) do print(side .. ": " .. tool) end scanInventory() end -- inventory functions function scanInventory() inventory = {} for i = 1, 16 do local data = turtle.getItemDetail(i) if data then if inventory[data.name] then table.insert(inventory[data.name], i) else inventory[data.name] = {i} end end end end function selectItem(itemName) scanInventory() if not inventory[itemName] then return false end turtle.select(inventory[itemName][1]) return true end function equipItem(itemName, side) side = side or "right" scanInventory() if not inventory[itemName] then return false end turtle.select(inventory[itemName][1]) if side == "right" then turtle.equipRight() else turtle.equipLeft() end end function purgeInv() for i = 1, 16 do local data = turtle.getItemDetail(i) if data then if garbage[data.name] then turtle.select(i) turtle.dropUp() end for b = 1, i-1 do local d = turtle.getItemDetail(b) if d then if d.name == data.name then turtle.select(i) turtle.transferTo(b) end end end end end end function refuel() scanInventory() if inventory["minecraft:coal"] then turtle.select(inventory["minecraft:coal"][1]) turtle.refuel() end end function emptyInventory() purgeInv() for i = 1, 16 do local data = turtle.getItemDetail(i) if data then if not tools[data.name] then turtle.select(i) turtle.drop() end end end end function getEmptySpace() local emptySpace = 0 for i = 1, 16 do local count = turtle.getItemCount(i) if count == 0 then emptySpace = emptySpace + 1 end end return emptySpace end -- navigation function getFacing() equipItem("minecraft:compass") local facing = peripheral.call("right", "getFacing") return directions[string.upper(facing)] end function compareVectors(vec1, vec2) if vec1.x == vec2.x and vec1.y == vec2.y and vec1.z == vec2.z then return true else return false end end function turnRight() turtle.turnRight() if compareVectors(heading, vector.new(1, 0, 0)) then heading = vector.new(0, 0, 1) elseif compareVectors(heading, vector.new(-1, 0, 0)) then heading = vector.new(0, 0, -1) elseif compareVectors(heading, vector.new(0, 0, 1)) then heading = vector.new(-1, 0, 0) elseif compareVectors(heading, vector.new(0, 0, -1)) then heading = vector.new(1, 0, 0) end return true end function turnLeft() turtle.turnLeft() if compareVectors(heading, vector.new(1, 0, 0)) then heading = vector.new(0, 0, -1) elseif compareVectors(heading, vector.new(-1, 0, 0)) then heading = vector.new(0, 0, 1) elseif compareVectors(heading, vector.new(0, 0, 1)) then heading = vector.new(1, 0, 0) elseif compareVectors(heading, vector.new(0, 0, -1)) then heading = vector.new(-1, 0, 0) end return true end function forward() local tries = 0 repeat if tries > 50 then return false end tries = tries + 1 turtle.dig() until turtle.forward() pos = pos + heading return true end function back() if not turtle.back() then turnRight() turnRight() forward() turnLeft() turnLeft() else pos = pos - heading end return true end function up() repeat turtle.digUp() until turtle.up() pos = pos + vector.new(0, 1, 0) return true end function down() local tries = 0 repeat if tries > 50 then return false end tries = tries + 1 turtle.digDown() until turtle.down() pos = pos + vector.new(0, -1, 0) return true end function turnToHeading(newHeading) if compareVectors(newHeading, heading) then return true end if compareVectors(newHeading, -heading) then turnRight() turnRight() return true end if orientations[newHeading:tostring()] == 0 and orientations[heading:tostring()] == 3 then turnRight() return true end if orientations[newHeading:tostring()] == 3 and orientations[heading:tostring()] == 0 then turnLeft() return true end if orientations[newHeading:tostring()] > orientations[heading:tostring()] then turnRight() else turnLeft() end end function goto(newPos) if newPos.x > pos.x then turnToHeading(vector.new(1, 0, 0)) while newPos.x > pos.x do if not forward() then return false end end end if newPos.x < pos.x then turnToHeading(vector.new(-1, 0, 0)) while newPos.x < pos.x do if not forward() then return false end end end if newPos.z > pos.z then turnToHeading(vector.new(0, 0, 1)) while newPos.z > pos.z do if not forward() then return false end end end if newPos.z < pos.z then turnToHeading(vector.new(0, 0, -1)) while newPos.z < pos.z do if not forward() then return false end end end while newPos.y > pos.y do up() end while newPos.y < pos.y do if not down() then return false end end end -- mining functions function isOreBlock(name) if string.find(name, "ore") and string.find(name, "minecraft") then return true end if string.find(name, "ore") and string.find(name, "thermal") then return true end return false end function scanArea() if equipment.right ~= "plethora:scanner" then equipItem("plethora:module") end local data = peripheral.call("right", "scan") local ores = {} for _, block in pairs(data) do if isOreBlock(block.name) then block.x = block.x + pos.x block.y = block.y + pos.y block.z = block.z + pos.z table.insert(ores, block) end end return ores end function getDistance(pos1, pos2) local x = math.abs(pos1.x - pos2.x) local y = math.abs(pos1.y - pos2.y) local z = math.abs(pos1.z - pos2.z) return (x + y + z) end function createMiningPath(ores) local unassignedOres = ores local assignedOres = {} local lowestScore = 999 local lowestIndex = 1 for i = 1, #unassignedOres do local dis = getDistance(unassignedOres[i], pos) if dis < lowestScore then lowestIndex = i lowestScore = dis end end table.insert(assignedOres, unassignedOres[lowestIndex]) table.remove(unassignedOres, lowestIndex) while #unassignedOres > 0 do local lowestScore = 999 local lowestIndex = 1 for i = 1, #unassignedOres do local dis = getDistance(unassignedOres[i], assignedOres[#assignedOres]) if dis < lowestScore then lowestIndex = i lowestScore = dis end end table.insert(assignedOres, unassignedOres[lowestIndex]) table.remove(unassignedOres, lowestIndex) end print(#assignedOres) return assignedOres end function scanAndMine() local ores = scanArea() equipItem("minecraft:diamond_pickaxe") local path = createMiningPath(ores) print(#path) for i = 1, #path do if i % 5 == 0 then purgeInv() if getEmptySpace() < 3 then dumpItems() end end goto(vector.new(path[i].x, path[i].y, path[i].z)) end end function dumpItems() local thisPos = pos local thisHeading = heading goto(home) turnToHeading(-startingHeading) emptyInventory() goto(thisPos) turnToHeading(thisHeading) end function main() equipItem("minecraft:diamond_pickaxe") for i = 1, 5 do turtle.digUp() forward() end for i = 1, tunnelLength/8 do equipItem("minecraft:diamond_pickaxe") for b = 1, 8 do turtle.digUp() forward() end local curPos = pos local curHeading = heading scanAndMine() goto(curPos) turnToHeading(curHeading) purgeInv() if turtle.getFuelLevel() < MINFUELLEVEL then refuel() end end goto(home) turnToHeading(-startingHeading) emptyInventory() end init() main()