local turtleUtils = {} local DEFAULT_IDLE_TIME = 2 local DEFAULT_MIN_FUEL_NEEDED = 1000 local function isTurtleInventoryFull() for i=1, 16, 1 do if turtle.getItemCount(i) == 0 then return false end end return true end turtleUtils.isFuelItem = function(item) item = item or {} if item.name == 'minecraft:stick' or item.name == 'minecraft:coal_coke_block' or item.name == 'immersiveengineering:coke' or item.name == 'silentgear:netherwood_charcoal' or item.name == 'silentgear:netherwood_charcoal_block' then return true end local tags = item.tags or {} return tags['minecraft:coals'] or tags['minecraft:logs'] or tags['minecraft:planks'] or tags['minecraft:saplings'] or false end turtleUtils.isSeedInSlot = function(slot) local item = turtle.getItemDetail(slot, true) local tags = item and item.tags or {} return tags['forge:seeds'] or tags['mysticalagriculture:seeds'] or false end 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.isInventoryEmpty = function() for i=1, 16, 1 do if turtle.getItemCount(i) > 0 then return false end end return true end turtleUtils.isInventoryFull = function(withCompact) local isFull = isTurtleInventoryFull() if isFull and withCompact then turtleUtils.compactInventory() return isTurtleInventoryFull() end return isFull end turtleUtils.getItemName = function(slotIndex) local item = turtle.getItemDetail(slotIndex) 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 if not inspectFn() then return nil end 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 true do local ok, err = turtle.dig() if not ok then return ok, err end 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.selectItemBy = function(predicate) for i = 1, 16, 1 do if predicate(i) then turtle.select(i) return true end end return false end turtleUtils.ensureSelected = function(slot) if turtle.getSelectedSlot() ~= slot then return turtle.select(slot) end return true 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 functions 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 (return the number of freed slots) turtleUtils.compactInventory = function() local initialNbFreeSlots = turtleUtils.countFreeSlots() 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 return turtleUtils.countFreeSlots() - initialNbFreeSlots end -- utils functions used by "refuelWithBuffer" local function getSuckFn(side) if side == 'front' then return turtle.suck elseif side == 'top' then return turtle.suckUp elseif side == 'bottom' then return turtle.suckDown end end local function findFuelSlot(inventory) for slot in pairs(inventory.list()) do local item = inventory.getItemDetail(slot) if item and turtleUtils.isFuelItem(item) then return slot end end end -- Refuel using a buffer chest turtleUtils.refuelWithBuffer = function(sideFuel, sideBuffer, minFuelNeeded, sleepTime) sleepTime = sleepTime or DEFAULT_IDLE_TIME minFuelNeeded = minFuelNeeded or DEFAULT_MIN_FUEL_NEEDED local suckFn = getSuckFn(sideBuffer) if not suckFn then return false, 'refuelWithBuffer: sideBuffer should be "front", "top" or "bottom"' end local fuelInventory = turtleUtils.waitForInventory(sideFuel, sleepTime) local bufferInventory = turtleUtils.waitForInventory(sideBuffer, sleepTime) local ok, errMessage = turtleUtils.refuel(minFuelNeeded, function() local fuelSlot = findFuelSlot(fuelInventory) if fuelSlot ~= nil then fuelInventory.pushItems(peripheral.getName(bufferInventory), fuelSlot) end return suckFn() end, sleepTime) return ok, errMessage end return turtleUtils