local STATIC_CONFIG = require('config/tunnels') local turtleUtils = require('libs/turtle-utils') local IDLE_TIME = 3 local TIME_TO_START = 3 local IDLE_TIME_BETWEEN_TUNNELS = 1 local SPACE_BETWEEN_TUNNELS = 3 local VERSION = "2.1.1" local MOVES_BY_DIRECTION = { right = { turnLeft = turtle.turnLeft, turnRight = turtle.turnRight }, left = { -- this is inversed turnLeft = turtle.turnRight, turnRight = turtle.turnLeft } } local function noop() end local function getMoves(config) return MOVES_BY_DIRECTION[config.DIRECTION] end local function getMinFuelNeeded(config) local fuelMultiplier = 2 local fuelMargin = config.FUEL_MARGIN if config.VEIN_MODE then fuelMultiplier = 4 fuelMargin = fuelMargin + config.FUEL_MARGIN_VEIN_MODE end return (config.DISTANCE_Z * fuelMultiplier) + SPACE_BETWEEN_TUNNELS + fuelMargin end local function checkEnoughFuelForTunnel(config) local minFuelNeeded = getMinFuelNeeded(config) if turtle.getFuelLevel() < minFuelNeeded then turtleUtils.refuelAllFromInventory() return turtle.getFuelLevel() < minFuelNeeded end return true end local function assertEnoughFuelForTunnel(config) if not checkEnoughFuelForTunnel(config) then error('not enough fuel', 0) end end local function assertValidConfig(config) if config.DIRECTION ~= 'left' and config.DIRECTION ~= 'right' then error('config.DIRECTION should be "left" or "right"', 0) end if config.DISTANCE_Z <= 0 then error('config.DISTANCE_Z should be a positive number', 0) end local minFuelMargin = 6 if config.FUEL_MARGIN < minFuelMargin then error('config.FUEL_MARGIN cannot be lower than ' .. minFuelMargin) end end local function assertInventoryIsEmpty() if not turtleUtils.isInventoryEmpty() then error('turtle inventory should be empty', 0) end end local function printFuelReport(config) print('> current fuel: ' .. turtleUtils.getFuelPercentage() .. '%') print('> fuel needed: ' .. turtleUtils.getFuelPercentage(getMinFuelNeeded(config)) .. '%') end local function findGroundProcedure() local foundGround, errMessage = turtleUtils.goGround() if not foundGround then error('cannot find the ground because ' .. tostring(errMessage), 0) end end local function digForward(n, cb) n = n or 1 cb = cb or noop for i=1, n, 1 do turtleUtils.forceForward() turtle.digDown() cb(i) end end local function isWhitelistedOre(config, itemOrBlock) local itemOrBlockName = itemOrBlock and itemOrBlock.name if config.VEIN_ORES_WHITELIST[itemOrBlockName] then return true end if config.VEIN_ORES_WHITELIST_ITEMS[itemOrBlockName] then return true end return false end local function inspectWhitelistedOre(config, inspectFn) local _, block = inspectFn() return isWhitelistedOre(config, block) end local function trySelectEmptySlot() if turtle.getItemDetail() then turtleUtils.selectItemBy(function(slot) return not not turtle.getItemDetail(slot) end) end end local function ensureEnoughSpaceInInventory(config) if not turtleUtils.isInventoryFull() then return end -- 1. select an item that is not in whitelist item local selected = turtleUtils.selectItemBy(function(slot) return not isWhitelistedOre(config, turtle.getItemDetail(slot)) end) if selected then -- 2. drop the selected item turtle.drop() trySelectEmptySlot() else -- TODO: handle when cannot drop anything (monitoring over network ?) end end local function mineVeinOres(config) ensureEnoughSpaceInInventory(config) -- 1. front if inspectWhitelistedOre(config, turtle.inspect) then turtleUtils.forceForward() mineVeinOres(config) turtle.back() end -- 2. up if inspectWhitelistedOre(config, turtle.inspectUp) then turtleUtils.forceUp() mineVeinOres(config) turtle.down() end -- 3. down if inspectWhitelistedOre(config, turtle.inspectDown) then turtleUtils.forceDown() mineVeinOres(config) turtle.up() end -- 4. check left turtle.turnLeft() if inspectWhitelistedOre(config, turtle.inspect) then turtleUtils.forceForward() mineVeinOres(config) turtle.back() end turtle.turnRight() -- 5. right turtle.turnRight() if inspectWhitelistedOre(config, turtle.inspect) then turtleUtils.forceForward() mineVeinOres(config) turtle.back() end turtle.turnLeft() end local function mineVeinProcedure(config) if not config.VEIN_MODE then return end mineVeinOres(config) turtleUtils.forceDown() mineVeinOres(config) turtleUtils.forceUp() end local function mineTunnelProcedure(config) local distance = config.DISTANCE_Z local onMineCb = function() ensureEnoughSpaceInInventory() mineVeinProcedure(config) end digForward(distance, onMineCb) getMoves(config).turnRight() digForward(SPACE_BETWEEN_TUNNELS, onMineCb) getMoves(config).turnRight() digForward(distance, onMineCb) end local function dropAllProcedure(config) turtleUtils.forceDown() getMoves(config).turnRight() -- try to refuel before dropping items turtleUtils.refuel(getMinFuelNeeded(config), turtle.suck, IDLE_TIME) turtleUtils.refuelAllFromInventory() -- drop all items for i=1, 16, 1 do local count = turtle.getItemCount(i) if count > 0 then turtleUtils.waitForInventory('front', IDLE_TIME) while turtle.getItemCount(i) and not turtleUtils.dropSlot(i, turtle.drop) do os.sleep(IDLE_TIME) end end end getMoves(config).turnLeft() -- turtleUtils.forceUp() end local function goToNextMineProcedure(config) getMoves(config).turnLeft() for _=1, SPACE_BETWEEN_TUNNELS, 1 do turtleUtils.forceForward() end getMoves(config).turnLeft() turtleUtils.forceUp() end local function main(config) assertValidConfig(config) turtleUtils.refuelAllFromInventory() assertInventoryIsEmpty() -- Warning here when implementing persistance printFuelReport(config) assertEnoughFuelForTunnel(config) findGroundProcedure() turtleUtils.forceUp() assertEnoughFuelForTunnel(config) print('> Starting tunnels-miner v' .. VERSION .. ' in ' .. TIME_TO_START .. ' seconds...') os.sleep(TIME_TO_START) local tunnelNumber = 1 while true do if tunnelNumber > 1 then printFuelReport(config) assertEnoughFuelForTunnel(config) end print('> Start mining tunnel number ' .. tostring(tunnelNumber)) mineTunnelProcedure(config) dropAllProcedure(config) goToNextMineProcedure(config) os.sleep(IDLE_TIME_BETWEEN_TUNNELS) tunnelNumber = tunnelNumber + 1 end end main(STATIC_CONFIG)