cc-utilities/quarry.lua
2024-12-03 23:17:57 +01:00

185 lines
4.6 KiB
Lua

local args = {...}
local Logging = require("logging")
local Logger = Logging.firstLoad(
Logging.OUTPUTS.file("tunnel.log"),
Logging.OUTPUTS.stdout()
)
local CHEST_SLOT = #args == 1 and tonumber(args[1]) or 1
if type(CHEST_SLOT) ~= "number" or CHEST_SLOT < 1 or CHEST_SLOT > 16 then
Logger:error("Slot number is not valid:", CHEST_SLOT)
end
local CHEST_PICKUP = #args == 2 and (args[2]:lower() )
local CHEST_DETAIL = turtle.getItemDetail(CHEST_SLOT)
if CHEST_DETAIL == nil then
Logger:error("No chest in slot! Quitting...")
return
end
local CHEST_NAME = CHEST_DETAIL.name
local function refuel(minFuel)
local fuelLevel = turtle.getFuelLevel()
while fuelLevel < minFuel do
Logger:debug("Checking fuel level:", fuelLevel)
for i=1,16 do
if i == CHEST_SLOT then
goto continue
end
if turtle.getItemCount(i) > 0 then
turtle.select(i)
turtle.refuel()
end
::continue::
end
fuelLevel = turtle.getFuelLevel()
end
Logger:debug("Fuel level is sufficient:", fuelLevel)
turtle.select(1)
end
local function isFull(minEmpty)
local emptyCount = 0
for i=1,16 do
if i == CHEST_SLOT then
goto continue
end
if turtle.getItemCount(i) == 0 then
emptyCount = emptyCount + 1
if emptyCount >= minEmpty then
return false
end
end
::continue::
end
return true
end
local function placeChest()
if not turtle.select(CHEST_SLOT) then
Logger:error("Cannot select chest slot", CHEST_SLOT)
return false, nil, nil, nil
end
if turtle.placeUp() or (turtle.digUp() and turtle.placeUp()) then
return true, turtle.dropUp, turtle.digUp, function() end
end
if turtle.turnLeft() and turtle.turnLeft() and (turtle.place() or (turtle.dig() and turtle.place())) then
return true, turtle.drop, turtle.dig, function()
turtle.turnRight()
turtle.turnRight()
end
end
return false, nil, nil, nil
end
local function handleFullInv(minEmpty)
local didPlace = false
local result, drop, dig, onComplete = false, nil, nil, nil
-- Empty inventory
while isFull(minEmpty) do
if not didPlace then
local detail = turtle.getItemDetail(CHEST_SLOT)
if type(detail) ~= "table" or detail.name ~= CHEST_NAME then
Logger:error("Can't find chest :(")
os.sleep(5)
goto continue
end
-- Try: place, check block above is empty or dig it, place
-- If all fails, print error, wait and repeat
result, drop, dig, onComplete = placeChest()
if not result then
Logger:error("Can't place chest :(")
os.sleep(5)
goto continue
end
didPlace = true
end
assert(drop ~= nil, "Placed chest, but drop operation is nil")
for i=1,16 do
if i == CHEST_SLOT then
goto continue_SLOT
end
if turtle.getItemCount(i) > 0 and not (turtle.select(i) and drop()) then
Logger:error("Couldn't drop items into chest!")
goto continue
end
::continue_SLOT::
end
::continue::
end
if result then
assert(dig ~= nil, "Placed chest, but dig operation is nil")
if didPlace and CHEST_PICKUP then
turtle.select(CHEST_SLOT)
dig()
end
assert(onComplete ~= nil, "Placed chest, but onComplete operation is nil")
onComplete()
end
end
local function dig(checkRefuel)
while not turtle.forward() do
turtle.dig()
checkRefuel()
end
turtle.digUp()
turtle.digDown()
end
local function line(length, turn, checkRefuel)
turtle.digDown()
for _=2,length do
dig(checkRefuel)
end
turn()
end
local function panel(width, length, leftFirst, checkRefuel, checkFullInv)
Logger:trace("Panel:", width, length)
local turn, otherTurn = leftFirst and turtle.turnLeft or turtle.turnRight, leftFirst and turtle.turnRight or turtle.turnLeft
for _=2,width do
checkFullInv()
line(length, turn, checkRefuel)
dig(checkRefuel)
turn()
turn, otherTurn = otherTurn, turn
end
line(length, turn, checkRefuel)
turn()
end
local function rectPrism(depth, width, length, leftFirst)
local refuelTarget = width * length * 1.5
local function checkRefuel()
refuel(refuelTarget)
end
local invEmptyTarget = 3
local function checkFullInv()
Logger:debug("Handling full inventory with target:", invEmptyTarget, " handled:", handleFullInv(invEmptyTarget))
end
Logger:trace("RectPrism:", depth, width, length)
for _=1,depth do
panel(width, length, leftFirst, checkRefuel, checkFullInv)
for __=1,3 do
while not turtle.down() do
turtle.digDown()
checkRefuel()
end
end
leftFirst = (not not leftFirst) ~= (width % 2 == 0)
end
end
rectPrism(200, 16, 16)