inital commit
This commit is contained in:
488
pocketremote.lua
Normal file
488
pocketremote.lua
Normal file
@@ -0,0 +1,488 @@
|
|||||||
|
-- Touch-Enabled Command Center for Pocket Computer (FIXED)
|
||||||
|
-- Monitor and control autonomous mining turtles
|
||||||
|
|
||||||
|
local CHANNEL_SEND = 100
|
||||||
|
local CHANNEL_RECEIVE = 101
|
||||||
|
local STATUS_CHANNEL = 102
|
||||||
|
|
||||||
|
local modem = peripheral.find("modem")
|
||||||
|
if not modem then
|
||||||
|
error("No wireless modem found!")
|
||||||
|
end
|
||||||
|
|
||||||
|
if pocket then
|
||||||
|
pocket.equipBack()
|
||||||
|
modem = peripheral.find("modem")
|
||||||
|
end
|
||||||
|
|
||||||
|
modem.open(CHANNEL_RECEIVE)
|
||||||
|
modem.open(STATUS_CHANNEL)
|
||||||
|
|
||||||
|
local w, h = term.getSize()
|
||||||
|
|
||||||
|
-- Tracked turtles
|
||||||
|
local turtles = {}
|
||||||
|
local selectedTurtle = nil
|
||||||
|
local viewMode = "overview" -- overview, detail, manual
|
||||||
|
|
||||||
|
-- Button system
|
||||||
|
local buttons = {}
|
||||||
|
|
||||||
|
local function clearButtons()
|
||||||
|
buttons = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
local function addButton(x, y, width, height, label, action, color)
|
||||||
|
table.insert(buttons, {
|
||||||
|
x = x,
|
||||||
|
y = y,
|
||||||
|
width = width,
|
||||||
|
height = height,
|
||||||
|
label = label,
|
||||||
|
action = action,
|
||||||
|
color = color or colors.gray
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
local function drawButton(btn, highlight)
|
||||||
|
term.setCursorPos(btn.x, btn.y)
|
||||||
|
|
||||||
|
if highlight then
|
||||||
|
term.setBackgroundColor(colors.white)
|
||||||
|
term.setTextColor(colors.black)
|
||||||
|
else
|
||||||
|
term.setBackgroundColor(btn.color)
|
||||||
|
term.setTextColor(colors.white)
|
||||||
|
end
|
||||||
|
|
||||||
|
local text = btn.label
|
||||||
|
local padding = math.floor((btn.width - #text) / 2)
|
||||||
|
|
||||||
|
for dy = 0, btn.height - 1 do
|
||||||
|
term.setCursorPos(btn.x, btn.y + dy)
|
||||||
|
if dy == math.floor(btn.height / 2) then
|
||||||
|
term.write(string.rep(" ", padding) .. text .. string.rep(" ", btn.width - padding - #text))
|
||||||
|
else
|
||||||
|
term.write(string.rep(" ", btn.width))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
term.setBackgroundColor(colors.black)
|
||||||
|
term.setTextColor(colors.white)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function checkButton(x, y)
|
||||||
|
for _, btn in ipairs(buttons) do
|
||||||
|
if x >= btn.x and x < btn.x + btn.width and
|
||||||
|
y >= btn.y and y < btn.y + btn.height then
|
||||||
|
return btn
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Send command to turtle
|
||||||
|
local function sendCommand(turtleID, command, param)
|
||||||
|
modem.transmit(CHANNEL_SEND, CHANNEL_RECEIVE, {
|
||||||
|
command = command,
|
||||||
|
param = param,
|
||||||
|
target = turtleID
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Helper function to format fuel display
|
||||||
|
local function formatFuel(fuel)
|
||||||
|
if not fuel then
|
||||||
|
return "?"
|
||||||
|
elseif fuel == "unlimited" then
|
||||||
|
return "INF"
|
||||||
|
else
|
||||||
|
return tostring(fuel)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Draw UI modes
|
||||||
|
local function drawOverview()
|
||||||
|
clearButtons()
|
||||||
|
term.setBackgroundColor(colors.black)
|
||||||
|
term.clear()
|
||||||
|
term.setCursorPos(1, 1)
|
||||||
|
term.setTextColor(colors.yellow)
|
||||||
|
print("=MINING CMD CENTER=")
|
||||||
|
term.setTextColor(colors.white)
|
||||||
|
|
||||||
|
local startY = 3
|
||||||
|
|
||||||
|
if #turtles == 0 then
|
||||||
|
term.setCursorPos(1, startY)
|
||||||
|
print("No turtles online")
|
||||||
|
print("Waiting...")
|
||||||
|
else
|
||||||
|
for i, turtle in ipairs(turtles) do
|
||||||
|
if i > 3 then break end -- Max 3 turtles on screen
|
||||||
|
|
||||||
|
local y = startY + (i - 1) * 4
|
||||||
|
local selected = (selectedTurtle == i)
|
||||||
|
|
||||||
|
-- Turtle info box
|
||||||
|
term.setCursorPos(1, y)
|
||||||
|
term.setTextColor(selected and colors.lime or colors.white)
|
||||||
|
print(string.format("T-%d [%s]", turtle.turtleID or 0, turtle.mode or "unknown"))
|
||||||
|
|
||||||
|
if turtle.position then
|
||||||
|
print(string.format(" %d,%d,%d",
|
||||||
|
turtle.position.x or 0,
|
||||||
|
turtle.position.y or 0,
|
||||||
|
turtle.position.z or 0))
|
||||||
|
else
|
||||||
|
print(" No GPS")
|
||||||
|
end
|
||||||
|
|
||||||
|
print(string.format(" F:%s I:%d",
|
||||||
|
formatFuel(turtle.fuel),
|
||||||
|
turtle.inventoryCount or 0))
|
||||||
|
|
||||||
|
-- Select button
|
||||||
|
addButton(20, y, 6, 2, "SEL", function()
|
||||||
|
selectedTurtle = i
|
||||||
|
viewMode = "detail"
|
||||||
|
end, selected and colors.lime or colors.blue)
|
||||||
|
|
||||||
|
drawButton(buttons[#buttons])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Bottom buttons
|
||||||
|
local btnY = h - 3
|
||||||
|
addButton(1, btnY, 8, 2, "EXPLORE", function()
|
||||||
|
if selectedTurtle and turtles[selectedTurtle] then
|
||||||
|
sendCommand(turtles[selectedTurtle].turtleID, "explore")
|
||||||
|
end
|
||||||
|
end, colors.green)
|
||||||
|
|
||||||
|
addButton(10, btnY, 8, 2, "HOME", function()
|
||||||
|
if selectedTurtle and turtles[selectedTurtle] then
|
||||||
|
sendCommand(turtles[selectedTurtle].turtleID, "returnHome")
|
||||||
|
end
|
||||||
|
end, colors.orange)
|
||||||
|
|
||||||
|
addButton(19, btnY, 7, 2, "STOP", function()
|
||||||
|
if selectedTurtle and turtles[selectedTurtle] then
|
||||||
|
sendCommand(turtles[selectedTurtle].turtleID, "stop")
|
||||||
|
end
|
||||||
|
end, colors.red)
|
||||||
|
|
||||||
|
for _, btn in ipairs(buttons) do
|
||||||
|
drawButton(btn)
|
||||||
|
end
|
||||||
|
|
||||||
|
term.setTextColor(colors.white)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function drawDetail()
|
||||||
|
if not selectedTurtle or not turtles[selectedTurtle] then
|
||||||
|
viewMode = "overview"
|
||||||
|
drawOverview()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
clearButtons()
|
||||||
|
local turtle = turtles[selectedTurtle]
|
||||||
|
|
||||||
|
term.setBackgroundColor(colors.black)
|
||||||
|
term.clear()
|
||||||
|
term.setCursorPos(1, 1)
|
||||||
|
term.setTextColor(colors.yellow)
|
||||||
|
print("=TURTLE " .. (turtle.turtleID or "?") .. "=")
|
||||||
|
term.setTextColor(colors.white)
|
||||||
|
|
||||||
|
print("")
|
||||||
|
print("Mode: " .. (turtle.mode or "unknown"))
|
||||||
|
print("Fuel: " .. formatFuel(turtle.fuel))
|
||||||
|
|
||||||
|
if turtle.position then
|
||||||
|
print(string.format("Pos: %d,%d,%d",
|
||||||
|
turtle.position.x or 0,
|
||||||
|
turtle.position.y or 0,
|
||||||
|
turtle.position.z or 0))
|
||||||
|
else
|
||||||
|
print("Pos: No GPS")
|
||||||
|
end
|
||||||
|
|
||||||
|
if turtle.homePosition and turtle.position then
|
||||||
|
local dist = math.abs((turtle.position.x or 0) - (turtle.homePosition.x or 0)) +
|
||||||
|
math.abs((turtle.position.y or 0) - (turtle.homePosition.y or 0)) +
|
||||||
|
math.abs((turtle.position.z or 0) - (turtle.homePosition.z or 0))
|
||||||
|
print("Home: " .. dist .. " blocks")
|
||||||
|
elseif turtle.homePosition then
|
||||||
|
print("Home: Set")
|
||||||
|
else
|
||||||
|
print("Home: Not set")
|
||||||
|
end
|
||||||
|
|
||||||
|
print("")
|
||||||
|
print("Inventory:")
|
||||||
|
if turtle.inventory and #turtle.inventory > 0 then
|
||||||
|
for i, item in ipairs(turtle.inventory) do
|
||||||
|
if i <= 4 then
|
||||||
|
local name = item.name:match("minecraft:(.+)") or item.name
|
||||||
|
if #name > 18 then name = name:sub(1, 15) .. "..." end
|
||||||
|
print(string.format("%d:%s x%d", item.slot or 0, name, item.count or 0))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
print(" Empty")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Action buttons
|
||||||
|
local btnY = h - 7
|
||||||
|
addButton(1, btnY, 8, 2, "EXPLORE", function()
|
||||||
|
sendCommand(turtle.turtleID, "explore")
|
||||||
|
end, colors.green)
|
||||||
|
|
||||||
|
addButton(10, btnY, 8, 2, "HOME", function()
|
||||||
|
sendCommand(turtle.turtleID, "returnHome")
|
||||||
|
end, colors.orange)
|
||||||
|
|
||||||
|
addButton(19, btnY, 7, 2, "STOP", function()
|
||||||
|
sendCommand(turtle.turtleID, "stop")
|
||||||
|
end, colors.red)
|
||||||
|
|
||||||
|
btnY = h - 4
|
||||||
|
addButton(1, btnY, 12, 2, "MANUAL", function()
|
||||||
|
viewMode = "manual"
|
||||||
|
sendCommand(turtle.turtleID, "manual")
|
||||||
|
end, colors.purple)
|
||||||
|
|
||||||
|
addButton(14, btnY, 12, 2, "SET HOME", function()
|
||||||
|
sendCommand(turtle.turtleID, "setHome")
|
||||||
|
end, colors.blue)
|
||||||
|
|
||||||
|
addButton(1, h - 1, 12, 2, "< BACK", function()
|
||||||
|
viewMode = "overview"
|
||||||
|
end, colors.gray)
|
||||||
|
|
||||||
|
for _, btn in ipairs(buttons) do
|
||||||
|
drawButton(btn)
|
||||||
|
end
|
||||||
|
|
||||||
|
term.setTextColor(colors.white)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function drawManual()
|
||||||
|
if not selectedTurtle or not turtles[selectedTurtle] then
|
||||||
|
viewMode = "overview"
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
clearButtons()
|
||||||
|
local turtle = turtles[selectedTurtle]
|
||||||
|
|
||||||
|
term.setBackgroundColor(colors.black)
|
||||||
|
term.clear()
|
||||||
|
term.setCursorPos(1, 1)
|
||||||
|
term.setTextColor(colors.red)
|
||||||
|
print("=MANUAL CONTROL=")
|
||||||
|
term.setTextColor(colors.white)
|
||||||
|
|
||||||
|
print(string.format("T-%d Fuel:%s",
|
||||||
|
turtle.turtleID or 0,
|
||||||
|
formatFuel(turtle.fuel)))
|
||||||
|
|
||||||
|
-- Movement buttons
|
||||||
|
local centerX = 6
|
||||||
|
local centerY = 5
|
||||||
|
|
||||||
|
-- Forward
|
||||||
|
addButton(centerX, centerY, 3, 2, "W", function()
|
||||||
|
sendCommand(turtle.turtleID, "forward")
|
||||||
|
end, colors.blue)
|
||||||
|
|
||||||
|
-- Left
|
||||||
|
addButton(centerX - 4, centerY + 2, 3, 2, "A", function()
|
||||||
|
sendCommand(turtle.turtleID, "turnLeft")
|
||||||
|
end, colors.blue)
|
||||||
|
|
||||||
|
-- Back
|
||||||
|
addButton(centerX, centerY + 2, 3, 2, "S", function()
|
||||||
|
sendCommand(turtle.turtleID, "back")
|
||||||
|
end, colors.blue)
|
||||||
|
|
||||||
|
-- Right
|
||||||
|
addButton(centerX + 4, centerY + 2, 3, 2, "D", function()
|
||||||
|
sendCommand(turtle.turtleID, "turnRight")
|
||||||
|
end, colors.blue)
|
||||||
|
|
||||||
|
-- Up/Down
|
||||||
|
addButton(centerX + 9, centerY, 4, 2, "UP", function()
|
||||||
|
sendCommand(turtle.turtleID, "up")
|
||||||
|
end, colors.cyan)
|
||||||
|
|
||||||
|
addButton(centerX + 9, centerY + 2, 4, 2, "DN", function()
|
||||||
|
sendCommand(turtle.turtleID, "down")
|
||||||
|
end, colors.cyan)
|
||||||
|
|
||||||
|
-- Action buttons
|
||||||
|
local actY = centerY + 5
|
||||||
|
addButton(1, actY, 6, 2, "DIG", function()
|
||||||
|
sendCommand(turtle.turtleID, "dig")
|
||||||
|
end, colors.orange)
|
||||||
|
|
||||||
|
addButton(8, actY, 6, 2, "PLACE", function()
|
||||||
|
sendCommand(turtle.turtleID, "place")
|
||||||
|
end, colors.green)
|
||||||
|
|
||||||
|
addButton(15, actY, 6, 2, "DIGUP", function()
|
||||||
|
sendCommand(turtle.turtleID, "digUp")
|
||||||
|
end, colors.orange)
|
||||||
|
|
||||||
|
addButton(22, actY, 5, 2, "DIGD", function()
|
||||||
|
sendCommand(turtle.turtleID, "digDown")
|
||||||
|
end, colors.orange)
|
||||||
|
|
||||||
|
-- Bottom buttons
|
||||||
|
addButton(1, h - 3, 8, 2, "HOME", function()
|
||||||
|
sendCommand(turtle.turtleID, "returnHome")
|
||||||
|
end, colors.orange)
|
||||||
|
|
||||||
|
addButton(10, h - 3, 8, 2, "REFUEL", function()
|
||||||
|
sendCommand(turtle.turtleID, "refuel")
|
||||||
|
end, colors.lime)
|
||||||
|
|
||||||
|
addButton(19, h - 3, 7, 2, "INFO", function()
|
||||||
|
sendCommand(turtle.turtleID, "status")
|
||||||
|
end, colors.lightBlue)
|
||||||
|
|
||||||
|
addButton(1, h, 12, 1, "< BACK", function()
|
||||||
|
viewMode = "detail"
|
||||||
|
end, colors.gray)
|
||||||
|
|
||||||
|
addButton(14, h, 13, 1, "AUTO MODE", function()
|
||||||
|
sendCommand(turtle.turtleID, "explore")
|
||||||
|
viewMode = "detail"
|
||||||
|
end, colors.purple)
|
||||||
|
|
||||||
|
for _, btn in ipairs(buttons) do
|
||||||
|
drawButton(btn)
|
||||||
|
end
|
||||||
|
|
||||||
|
term.setTextColor(colors.white)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function draw()
|
||||||
|
if viewMode == "overview" then
|
||||||
|
drawOverview()
|
||||||
|
elseif viewMode == "detail" then
|
||||||
|
drawDetail()
|
||||||
|
elseif viewMode == "manual" then
|
||||||
|
drawManual()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Handle keyboard input (still works alongside touch)
|
||||||
|
local function handleKey(key)
|
||||||
|
if viewMode == "manual" then
|
||||||
|
local turtle = turtles[selectedTurtle]
|
||||||
|
if not turtle then return end
|
||||||
|
|
||||||
|
local cmd = nil
|
||||||
|
if key == keys.w then cmd = "forward"
|
||||||
|
elseif key == keys.s then cmd = "back"
|
||||||
|
elseif key == keys.a then cmd = "turnLeft"
|
||||||
|
elseif key == keys.d then cmd = "turnRight"
|
||||||
|
elseif key == keys.space then cmd = "up"
|
||||||
|
elseif key == keys.leftShift or key == keys.rightShift then cmd = "down"
|
||||||
|
elseif key == keys.e then cmd = "dig"
|
||||||
|
elseif key == keys.q then cmd = "place"
|
||||||
|
end
|
||||||
|
|
||||||
|
if cmd then
|
||||||
|
sendCommand(turtle.turtleID, cmd)
|
||||||
|
end
|
||||||
|
elseif viewMode == "overview" then
|
||||||
|
if key >= keys.one and key <= keys.nine then
|
||||||
|
local index = key - keys.one + 1
|
||||||
|
if turtles[index] then
|
||||||
|
selectedTurtle = index
|
||||||
|
viewMode = "detail"
|
||||||
|
draw()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Handle touch
|
||||||
|
local function handleTouch(x, y)
|
||||||
|
local btn = checkButton(x, y)
|
||||||
|
if btn and btn.action then
|
||||||
|
-- Visual feedback
|
||||||
|
drawButton(btn, true)
|
||||||
|
sleep(0.1)
|
||||||
|
drawButton(btn, false)
|
||||||
|
|
||||||
|
-- Execute action
|
||||||
|
btn.action()
|
||||||
|
draw()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Main loop
|
||||||
|
print("Initializing...")
|
||||||
|
sleep(0.5)
|
||||||
|
draw()
|
||||||
|
|
||||||
|
parallel.waitForAny(
|
||||||
|
function()
|
||||||
|
-- Touch/click handler
|
||||||
|
while true do
|
||||||
|
local event, p1, p2, p3 = os.pullEvent()
|
||||||
|
if event == "mouse_click" or event == "monitor_touch" then
|
||||||
|
handleTouch(p2, p3)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
function()
|
||||||
|
-- Keyboard handler
|
||||||
|
while true do
|
||||||
|
local event, key = os.pullEvent("key")
|
||||||
|
handleKey(key)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
function()
|
||||||
|
-- Status receiver
|
||||||
|
while true do
|
||||||
|
local event, side, channel, replyChannel, message = os.pullEvent("modem_message")
|
||||||
|
|
||||||
|
if channel == STATUS_CHANNEL and type(message) == "table" and message.type == "status" then
|
||||||
|
-- Update or add turtle
|
||||||
|
local found = false
|
||||||
|
for i, t in ipairs(turtles) do
|
||||||
|
if t.turtleID == message.turtleID then
|
||||||
|
turtles[i] = message
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not found then
|
||||||
|
table.insert(turtles, message)
|
||||||
|
if not selectedTurtle then
|
||||||
|
selectedTurtle = 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
draw()
|
||||||
|
elseif channel == CHANNEL_RECEIVE and type(message) == "table" and message.status then
|
||||||
|
-- Response from turtle
|
||||||
|
draw()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
function()
|
||||||
|
-- Refresh display
|
||||||
|
while true do
|
||||||
|
sleep(2)
|
||||||
|
draw()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
)
|
||||||
611
turtle.lua
Normal file
611
turtle.lua
Normal file
@@ -0,0 +1,611 @@
|
|||||||
|
-- Advanced Autonomous Mining Turtle (FIXED v3)
|
||||||
|
-- Features: GPS tracking, auto-mining, fuel management, smart navigation
|
||||||
|
|
||||||
|
local CHANNEL_RECEIVE = 100
|
||||||
|
local CHANNEL_SEND = 101
|
||||||
|
local STATUS_CHANNEL = 102
|
||||||
|
|
||||||
|
-- State management
|
||||||
|
local state = {
|
||||||
|
mode = "idle", -- idle, manual, exploring, mining, returning
|
||||||
|
position = nil,
|
||||||
|
homePosition = nil,
|
||||||
|
fuel = 0,
|
||||||
|
inventory = {},
|
||||||
|
target = nil,
|
||||||
|
path = {},
|
||||||
|
lastStatusUpdate = 0,
|
||||||
|
stuckCounter = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Configuration
|
||||||
|
local config = {
|
||||||
|
minFuelToReturn = 500,
|
||||||
|
minFuelToExplore = 1000,
|
||||||
|
statusUpdateInterval = 5, -- seconds
|
||||||
|
maxStuckAttempts = 3,
|
||||||
|
valuableBlocks = {
|
||||||
|
["minecraft:coal_ore"] = 1,
|
||||||
|
["minecraft:iron_ore"] = 2,
|
||||||
|
["minecraft:gold_ore"] = 3,
|
||||||
|
["minecraft:diamond_ore"] = 5,
|
||||||
|
["minecraft:emerald_ore"] = 5,
|
||||||
|
["minecraft:redstone_ore"] = 2,
|
||||||
|
["minecraft:lapis_ore"] = 2,
|
||||||
|
["minecraft:deepslate_coal_ore"] = 1,
|
||||||
|
["minecraft:deepslate_iron_ore"] = 2,
|
||||||
|
["minecraft:deepslate_gold_ore"] = 3,
|
||||||
|
["minecraft:deepslate_diamond_ore"] = 5,
|
||||||
|
["minecraft:deepslate_emerald_ore"] = 5,
|
||||||
|
["minecraft:deepslate_redstone_ore"] = 2,
|
||||||
|
["minecraft:deepslate_lapis_ore"] = 2,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Check for modem
|
||||||
|
local modem = peripheral.find("modem")
|
||||||
|
if not modem then
|
||||||
|
error("No wireless modem found!")
|
||||||
|
end
|
||||||
|
modem.open(CHANNEL_RECEIVE)
|
||||||
|
|
||||||
|
print("Advanced Mining Turtle System")
|
||||||
|
print("ID: " .. os.getComputerID())
|
||||||
|
|
||||||
|
-- GPS Functions
|
||||||
|
local function updatePosition()
|
||||||
|
local x, y, z = gps.locate(2)
|
||||||
|
if x then
|
||||||
|
state.position = {x = math.floor(x), y = math.floor(y), z = math.floor(z)}
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local function setHome()
|
||||||
|
if updatePosition() then
|
||||||
|
state.homePosition = {
|
||||||
|
x = state.position.x,
|
||||||
|
y = state.position.y,
|
||||||
|
z = state.position.z
|
||||||
|
}
|
||||||
|
print("Home set at: " .. state.homePosition.x .. ", " .. state.homePosition.y .. ", " .. state.homePosition.z)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
print("Failed to get GPS position for home")
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Movement tracking
|
||||||
|
local facing = 0 -- 0=North(Z-), 1=East(X+), 2=South(Z+), 3=West(X-)
|
||||||
|
|
||||||
|
local function updateFacingAfterTurn(right)
|
||||||
|
if right then
|
||||||
|
facing = (facing + 1) % 4
|
||||||
|
else
|
||||||
|
facing = (facing - 1) % 4
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function smartForward()
|
||||||
|
local success = turtle.forward()
|
||||||
|
if success and state.position then
|
||||||
|
if facing == 0 then state.position.z = state.position.z - 1
|
||||||
|
elseif facing == 1 then state.position.x = state.position.x + 1
|
||||||
|
elseif facing == 2 then state.position.z = state.position.z + 1
|
||||||
|
elseif facing == 3 then state.position.x = state.position.x - 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return success
|
||||||
|
end
|
||||||
|
|
||||||
|
local function smartBack()
|
||||||
|
local success = turtle.back()
|
||||||
|
if success and state.position then
|
||||||
|
if facing == 0 then state.position.z = state.position.z + 1
|
||||||
|
elseif facing == 1 then state.position.x = state.position.x - 1
|
||||||
|
elseif facing == 2 then state.position.z = state.position.z - 1
|
||||||
|
elseif facing == 3 then state.position.x = state.position.x + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return success
|
||||||
|
end
|
||||||
|
|
||||||
|
local function smartUp()
|
||||||
|
local success = turtle.up()
|
||||||
|
if success and state.position then
|
||||||
|
state.position.y = state.position.y + 1
|
||||||
|
end
|
||||||
|
return success
|
||||||
|
end
|
||||||
|
|
||||||
|
local function smartDown()
|
||||||
|
local success = turtle.down()
|
||||||
|
if success and state.position then
|
||||||
|
state.position.y = state.position.y - 1
|
||||||
|
end
|
||||||
|
return success
|
||||||
|
end
|
||||||
|
|
||||||
|
local function smartTurnRight()
|
||||||
|
local success = turtle.turnRight()
|
||||||
|
if success then
|
||||||
|
updateFacingAfterTurn(true)
|
||||||
|
end
|
||||||
|
return success
|
||||||
|
end
|
||||||
|
|
||||||
|
local function smartTurnLeft()
|
||||||
|
local success = turtle.turnLeft()
|
||||||
|
if success then
|
||||||
|
updateFacingAfterTurn(false)
|
||||||
|
end
|
||||||
|
return success
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Fuel management
|
||||||
|
local function updateFuel()
|
||||||
|
state.fuel = turtle.getFuelLevel()
|
||||||
|
return state.fuel
|
||||||
|
end
|
||||||
|
|
||||||
|
local function needsRefuel()
|
||||||
|
return state.fuel ~= "unlimited" and state.fuel < config.minFuelToReturn
|
||||||
|
end
|
||||||
|
|
||||||
|
local function tryRefuel()
|
||||||
|
for slot = 1, 16 do
|
||||||
|
turtle.select(slot)
|
||||||
|
if turtle.refuel(0) then -- Check if it's fuel
|
||||||
|
local count = turtle.getItemCount()
|
||||||
|
if count > 0 then
|
||||||
|
turtle.refuel(1)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Inventory management
|
||||||
|
local function updateInventory()
|
||||||
|
state.inventory = {}
|
||||||
|
for slot = 1, 16 do
|
||||||
|
local item = turtle.getItemDetail(slot)
|
||||||
|
if item then
|
||||||
|
table.insert(state.inventory, {
|
||||||
|
slot = slot,
|
||||||
|
name = item.name,
|
||||||
|
count = item.count
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function inventoryFull()
|
||||||
|
for slot = 1, 16 do
|
||||||
|
if turtle.getItemCount(slot) == 0 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local function isValuableBlock(blockName)
|
||||||
|
return config.valuableBlocks[blockName] ~= nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check if block is unbreakable
|
||||||
|
local function isUnbreakable(blockName)
|
||||||
|
if not blockName then return false end
|
||||||
|
return string.find(blockName, "bedrock") or string.find(blockName, "barrier")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Mining functions
|
||||||
|
local function smartDig(direction)
|
||||||
|
direction = direction or "forward"
|
||||||
|
|
||||||
|
local digFunc, inspectFunc
|
||||||
|
if direction == "forward" then
|
||||||
|
digFunc = turtle.dig
|
||||||
|
inspectFunc = turtle.inspect
|
||||||
|
elseif direction == "up" then
|
||||||
|
digFunc = turtle.digUp
|
||||||
|
inspectFunc = turtle.inspectUp
|
||||||
|
elseif direction == "down" then
|
||||||
|
digFunc = turtle.digDown
|
||||||
|
inspectFunc = turtle.inspectDown
|
||||||
|
end
|
||||||
|
|
||||||
|
local hasBlock, data = inspectFunc()
|
||||||
|
if hasBlock then
|
||||||
|
if isUnbreakable(data.name) then
|
||||||
|
return false, false, data.name
|
||||||
|
end
|
||||||
|
local valuable = isValuableBlock(data.name)
|
||||||
|
digFunc()
|
||||||
|
return true, valuable, data.name
|
||||||
|
end
|
||||||
|
return false, false, nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Pathfinding (improved with obstacle handling)
|
||||||
|
local function getDistance(pos1, pos2)
|
||||||
|
return math.abs(pos1.x - pos2.x) + math.abs(pos1.y - pos2.y) + math.abs(pos1.z - pos2.z)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Try to dig and move forward
|
||||||
|
local function forceForward()
|
||||||
|
for i = 1, 5 do
|
||||||
|
if smartForward() then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
smartDig("forward")
|
||||||
|
sleep(0.3)
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Try to dig and move up
|
||||||
|
local function forceUp()
|
||||||
|
for i = 1, 5 do
|
||||||
|
if smartUp() then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
smartDig("up")
|
||||||
|
sleep(0.3)
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Try to dig and move down
|
||||||
|
local function forceDown()
|
||||||
|
for i = 1, 5 do
|
||||||
|
if smartDown() then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
smartDig("down")
|
||||||
|
sleep(0.3)
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Advanced navigation with unstuck logic
|
||||||
|
local function navigateTowards(target)
|
||||||
|
if not state.position or not target then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local dx = target.x - state.position.x
|
||||||
|
local dy = target.y - state.position.y
|
||||||
|
local dz = target.z - state.position.z
|
||||||
|
|
||||||
|
local lastPos = {x = state.position.x, y = state.position.y, z = state.position.z}
|
||||||
|
|
||||||
|
-- Prioritize vertical movement if needed
|
||||||
|
if math.abs(dy) > 3 then
|
||||||
|
if dy > 0 then
|
||||||
|
if forceUp() then
|
||||||
|
state.stuckCounter = 0
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if forceDown() then
|
||||||
|
state.stuckCounter = 0
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Horizontal movement
|
||||||
|
local targetFacing
|
||||||
|
if math.abs(dx) > math.abs(dz) then
|
||||||
|
targetFacing = dx > 0 and 1 or 3
|
||||||
|
else
|
||||||
|
targetFacing = dz > 0 and 2 or 0
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Face the right direction
|
||||||
|
while facing ~= targetFacing do
|
||||||
|
smartTurnRight()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Try to move forward
|
||||||
|
if forceForward() then
|
||||||
|
state.stuckCounter = 0
|
||||||
|
else
|
||||||
|
-- Stuck! Try alternative routes
|
||||||
|
state.stuckCounter = state.stuckCounter + 1
|
||||||
|
print("Stuck counter: " .. state.stuckCounter)
|
||||||
|
|
||||||
|
if state.stuckCounter > config.maxStuckAttempts then
|
||||||
|
print("Trying alternative path...")
|
||||||
|
state.stuckCounter = 0
|
||||||
|
|
||||||
|
-- Try going up to go over obstacle
|
||||||
|
if forceUp() then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Try going around
|
||||||
|
smartTurnRight()
|
||||||
|
if forceForward() then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
smartTurnLeft()
|
||||||
|
smartTurnLeft()
|
||||||
|
if forceForward() then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Last resort: dig down and try lower path
|
||||||
|
smartTurnRight()
|
||||||
|
forceDown()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check if we're close enough
|
||||||
|
return getDistance(state.position, target) < 2
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Status broadcasting
|
||||||
|
function broadcastStatus()
|
||||||
|
updateFuel()
|
||||||
|
updateInventory()
|
||||||
|
updatePosition()
|
||||||
|
|
||||||
|
modem.transmit(STATUS_CHANNEL, CHANNEL_RECEIVE, {
|
||||||
|
type = "status",
|
||||||
|
turtleID = os.getComputerID(),
|
||||||
|
mode = state.mode,
|
||||||
|
position = state.position,
|
||||||
|
homePosition = state.homePosition,
|
||||||
|
fuel = state.fuel,
|
||||||
|
inventoryCount = #state.inventory,
|
||||||
|
inventory = state.inventory,
|
||||||
|
facing = facing
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Return to home with better navigation
|
||||||
|
local function returnHome()
|
||||||
|
print("Returning home...")
|
||||||
|
state.mode = "returning"
|
||||||
|
state.stuckCounter = 0
|
||||||
|
broadcastStatus()
|
||||||
|
|
||||||
|
local maxAttempts = 1000
|
||||||
|
local attempts = 0
|
||||||
|
|
||||||
|
while state.homePosition and state.position and
|
||||||
|
getDistance(state.position, state.homePosition) > 1 and
|
||||||
|
attempts < maxAttempts do
|
||||||
|
|
||||||
|
-- Check for stop command
|
||||||
|
if state.mode ~= "returning" then
|
||||||
|
print("Return cancelled")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
updateFuel()
|
||||||
|
if needsRefuel() then
|
||||||
|
print("Low fuel, trying to refuel...")
|
||||||
|
if tryRefuel() then
|
||||||
|
print("Refueled!")
|
||||||
|
else
|
||||||
|
print("WARNING: Out of fuel!")
|
||||||
|
state.mode = "idle"
|
||||||
|
broadcastStatus()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local arrived = navigateTowards(state.homePosition)
|
||||||
|
if arrived then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
attempts = attempts + 1
|
||||||
|
|
||||||
|
-- Update GPS position every few steps
|
||||||
|
if attempts % 10 == 0 then
|
||||||
|
updatePosition()
|
||||||
|
print("Distance to home: " .. getDistance(state.position, state.homePosition))
|
||||||
|
end
|
||||||
|
|
||||||
|
sleep(0.1)
|
||||||
|
end
|
||||||
|
|
||||||
|
if attempts >= maxAttempts then
|
||||||
|
print("Could not reach home - gave up after " .. maxAttempts .. " attempts")
|
||||||
|
else
|
||||||
|
print("Arrived at home!")
|
||||||
|
end
|
||||||
|
|
||||||
|
state.mode = "idle"
|
||||||
|
state.stuckCounter = 0
|
||||||
|
broadcastStatus()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Exploration algorithm
|
||||||
|
local function exploreStep()
|
||||||
|
-- Check all directions for valuable ores
|
||||||
|
for _, direction in ipairs({"forward", "up", "down"}) do
|
||||||
|
local dug, valuable, blockName = smartDig(direction)
|
||||||
|
if valuable then
|
||||||
|
print("Found: " .. blockName)
|
||||||
|
broadcastStatus()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Random exploration with preference for going deeper
|
||||||
|
local r = math.random(1, 10)
|
||||||
|
if r <= 3 then
|
||||||
|
-- Go down 30% of the time
|
||||||
|
if not smartDown() then
|
||||||
|
smartDig("down")
|
||||||
|
smartDown()
|
||||||
|
end
|
||||||
|
elseif r <= 5 then
|
||||||
|
-- Turn
|
||||||
|
if math.random() > 0.5 then
|
||||||
|
smartTurnRight()
|
||||||
|
else
|
||||||
|
smartTurnLeft()
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- Move forward
|
||||||
|
if not smartForward() then
|
||||||
|
smartDig("forward")
|
||||||
|
if not smartForward() then
|
||||||
|
smartTurnRight()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Command handling
|
||||||
|
local commands = {
|
||||||
|
forward = function() return smartForward(), "Moved forward" end,
|
||||||
|
back = function() return smartBack(), "Moved back" end,
|
||||||
|
up = function() return smartUp(), "Moved up" end,
|
||||||
|
down = function() return smartDown(), "Moved down" end,
|
||||||
|
turnLeft = function() return smartTurnLeft(), "Turned left" end,
|
||||||
|
turnRight = function() return smartTurnRight(), "Turned right" end,
|
||||||
|
dig = function()
|
||||||
|
local dug, val, name = smartDig("forward")
|
||||||
|
return dug, dug and "Dug: " .. (name or "block") or "Nothing to dig"
|
||||||
|
end,
|
||||||
|
digUp = function()
|
||||||
|
local dug, val, name = smartDig("up")
|
||||||
|
return dug, dug and "Dug up: " .. (name or "block") or "Nothing above"
|
||||||
|
end,
|
||||||
|
digDown = function()
|
||||||
|
local dug, val, name = smartDig("down")
|
||||||
|
return dug, dug and "Dug down: " .. (name or "block") or "Nothing below"
|
||||||
|
end,
|
||||||
|
place = function() return turtle.place(), "Placed" end,
|
||||||
|
select = function(slot) return turtle.select(slot), "Selected slot " .. slot end,
|
||||||
|
refuel = function()
|
||||||
|
local success = tryRefuel()
|
||||||
|
updateFuel()
|
||||||
|
broadcastStatus()
|
||||||
|
return success, success and ("Refueled! Now: " .. state.fuel) or "No fuel"
|
||||||
|
end,
|
||||||
|
status = function() broadcastStatus() return true, "Status sent" end,
|
||||||
|
|
||||||
|
-- Autonomous commands
|
||||||
|
setHome = function() return setHome(), "Home set" end,
|
||||||
|
|
||||||
|
explore = function()
|
||||||
|
print("Explore command received")
|
||||||
|
state.mode = "exploring"
|
||||||
|
state.stuckCounter = 0
|
||||||
|
broadcastStatus()
|
||||||
|
return true, "Starting exploration"
|
||||||
|
end,
|
||||||
|
|
||||||
|
returnHome = function()
|
||||||
|
print("Return home command received")
|
||||||
|
state.mode = "returning"
|
||||||
|
state.stuckCounter = 0
|
||||||
|
broadcastStatus()
|
||||||
|
return true, "Returning home"
|
||||||
|
end,
|
||||||
|
|
||||||
|
stop = function()
|
||||||
|
print("STOP command received")
|
||||||
|
state.mode = "idle"
|
||||||
|
state.stuckCounter = 0
|
||||||
|
broadcastStatus()
|
||||||
|
return true, "Stopped"
|
||||||
|
end,
|
||||||
|
|
||||||
|
manual = function()
|
||||||
|
state.mode = "manual"
|
||||||
|
broadcastStatus()
|
||||||
|
return true, "Manual control"
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Process incoming messages
|
||||||
|
local function processMessage(message)
|
||||||
|
if type(message) == "table" and message.command then
|
||||||
|
print("Command: " .. message.command)
|
||||||
|
|
||||||
|
local handler = commands[message.command]
|
||||||
|
if handler then
|
||||||
|
local success, result = handler(message.param)
|
||||||
|
|
||||||
|
modem.transmit(CHANNEL_SEND, CHANNEL_RECEIVE, {
|
||||||
|
status = success and "ok" or "error",
|
||||||
|
message = result or "",
|
||||||
|
turtleID = os.getComputerID()
|
||||||
|
})
|
||||||
|
|
||||||
|
broadcastStatus()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Main loop
|
||||||
|
print("Initializing...")
|
||||||
|
updatePosition()
|
||||||
|
updateFuel()
|
||||||
|
|
||||||
|
if not state.position then
|
||||||
|
print("WARNING: No GPS signal!")
|
||||||
|
print("Limited functionality available")
|
||||||
|
end
|
||||||
|
|
||||||
|
print("Ready! Waiting for commands...")
|
||||||
|
broadcastStatus()
|
||||||
|
|
||||||
|
-- Main execution loop
|
||||||
|
parallel.waitForAny(
|
||||||
|
function()
|
||||||
|
-- Status broadcast loop
|
||||||
|
while true do
|
||||||
|
sleep(config.statusUpdateInterval)
|
||||||
|
broadcastStatus()
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
function()
|
||||||
|
-- Command processing loop
|
||||||
|
while true do
|
||||||
|
local event, side, channel, replyChannel, message = os.pullEvent()
|
||||||
|
|
||||||
|
if event == "modem_message" then
|
||||||
|
processMessage(message)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
function()
|
||||||
|
-- Autonomous execution loop
|
||||||
|
while true do
|
||||||
|
if state.mode == "exploring" then
|
||||||
|
updateFuel()
|
||||||
|
|
||||||
|
-- Check if we should stop
|
||||||
|
if needsRefuel() or inventoryFull() then
|
||||||
|
print("Need to return home")
|
||||||
|
state.mode = "returning"
|
||||||
|
broadcastStatus()
|
||||||
|
else
|
||||||
|
exploreStep()
|
||||||
|
sleep(0.2)
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif state.mode == "returning" then
|
||||||
|
returnHome()
|
||||||
|
|
||||||
|
else
|
||||||
|
-- Idle or manual mode
|
||||||
|
sleep(0.5)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user