From f811031db5f9cf3eefec4b59ea8c8369f5fce0e4 Mon Sep 17 00:00:00 2001 From: Guillaume ARM Date: Sun, 19 May 2024 16:34:28 +0200 Subject: [PATCH] feat: first version of inferium harvester --- inferium-harvester.lua | 174 +++++++++++++++++++++++++++++++++++++++++ install.lua | 3 +- libs/turtle-utils.lua | 162 +++++++++++++++++++++++++++++++++----- 3 files changed, 320 insertions(+), 19 deletions(-) create mode 100644 inferium-harvester.lua diff --git a/inferium-harvester.lua b/inferium-harvester.lua new file mode 100644 index 0000000..abb6c28 --- /dev/null +++ b/inferium-harvester.lua @@ -0,0 +1,174 @@ +local config = { + length = 8 + firstCropZ = 2 +} + +local MIN_FUEL_NEEDED = (10 + config.firstCropZ + config.length) * 2 + +local VERSION = "0.1.0" +local IDLE_TIME = 2 + +local turtleUtils = require('libs/turtle-utils') + +-- UTILS +local function waitForMatureCrop() + return turtleUtils.waitFor(function() + return turtleUtils.isMatureCrop(turtle.inspectDown) + end, IDLE_TIME) +end + +local function assertEnoughFuel() + if turtle.getFuelLevel() < MIN_FUEL_NEEDED then + error('Not enough fuel') + end +end + +local function retrieveChestFuelOrientation() + local inventoryFound = false + + for i=1, 4, 1 do + if turtleUtils.getInventory('front') then + inventoryFound = true + break + end + + turtle.turnRight() + end + + if not inventoryFound then + error('chest fuel not found') + end +end + +-- Implementations +local function retrieveHomePositionProcedure() + if turtleUtils.getInventory('bottom') then + retrieveChestFuelOrientation() + turtle.turnLeft() + end + + turtle.turnRight() + + if turtle.inspect() then + turtle.turnRight() + end + + while true do + if turtleUtils.getInventory('bottom') then + return + end + + if turtle.inspect() then + break + else + turtle.forward() + end + end + + turtle.turnLeft() + turtle.turnLeft() + + while true do + if turtleUtils.getInventory('bottom') then + return + end + + if turtle.inspect() then + error('Cannot retrieve home position') + else + turtle.forward() + end + end +end + +local function dropAllProcedure() + for i=1, 16, 1 do + local count = turtle.getItemCount(i) + + if count > 0 then + while not turtleUtils.dropSlot(i, turtle.dropDown) do + os.sleep(IDLE_TIME) + end + end + end +end + +local function refuelProcedure() + turtle.turnLeft() + turtleUtils.waitForInventory('front') + turtleUtils.refuel(MIN_FUEL_NEEDED, turtle.suck) + turtle.turnLeft() +end + +local function goToHarvestPoint() + for i=1, config.firstCropZ, 1 do + turtle.forward() + end +end + +local function goBackToHome() + for i=1, config.firstCropZ - 1, 1 do + turtle.forward() + end +end + +local function harvestDown() + local cropName = waitForMatureCrop() + + if not turtle.digDown() then + error('turtle cannot harvest crop') + end + + if not turtleUtils.selectItemByName(cropName) then + error('turtle cannot find any crop to place') + end + + if not turtleUtils.placeDown() then + error('turtle cannot place crop') + end +end + +local function forward() + if not turtle.forward() then + error('turtle is blocked') + end +end + +local function harvestProcedure() + for i=1, config.length, 1 do + harvestDown() + forward() + end + + turtle.turnLeft() + turtle.turnLeft() + + for i=1, config.length, 1 do + harvestDown() + forward() + end +end + +-- Main procedure +local function main() + print("Starting Trap's inferium harvester v" .. VERSION) + + turtleUtils.refuelAllFromInventory() + assertEnoughFuel() + + print("> retrieving home position") + retrieveHomePositionProcedure() + + print("> start the harvesting process") + + while true do + dropAllProcedure() + refuelProcedure() + + goToHarvestPoint() + harvestProcedure() + goBackToHome() + end +end + +main() diff --git a/install.lua b/install.lua index 18d102b..5a8871b 100644 --- a/install.lua +++ b/install.lua @@ -1,7 +1,8 @@ local LIST_FILES = { 'miner.lua', 'old/simple-harvester.lua', - 'inferium-upgrader.lua' + 'inferium-upgrader.lua', + 'inferium-harvester.lua' }; local LIST_LIBS_FILES = { diff --git a/libs/turtle-utils.lua b/libs/turtle-utils.lua index a5b8e90..5284d10 100644 --- a/libs/turtle-utils.lua +++ b/libs/turtle-utils.lua @@ -1,45 +1,102 @@ local turtleUtils = {} -local IDLE_TIME = 2 +local DEFAULT_IDLE_TIME = 2 -turtleUtils.waitForInventory = function(side) - local inv = nil +turtleUtils.getInventory = function(side) + side = side or 'front' + local inv = peripheral.wrap(side) - while true do - inv = peripheral.wrap(side) - - if inv and peripheral.hasType(inv, 'inventory') then - break - end - - os.sleep(IDLE_TIME) + if peripheral.hasType(inv, 'inventory') then + return inv end - return inv + return nil +end + +function waitFor(predicate, sleepTime) + sleepTime = sleepTime or DEFAULT_IDLE_TIME + + while true do + local result = predicate() + + if result ~= nil and result ~= false then + return result + end + + os.sleep(sleepTime) + end +end + +turtleUtils.waitForInventory = function(side, sleepTime) + return waitFor(function() + return turtleUtils.getInventory(side) + end, sleepTime) +end + +turtleUtils.trySuck = function(suckFn, sleepTime) + suckFn = suckFn or turtle.suck + sleepTime = sleepTime or DEFAULT_IDLE_TIME + + while not suckFn() do + os.sleep(sleepTime) + end end turtleUtils.trySuckUp = function() - while not turtle.suckUp() do - os.sleep(IDLE_TIME) - end + return turtleUtils.trySuck(turtle.suckUp) end -turtleUtils.tryDrop = function() +turtleUtils.trySuckDown = function() + return turtleUtils.trySuck(turtle.suckDown) +end + +turtleUtils.tryDrop = function(dropFn, sleepTime) + dropFn = dropFn or turtle.drop + sleepTime = sleepTime or DEFAULT_IDLE_TIME + while true do if turtle.getItemCount() == 0 then return false end - local dropOk = turtle.drop(); + local dropOk = dropFn(); if (dropOk) then return true end - os.sleep(IDLE_TIME) + os.sleep(sleepTime) end end +turtleUtils.tryDropUp = function() + return turtleUtils.tryDrop(turtle.dropUp) +end + +turtleUtils.tryDropDown = function() + return turtleUtils.tryDrop(turtle.dropDown) +end + +turtleUtils.dropSlot = function(slotIndex, dropFn) + dropFn = dropFn or turtle.drop + + if turtle.getItemCount(slotIndex) == 0 then + return false + end + + if turtle.getSelectedSlot() ~= slotIndex then + turtle.select(slotIndex) + end + + local ok, err = dropFn() + + if not ok then + return false + end + + return true +end + turtleUtils.digAll = function() while turtle.dig() do end end @@ -60,4 +117,73 @@ turtleUtils.getFuelPercentage = function() return (turtle.getFuelLevel() / turtle.getFuelLimit()) * 100 end +turtleUtils.isMatureCrop = function(inspectFn) + inspectFn = inspectFn or turtle.inspect + + return function() + local isBlock, block = inspectFn() + local blockStateAge = block and block.state and block.state.age + return blockStateAge == 7 + end +end + +turtleUtils.selectFirstEmptySlot = function() + for i = 1, 16, 1 do + if turtle.getItemCount(i) == 0 then + turtle.select(i) + return true + end + end + + return false +end + +turtleUtils.selectItemByName = function(itemName) + for i = 1, 16, 1 do + local item = turtle.getItemDetail(i) + + if item and item.name == itemName then + turtle.select(i) + return true + end + end + + return false +end + +turtleUtils.refuel = function(minFuel, suckFn) + suckFn = suckFn or turtle.suck + + if not turtleUtils.selectFirstEmptySlot() then + return false + end + + while turtle.getFuelLevel() < minFuel do + suckFn() + + local ok = turtle.refuel() + + if not ok then + return false + end + end + + return true +end + +turtleUtils.refuelAllFromInventory = function() + local initialSelectedSlot = turtle.getSelectedSlot() + + for i=1, 16, 1 do + if turtle.getItemCount(i) > 0 then + turtle.select(i) + turtle.refuel() + end + end + + if turtle.getSelectedSlot() ~= initialSelectedSlot then + turtle.select(initialSelectedSlot) + end +end + return turtleUtils \ No newline at end of file