feat(inferium-harvester)!: add replant procedure

This commit is contained in:
Guillaume ARM 2024-05-20 19:03:34 +02:00
parent 51e93081a1
commit 0b724c7334
2 changed files with 276 additions and 10 deletions

View File

@ -1,13 +1,88 @@
local turtleUtils = require('libs/turtle-utils') local turtleUtils = require('libs/turtle-utils')
local config = require('config/harvesting') local config = require('config/harvesting')
local VERSION = "0.4.2" local VERSION = "0.5.0
local IDLE_TIME = 2 local IDLE_TIME = 2
local MIN_FUEL_NEEDED = (10 + config.firstCropZ + config.length) * 2 local WAIT_ITEM_IDLE_TIME = 5
local MIN_FUEL_NEEDED = (100 + config.firstCropZ + config.length) * 2
local MIN_FREE_SLOTS_BEFORE_COMPACT = 4 local MIN_FREE_SLOTS_BEFORE_COMPACT = 4
local function mystical(essenceName)
return 'mysticalagriculture:' .. essenceName .. '_seeds'
end
local fakeRemotePlan = {
mystical('coal'),
mystical('diamond'),
mystical('quartz'),
mystical('dye'),
mystical('inferium'),
mystical('inferium'),
mystical('inferium'),
mystical('inferium')
}
-- a table with the list of current crops
local localPlan = nil
-- UTILS -- UTILS
local function difference(a, b)
local aa = {}
for k,v in pairs(a) do aa[v]=true end
for k,v in pairs(b) do aa[v]=nil end
local ret = {}
local n = 0
for k,v in pairs(a) do
if aa[v] then n=n+1 ret[n]=v end
end
return ret
end
local function shallowClone(t)
local res = {}
for k,v in pairs(t) do
res[k] = v
end
return res
end
local function removeFirst(t, x)
local res = {}
local removed = false
for k,v in pairs(t) do
if not removed and x == v then
removed = true
else
table.insert(res, v)
end
end
end
local function find(t, predicate) do
for k,v in pairs(t) do
if predicate(v, k) then
return v, k
end
end
end
local function getIndexedCount(t)
local res = {}
for k,v in pairs(t) do
local count = res[v] or 0
res[v] = count + 1
end
return res
end
local function assertEnoughFuel() local function assertEnoughFuel()
if turtle.getFuelLevel() < MIN_FUEL_NEEDED then if turtle.getFuelLevel() < MIN_FUEL_NEEDED then
error('Not enough fuel') error('Not enough fuel')
@ -32,9 +107,35 @@ local function retrieveChestFuelOrientation()
end end
local function getSeedNameFromCropName(cropName) local function getSeedNameFromCropName(cropName)
if not cropName then
return cropName
end
return string.gsub(cropName, 'crop', 'seeds') return string.gsub(cropName, 'crop', 'seeds')
end end
function isSeed(item)
local tags = item.tags or {}
return tags['forge:seeds'] or tags['mysticalagriculture:seeds'] or false
end
-- Inventory utils
-- the slot of the item is returned
local function waitForItem(inventory, itemName, count, sleepTime)
sleepTime = sleepTime or 5 -- TODO: DEFAULT_IDLE_TIME
while true do
for slot, item in pairs(inventory.list()) do
if item.name == itemName and item.count >= count then
return slot
end
end
os.sleep(IDLE_TIME)
end
end
-- Implementations -- Implementations
local function retrieveHomePositionProcedure() local function retrieveHomePositionProcedure()
if turtleUtils.getInventory('bottom') then if turtleUtils.getInventory('bottom') then
@ -65,7 +166,7 @@ local function retrieveHomePositionProcedure()
while true do while true do
if turtleUtils.getInventory('bottom') then if turtleUtils.getInventory('bottom') then
return break
end end
if turtle.inspect() then if turtle.inspect() then
@ -74,6 +175,8 @@ local function retrieveHomePositionProcedure()
turtle.forward() turtle.forward()
end end
end end
turtle.turnLeft()
end end
local function dropAllProcedure() local function dropAllProcedure()
@ -91,18 +194,16 @@ local function dropAllProcedure()
end end
local function refuelProcedure() local function refuelProcedure()
turtle.turnLeft()
local refuelOk, refuelErr = turtleUtils.refuelWithBuffer('bottom', 'front', MIN_FUEL_NEEDED, IDLE_TIME) local refuelOk, refuelErr = turtleUtils.refuelWithBuffer('bottom', 'front', MIN_FUEL_NEEDED, IDLE_TIME)
if not refuelOk then if not refuelOk then
error('Cannot refuel the turtle: "' .. refuelErr .. '"') error('Cannot refuel the turtle: "' .. refuelErr .. '"')
end end
turtle.turnLeft()
end end
local function goToHarvestPoint() local function goToHarvestPoint()
turtle.turnLeft()
for i=1, config.firstCropZ, 1 do for i=1, config.firstCropZ, 1 do
turtle.forward() turtle.forward()
end end
@ -112,6 +213,14 @@ local function goBackToHome()
for i=1, config.firstCropZ, 1 do for i=1, config.firstCropZ, 1 do
turtle.forward() turtle.forward()
end end
turtle.turnLeft()
end
local function compactIfNeeded()
if turtleUtils.countFreeSlots() < MIN_FREE_SLOTS_BEFORE_COMPACT then
turtleUtils.compactInventory()
end
end end
local function harvestDown() local function harvestDown()
@ -130,11 +239,10 @@ local function harvestDown()
error('turtle cannot place crop') error('turtle cannot place crop')
end end
if turtleUtils.countFreeSlots() < MIN_FREE_SLOTS_BEFORE_COMPACT then compactIfNeeded()
turtleUtils.compactInventory()
end
end end
local function forward() local function forward()
if not turtle.forward() then if not turtle.forward() then
error('turtle is blocked') error('turtle is blocked')
@ -164,6 +272,151 @@ local function harvestProcedure()
end end
end end
local function retrieveLocalPlan()
goToHarvestPoint()
localPlan = {}
for i=1, config.length, 1 do
local ok, block = turtle.inspectDown()
local blockName = block and block.name
localPlan[i] = getSeedNameFromCropName(blockName)
if i ~= config.length then
forward()
end
end
turtle.turnLeft()
turtle.turnLeft()
for i=1, config.length, 1 do
if i ~= config.length then
forward()
end
end
goBackToHome()
end
local function fetchRemotePlan()
-- TODO
return fakeRemotePlan
end
local function removeSeeds(seeds)
goToHarvestPoint()
local stateSeeds = seeds
for i=1, config.length, 1 do
local ok, block = turtle.inspectDown()
local blockName = block and block.name
local found = find(stateSeeds, function(seedName) return seedName == getSeedNameFromCropName(blockName) end)
if found then
local digOk = turtle.digDown()
compactIfNeeded()
if not digOk then
error('cannot remove seed')
end
stateSeeds = removeFirst(stateSeeds, found)
end
if i ~= config.length then
forward()
end
end
turtle.turnLeft()
turtle.turnLeft()
for i=1, config.length, 1 do
if i ~= config.length then
forward()
end
end
goBackToHome()
dropAllProcedure()
end
local function retrieveSeeds(seeds)
local seedsCount = getIndexedCount(seeds)
local storageInventory = turtleUtils.waitForInventory('bottom', WAIT_ITEM_IDLE_TIME)
local bufferInventory = turtleUtils.waitForInventory('front', WAIT_ITEM_IDLE_TIME)
for seedName, count in pairs(seedsCount) do
local slot = waitForItem(storageInventory, seedName, count, WAIT_ITEM_IDLE_TIME)
local pushOk = storageInventory.pushItems(peripheral.getName(bufferInventory), slot, count)
if not pushOk then
error('retrieveSeeds error: cannot pushItems from storage to buffer')
end
local suckOk = turtle.suck()
if not suckOk then
error('retrieveSeeds error: cannot suck items from buffer')
end
end
end
local function replantSeeds()
goToHarvestPoint()
for i=1, config.length, 1 do
local ok, block = turtle.inspectDown()
if not ok then
turtleUtils.selectItemBy(function(slot)
local item = turtle.getItemDetail(slot, true)
return isSeed(item)
end)
turtle.placeDown()
end
if i ~= config.length then
forward()
end
end
turtle.turnLeft()
turtle.turnLeft()
for i=1, config.length, 1 do
if i ~= config.length then
forward()
end
end
goBackToHome()
end
local function replantProcedure()
if localPlan == nil then
retrieveLocalPlan()
end
local remotePlan = fetchRemotePlan()
if remotePlan == nil then
error('cannot fetch the remote plan')
end
local seedsToRemove = difference(localPlan, remotePlan)
local seedsToPlant = difference(remotePlan, localPlan)
removeSeeds(seedsToRemove)
retrieveSeeds(seedsToPlant)
replantSeeds()
end
-- Main procedure -- Main procedure
local function main() local function main()
print("Starting Trap's inferium harvester v" .. VERSION) print("Starting Trap's inferium harvester v" .. VERSION)
@ -180,6 +433,8 @@ local function main()
dropAllProcedure() dropAllProcedure()
refuelProcedure() refuelProcedure()
replantProcedure()
goToHarvestPoint() goToHarvestPoint()
harvestProcedure() harvestProcedure()
goBackToHome() goBackToHome()

View File

@ -181,6 +181,17 @@ turtleUtils.selectItemByName = function(itemName)
return false return false
end end
turtleUtils.selectItemBy = function(predicate)
for i = 1, 16, 1 do
if predicate(i) then
turtle.select(i)
return true
end
end
return false
end
turtleUtils.refuel = function(minFuel, suckFn, sleepTime) turtleUtils.refuel = function(minFuel, suckFn, sleepTime)
suckFn = suckFn or turtle.suck suckFn = suckFn or turtle.suck
sleepTime = sleepTime or DEFAULT_IDLE_TIME sleepTime = sleepTime or DEFAULT_IDLE_TIME