feat(inferium-harvester)!: add replant procedure
This commit is contained in:
parent
51e93081a1
commit
0b724c7334
@ -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()
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user