turtle/libs/turtleutils.lua
2025-06-27 15:17:02 +01:00

236 lines
5.9 KiB
Lua

local M = {}
local logger = require("libs.logger")
-- Optional external status setter (set via M.setStatusCallback)
-- Status callback
local statusCallback = nil
function M.setStatusCallback(fn) statusCallback = fn end
-- Position tracking state for manual mode
local manualPos = { x = 0, y = 0, z = 0 }
local directions = {"north", "east", "south", "west"}
local facing = 1
-- GPS attempt
local function tryGPS()
local x, y, z = gps.locate(2) -- 2 second timeout
if x and y and z then
return { x = math.floor(x), y = math.floor(y), z = math.floor(z) }
end
return nil
end
-- Manual position update helpers
local function updatePositionOnMove(direction)
if direction == "forward" then
if directions[facing] == "north" then manualPos.z = manualPos.z - 1
elseif directions[facing] == "south" then manualPos.z = manualPos.z + 1
elseif directions[facing] == "east" then manualPos.x = manualPos.x + 1
elseif directions[facing] == "west" then manualPos.x = manualPos.x - 1 end
elseif direction == "back" then
if directions[facing] == "north" then manualPos.z = manualPos.z + 1
elseif directions[facing] == "south" then manualPos.z = manualPos.z - 1
elseif directions[facing] == "east" then manualPos.x = manualPos.x - 1
elseif directions[facing] == "west" then manualPos.x = manualPos.x + 1 end
elseif direction == "up" then manualPos.y = manualPos.y + 1
elseif direction == "down" then manualPos.y = manualPos.y - 1 end
end
local function updateFacingLeft()
facing = facing - 1
if facing < 1 then facing = 4 end
end
local function updateFacingRight()
facing = facing + 1
if facing > 4 then facing = 1 end
end
-- Public function to get current position (GPS or manual)
function M.getPosition()
local gpsPos = tryGPS()
if gpsPos then
return gpsPos.x, gpsPos.y, gpsPos.z, true
else
return manualPos.x, manualPos.y, manualPos.z, false
end
end
-- Minimum fuel required to proceed with one movement
local MIN_FUEL = 1 -- you can raise this if you want a safety margin
-- 🔋 Attempt to refuel from inventory
local function refuelFromInventory(minRequired)
minRequired = minRequired or MIN_FUEL
local gained = 0
for slot = 1, 16 do
turtle.select(slot)
if turtle.getItemCount() > 0 and turtle.refuel(0) then
local before = turtle.getFuelLevel()
if turtle.refuel(1) then
local after = turtle.getFuelLevel()
local added = after - before
gained = gained + added
logger.log(string.format("Refueled +%d from slot %d", added, slot))
if after >= minRequired then break end
else
logger.log(string.format("Refuel failed from slot %d", slot))
end
end
end
return gained
end
-- Ensure fuel before doing anything
local function refuelIfNeeded()
local fuel = turtle.getFuelLevel()
if fuel == "unlimited" then return true end
if fuel < MIN_FUEL then
logger.log("Low fuel, attempting to refuel...")
local added = refuelFromInventory(MIN_FUEL)
fuel = turtle.getFuelLevel()
end
while fuel < MIN_FUEL do
if statusCallback then statusCallback("out_of_fuel") end
logger.log("No fuel. Waiting for fuel...")
sleep(5)
-- Try to refuel again
local added = refuelFromInventory(MIN_FUEL)
fuel = turtle.getFuelLevel()
end
return true
end
-- Retry a movement or action with fuel awareness
local function try(actionFn, times, name)
times = times or 5
for i = 1, times do
if not refuelIfNeeded() then
sleep(2)
elseif actionFn() then
if name then logger.log("Action succeeded: " .. name) end
return true
end
if name then logger.log("Retrying: " .. name) end
sleep(0.5)
end
if name then logger.log("Gave up after retries: " .. name) end
return false
end
-- Movement wrappers that update manual position
function M.forward()
if turtle.forward() then
updatePositionOnMove("forward")
return true
else
return false
end
end
function M.back()
if turtle.back() then
updatePositionOnMove("back")
return true
else
return false
end
end
function M.up()
if turtle.up() then
updatePositionOnMove("up")
return true
else
return false
end
end
function M.down()
if turtle.down() then
updatePositionOnMove("down")
return true
else
return false
end
end
-- Digging with movement
function M.digForward()
while turtle.detect() do
turtle.dig()
sleep(0.3)
end
end
function M.digUp()
while turtle.detectUp() do
turtle.digUp()
sleep(0.3)
end
end
function M.digDown()
while turtle.detectDown() do
turtle.digDown()
sleep(0.3)
end
end
-- Move forward, clearing blocks if necessary
function M.moveUntilClearForward()
while not turtle.forward() do
if turtle.detect() then
turtle.dig()
else
sleep(0.5)
end
end
end
-- Inspection
function M.inspectForward()
local success, data = turtle.inspect()
if success then return data else return nil end
end
function M.inspectUp()
local success, data = turtle.inspectUp()
if success then return data else return nil end
end
function M.inspectDown()
local success, data = turtle.inspectDown()
if success then return data else return nil end
end
-- Turning functions that update facing direction
function M.turnLeft()
turtle.turnLeft()
updateFacingLeft()
end
function M.turnRight()
turtle.turnRight()
updateFacingRight()
end
function M.turnAround()
turtle.turnLeft()
turtle.turnLeft()
updateFacingLeft()
updateFacingLeft()
end
return M