minecraft-cc-tools/libs/turtle-utils.lua
2024-05-19 19:37:16 +02:00

271 lines
5.2 KiB
Lua

local turtleUtils = {}
local DEFAULT_IDLE_TIME = 2
turtleUtils.getInventory = function(side)
side = side or 'front'
local inv = peripheral.wrap(side)
if inv and peripheral.hasType(inv, 'inventory') then
return inv
end
return nil
end
turtleUtils.getItemName = function(slotIndex)
local item = turtle.getItemDetail(i)
return item and item.name
end
turtleUtils.getItemCount = function(slotIndex)
return turtle.getItemCount(slotIndex)
end
local 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.waitForMatureCrop = function(inspectFn, sleepTime)
inspectFn = inspectFn or turtle.inspect
return waitFor(function()
return turtleUtils.getMatureCrop(inspectFn)
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()
return turtleUtils.trySuck(turtle.suckUp)
end
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 = dropFn();
if (dropOk) then
return true
end
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
turtleUtils.countFreeSlots = function()
local freeSlots = 0
for i=1, 16, 1 do
if turtle.getItemCount(i) == 0 then
freeSlots = freeSlots + 1
end
end
return freeSlots
end
turtleUtils.getFuelPercentage = function()
return (turtle.getFuelLevel() / turtle.getFuelLimit()) * 100
end
turtleUtils.getMatureCrop = function(inspectFn)
inspectFn = inspectFn or turtle.inspect
local isBlock, block = inspectFn()
local blockStateAge = block and block.state and block.state.age
if blockStateAge == 7 then
return block.name
end
return nil
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
if itemName == turtleUtils.getItemName(i) then
turtle.select(i)
return true
end
end
return false
end
turtleUtils.refuel = function(minFuel, suckFn, sleepTime)
suckFn = suckFn or turtle.suck
sleepTime = sleepTime or DEFAULT_IDLE_TIME
if not turtleUtils.selectFirstEmptySlot() then
return false, 'turtle inventory is full'
end
while turtle.getFuelLevel() < minFuel do
local suckRes = suckFn()
if suckRes then
local ok = turtle.refuel()
if not ok then
return false, 'selected item is not considered as fuel'
end
else
os.sleep(sleepTime)
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
-- utils function used by "compactInventory"
local function getItemsMap()
local result = {}
for i=1, 16, 1 do
local itemName = turtleUtils.getItemName(i)
if itemName then
local nbSlotUsed = result[itemName] or 0
result[itemName] = nbSlotUsed + 1
end
end
return result
end
local function getSlotsWithSpaces(itemName)
local slots = {}
for i=1, 16, 1 do
if turtleUtils.getItemName(i) == itemName then
if turtle.getItemSpace(i) > 0 then
table.insert(slots, i)
end
end
end
return slots
end
local function compactItem(itemName)
while true do
local slots = getSlotsWithSpaces(itemName)
if #slots < 2 then
break
end
turtle.select(slots[1])
turtle.transferTo(slots[2], turtle.getItemSpace(slots[2]))
end
end
-- Compact the internal turtle inventory
turtleUtils.compactInventory = function()
local initialSelectedSlot = turtle.getSelectedSlot()
local itemsMap = getItemsMap()
for itemName, nbSlotUsed in pairs(itemsMap) do
if nbSlotUsed > 1 then
compactItem(itemName)
end
end
if initialSelectedSlot ~= turtle.getSelectedSlot() then
turtle.select(initialSelectedSlot)
end
end
return turtleUtils