2019-01-17 19:26:13 +00:00
|
|
|
--[[
|
|
|
|
Turtle Positioning System
|
|
|
|
Use two turtles as an expensive and crappy GPS server! Use ALL the fuel!
|
|
|
|
|
2019-01-17 19:26:52 +00:00
|
|
|
wget https://raw.githubusercontent.com/LDDestroier/CC/master/tps.lua
|
|
|
|
std ld tps tps.lua
|
2019-01-17 19:26:13 +00:00
|
|
|
--]]
|
|
|
|
|
|
|
|
local chestX = 0 -- fill this in!
|
|
|
|
local chestY = 0 -- fill this in!
|
|
|
|
local chestZ = 0 -- fill this in!
|
|
|
|
|
|
|
|
local startx,starty,startz --if there isn't a file storing them
|
|
|
|
startx = 0
|
|
|
|
starty = 64
|
|
|
|
startz = 0
|
|
|
|
|
|
|
|
local chest = true
|
|
|
|
|
|
|
|
if not gps then -- I love error handling
|
|
|
|
return printError("GPS API wasn't found. Are you using an older version of ComputerCraft?")
|
|
|
|
else
|
|
|
|
if type(gps) == "table" then
|
|
|
|
if not (gps.locate) then
|
|
|
|
return printError("gps.locate seems to be missing.")
|
|
|
|
else
|
|
|
|
if type(gps.locate) == "string" then
|
|
|
|
return printError("Is this a joke? gps.locate is a string. This does not make sense.")
|
|
|
|
elseif type(gps.locate) == "table" then
|
|
|
|
return printError("What the... gps.locate is a table! Knock it off.")
|
|
|
|
elseif type(gps.locate) == "number" then
|
|
|
|
return printError("Eh? gps.locate is a number! This doesn't ADD UP!")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local cfilename = ".coords"
|
|
|
|
|
|
|
|
local tArg = {...}
|
|
|
|
local modem = peripheral.find("modem")
|
|
|
|
if not turtle then
|
|
|
|
if pocket then
|
|
|
|
return printError("Yo dipshit, pocket computers can't run TPS.")
|
|
|
|
else
|
|
|
|
return printError("Er. This is a turtle program, you know?")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if not modem then
|
|
|
|
local l = peripheral.wrap("right")
|
|
|
|
local r = peripheral.wrap("left")
|
|
|
|
if r and l then
|
|
|
|
return printError("Dangit, you messed up! Craft a WIRELESS turtle!")
|
|
|
|
else
|
|
|
|
return printError("You need a wireless modem.")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
modem.open(gps.CHANNEL_GPS)
|
|
|
|
|
|
|
|
local tew,tps
|
|
|
|
local requests = 0
|
|
|
|
local scr_x, scr_y = term.getSize()
|
|
|
|
|
|
|
|
local fuels = {
|
|
|
|
["minecraft:coal"] = 80,
|
|
|
|
["minecraft:coal_block"] = 80*9,
|
|
|
|
}
|
|
|
|
|
|
|
|
local dro = function(input)
|
|
|
|
return input % 4
|
|
|
|
end
|
|
|
|
|
|
|
|
local fixNumber = function(num)
|
|
|
|
return math.floor(num+0.5)
|
|
|
|
end
|
|
|
|
|
|
|
|
local getDist = function(x1,y1,z1,x2,y2,z2)
|
|
|
|
return math.abs(x2-x1)+math.abs(y2-y1)+math.abs(z2-z1)
|
|
|
|
end
|
|
|
|
|
|
|
|
local directionNames = {
|
|
|
|
[0] = "South",
|
|
|
|
[1] = "West",
|
|
|
|
[2] = "North",
|
|
|
|
[3] = "East",
|
|
|
|
}
|
|
|
|
|
|
|
|
local dudes = {}
|
|
|
|
|
|
|
|
local total
|
|
|
|
|
|
|
|
local sendRequest = function()
|
|
|
|
total = 0
|
|
|
|
for k,v in pairs(dudes) do
|
|
|
|
if v > 0 then
|
|
|
|
modem.transmit( k, gps.CHANNEL_GPS, { tew.x, tew.y, tew.z } )
|
|
|
|
dudes[k] = dudes[k] - 1
|
|
|
|
requests = requests + 1
|
|
|
|
total = total + 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
tew.lock = (total == 0)
|
|
|
|
end
|
|
|
|
|
|
|
|
local adjustCoords = function(dir, dist)
|
|
|
|
if dir == -1 then
|
|
|
|
tew.y = tew.y + 1
|
|
|
|
elseif dir == -2 then
|
|
|
|
tew.y = tew.y - 1
|
|
|
|
else
|
|
|
|
tew.x = fixNumber(tew.x - math.sin(math.rad(dir*90)))
|
|
|
|
tew.z = fixNumber(tew.z + math.cos(math.rad(dir*90)))
|
|
|
|
end
|
|
|
|
tps(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
local gotoCoords = function( gx, gy, gz )
|
|
|
|
if (gx == tew.x) and (gy == tew.y) and (gz == tew.z) then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
local cx,cy,cz = tew.x,tew.y,tew.z
|
|
|
|
|
|
|
|
while (gx ~= tew.x) or (gy ~= tew.y) or (gz ~= tew.z) do
|
|
|
|
|
|
|
|
for a = 1, math.abs(gy-cy) do
|
|
|
|
if tew.y == gy then
|
|
|
|
break
|
|
|
|
end
|
|
|
|
tew.lock = false
|
|
|
|
if gy > cy then
|
|
|
|
tew.up()
|
|
|
|
else
|
|
|
|
tew.down()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if tew.x ~= gx then
|
|
|
|
tew.lock = false
|
|
|
|
tew.turn(3)
|
|
|
|
for a = 1, math.abs(gx-cx) do
|
|
|
|
if tew.x == gx then
|
|
|
|
break
|
|
|
|
end
|
|
|
|
tew.lock = false
|
|
|
|
if gx > cx then
|
|
|
|
tew.forward()
|
|
|
|
else
|
|
|
|
tew.back()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if tew.z ~= gz then
|
|
|
|
tew.lock = false
|
|
|
|
tew.turn(0)
|
|
|
|
for a = 1, math.abs(gz-cz) do
|
|
|
|
if tew.z == gz then
|
|
|
|
break
|
|
|
|
end
|
|
|
|
tew.lock = false
|
|
|
|
if gz > cz then
|
|
|
|
tew.forward()
|
|
|
|
else
|
|
|
|
tew.back()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local saveTheWhales = function() --HOPEFULLY the path is unobstructed by blocks
|
|
|
|
local bC = {
|
|
|
|
x = tew.x,
|
|
|
|
y = tew.y,
|
|
|
|
z = tew.z,
|
|
|
|
direction = tew.direction,
|
|
|
|
}
|
|
|
|
gotoCoords(chestX,((chestY>bC.y) and (chestY-1) or (chestY+1)),chestZ)
|
|
|
|
for a = 1, 16 do
|
|
|
|
if turtle.inspectUp() then
|
|
|
|
turtle.suckUp()
|
|
|
|
elseif turtle.inspectDown() then
|
|
|
|
turtle.suckDown()
|
|
|
|
elseif turtle.inspect() then
|
|
|
|
turtle.suck()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
gotoCoords(bC.x,bC.y,bC.z)
|
|
|
|
tew.lock = false
|
|
|
|
tew.turn(bC.direction)
|
|
|
|
end
|
|
|
|
|
|
|
|
local checkIfCanFuel = function()
|
|
|
|
local currentSlot = turtle.getSelectedSlot()
|
|
|
|
for a = 1, 16 do
|
|
|
|
local item = turtle.getItemDetail(a)
|
|
|
|
if item then
|
|
|
|
if fuels[item.name] then
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
local doRefuel = function()
|
|
|
|
while true do
|
|
|
|
local currentSlot = turtle.getSelectedSlot()
|
|
|
|
for a = 1, 16 do
|
|
|
|
local item = turtle.getItemDetail(a)
|
|
|
|
if item then
|
|
|
|
if fuels[item.name] then
|
|
|
|
turtle.select(a)
|
|
|
|
turtle.refuel(1)
|
|
|
|
turtle.select(currentSlot)
|
|
|
|
term.setCursorPos(1,scr_y)
|
|
|
|
term.clearLine()
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
sleep(0) -- INSERT MORE FUEL!
|
|
|
|
term.setCursorPos(1,scr_y)
|
|
|
|
term.write("Insert more fuel!!")
|
|
|
|
end
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
local handleFuel = function(chest)
|
|
|
|
if type(turtle.getFuelLevel()) == "number" then
|
|
|
|
if chest and (not checkIfCanFuel()) then
|
|
|
|
local dist = getDist(tew.x,tew.y,tew.z,chestX,chestY,chestZ)
|
|
|
|
if dist+10 > turtle.getFuelLevel() then -- gives me some leeway
|
|
|
|
saveTheWhales() -- PANIC
|
|
|
|
doRefuel()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if turtle.getFuelLevel() == 0 then
|
|
|
|
doRefuel()
|
|
|
|
end
|
|
|
|
else
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- 'tew' is a reproduction of the turtle API, but tracked and written to a file located at cfilename (default: "/.coords")
|
|
|
|
|
|
|
|
tew = { --already localized
|
|
|
|
lock = false,
|
|
|
|
direction = 0,
|
|
|
|
x = startx,
|
|
|
|
y = starty,
|
|
|
|
z = startz,
|
|
|
|
forward = function(dist,doFuelThing)
|
|
|
|
local success, msg
|
|
|
|
for a = 1, dist or 1 do
|
|
|
|
if tew.lock then
|
|
|
|
repeat
|
|
|
|
sleep(0)
|
|
|
|
until not tew.lock
|
|
|
|
end
|
|
|
|
handleFuel(doFuelThing)
|
|
|
|
success, msg = turtle.forward()
|
|
|
|
if success then
|
|
|
|
adjustCoords(dro(tew.direction),1)
|
|
|
|
--os.queueEvent("tew_move")
|
|
|
|
sendRequest()
|
|
|
|
else
|
|
|
|
return success, msg
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return true
|
|
|
|
end,
|
|
|
|
back = function(dist,doFuelThing)
|
|
|
|
local success, msg
|
|
|
|
for a = 1, dist or 1 do
|
|
|
|
if tew.lock then
|
|
|
|
repeat
|
|
|
|
sleep(0)
|
|
|
|
until not tew.lock
|
|
|
|
end
|
|
|
|
handleFuel(doFuelThing)
|
|
|
|
success, msg = turtle.back()
|
|
|
|
if success then
|
|
|
|
adjustCoords(dro(tew.direction+2),1)
|
|
|
|
--os.queueEvent("tew_move")
|
|
|
|
sendRequest()
|
|
|
|
else
|
|
|
|
return success, msg
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return true
|
|
|
|
end,
|
|
|
|
up = function(dist,doFuelThing)
|
|
|
|
local success, msg
|
|
|
|
for a = 1, dist or 1 do
|
|
|
|
if tew.lock then
|
|
|
|
repeat
|
|
|
|
sleep(0)
|
|
|
|
until not tew.lock
|
|
|
|
end
|
|
|
|
handleFuel(doFuelThing)
|
|
|
|
success, msg = turtle.up()
|
|
|
|
if success then
|
|
|
|
adjustCoords(-1,1)
|
|
|
|
--os.queueEvent("tew_move")
|
|
|
|
sendRequest()
|
|
|
|
else
|
|
|
|
return success, msg
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return true
|
|
|
|
end,
|
|
|
|
down = function(dist,doFuelThing)
|
|
|
|
local success, msg
|
|
|
|
for a = 1, dist or 1 do
|
|
|
|
if tew.lock then
|
|
|
|
repeat
|
|
|
|
sleep(0)
|
|
|
|
until not tew.lock
|
|
|
|
end
|
|
|
|
handleFuel(doFuelThing)
|
|
|
|
success, msg = turtle.down()
|
|
|
|
if success then
|
|
|
|
adjustCoords(-2,1)
|
|
|
|
--os.queueEvent("tew_move")
|
|
|
|
sendRequest()
|
|
|
|
else
|
|
|
|
return success, msg
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return true
|
|
|
|
end,
|
|
|
|
turnRight = function(times,doFuelThing)
|
|
|
|
handleFuel(doFuelThing)
|
|
|
|
for a = 1, times or 1 do
|
|
|
|
if tew.lock then
|
|
|
|
repeat
|
|
|
|
sleep(0)
|
|
|
|
until not tew.lock
|
|
|
|
end
|
|
|
|
turtle.turnRight()
|
|
|
|
tew.direction = dro(tew.direction+1)
|
|
|
|
tps(true)
|
|
|
|
end
|
|
|
|
return true
|
|
|
|
end,
|
|
|
|
turnLeft = function(times,doFuelThing)
|
|
|
|
handleFuel(doFuelThing)
|
|
|
|
for a = 1, times or 1 do
|
|
|
|
if tew.lock then
|
|
|
|
repeat
|
|
|
|
sleep(0)
|
|
|
|
until not tew.lock
|
|
|
|
end
|
|
|
|
turtle.turnRight()
|
|
|
|
tew.direction = dro(tew.direction+1)
|
|
|
|
tps(true)
|
|
|
|
end
|
|
|
|
return true
|
|
|
|
end,
|
|
|
|
turn = function(dir)
|
|
|
|
if dir == tew.direction then
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
repeat
|
|
|
|
tew.turnRight()
|
|
|
|
until tew.direction == dir
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
}
|
|
|
|
|
|
|
|
tps = function( doWrite )
|
|
|
|
if doWrite then
|
|
|
|
local file = fs.open(cfilename,"w")
|
|
|
|
file.write(tew.x.."\n"..tew.y.."\n"..tew.z.."\n"..tew.direction.."\n"..chestX.."\n"..chestY.."\n"..chestZ)
|
|
|
|
file.close()
|
|
|
|
else
|
|
|
|
if not fs.exists(cfilename) then
|
|
|
|
tps(true)
|
|
|
|
end
|
|
|
|
local file = fs.open(cfilename,"r")
|
|
|
|
tew.x = tonumber(file.readLine())
|
|
|
|
tew.y = tonumber(file.readLine())
|
|
|
|
tew.z = tonumber(file.readLine())
|
|
|
|
tew.direction = tonumber(file.readLine())
|
|
|
|
chestX = tonumber(file.readLine())
|
|
|
|
chestY = tonumber(file.readLine())
|
|
|
|
chestZ = tonumber(file.readLine())
|
|
|
|
file.close()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
tps(false)
|
|
|
|
tew.lock = true
|
|
|
|
|
|
|
|
local doTurtleMove = function()
|
|
|
|
while true do
|
|
|
|
tew.forward( 1,true)
|
|
|
|
tew.turnRight( 1,true)
|
|
|
|
tew.forward( 1,true)
|
|
|
|
tew.up( 1,true)
|
|
|
|
tew.turnRight( 1,true)
|
|
|
|
tew.forward( 1,true)
|
|
|
|
tew.turnRight( 1,true)
|
|
|
|
tew.forward( 1,true)
|
|
|
|
tew.down( 1,true)
|
|
|
|
tew.turnRight( 1,true)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local handleRequests = function() --also handles manual exit
|
|
|
|
local evt, side, chan, repchan, message, distance
|
|
|
|
while true do
|
|
|
|
evt, side, chan, repchan, message, distance = os.pullEvent()
|
|
|
|
if evt == "modem_message" then
|
|
|
|
if (chan == gps.CHANNEL_GPS) and (message == "PING") then
|
|
|
|
dudes[repchan] = 4
|
|
|
|
--os.queueEvent("tew_receive")
|
|
|
|
sendRequest()
|
|
|
|
end
|
|
|
|
elseif evt == "key" then
|
|
|
|
if side == keys.x then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local getEvents = function(...)
|
|
|
|
local evt
|
|
|
|
while true do
|
|
|
|
evt = {os.pullEvent()}
|
|
|
|
for a = 1, #arg do
|
|
|
|
if arg[a] == evt[1] then
|
|
|
|
return unpack(evt)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local colClearLine = function(col,y,char)
|
|
|
|
local cbg,ctxt,cx,cy = term.getBackgroundColor(), term.getTextColor(), term.getCursorPos()
|
|
|
|
local scr_x,scr_y = term.getSize()
|
|
|
|
term.setCursorPos(1,y or cy)
|
|
|
|
term.setBackgroundColor(col or cbg)
|
|
|
|
term.write((char or " "):rep(scr_x))
|
|
|
|
term.setBackgroundColor(cbg)
|
|
|
|
term.setTextColor(ctxt)
|
|
|
|
term.setCursorPos(cx,cy)
|
|
|
|
end
|
|
|
|
|
|
|
|
local prettyPrint = function(left,right)
|
|
|
|
local ctxt = term.getTextColor()
|
|
|
|
term.setTextColor(term.isColor() and colors.yellow or colors.lightGray)
|
|
|
|
write(left)
|
|
|
|
term.setTextColor(ctxt)
|
|
|
|
print(right)
|
|
|
|
end
|
|
|
|
|
|
|
|
local displayData = function()
|
|
|
|
while true do
|
|
|
|
term.clear()
|
|
|
|
term.setCursorPos(1,1)
|
|
|
|
colClearLine(colors.gray)
|
|
|
|
prettyPrint("\nFuel: ",turtle.getFuelLevel())
|
|
|
|
prettyPrint("X/Y/Z: ",tew.x.."/"..tew.y.."/"..tew.z)
|
|
|
|
prettyPrint("Direction: ",tew.direction.." ("..directionNames[tew.direction]..")")
|
|
|
|
prettyPrint("Requests: ",requests)
|
|
|
|
colClearLine(colors.gray)
|
|
|
|
print("\nPress 'X' to exit.")
|
|
|
|
sleep(0)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local displayHelp = function()
|
|
|
|
local data = [[
|
|
|
|
Turtle GPS System (TPS)
|
|
|
|
by LDDestroier/EldidiStroyrr
|
|
|
|
Place a chest down, and fill it with fuel.
|
|
|
|
Place the turtle down (you did), and specify its own coordinates ('1') and the chest coordinates ('2').
|
|
|
|
Start!]]
|
|
|
|
print(data)
|
|
|
|
sleep(0.1)
|
|
|
|
os.pullEvent("key")
|
|
|
|
end
|
|
|
|
|
|
|
|
local okaythen = false
|
|
|
|
while not okaythen do
|
|
|
|
term.clear()
|
|
|
|
term.setCursorPos(1,1)
|
|
|
|
print()
|
|
|
|
print("Push '1' to change coordinates...")
|
|
|
|
print("Push '2' to change chest coordinates...")
|
|
|
|
print("Push 'X' to cancel...")
|
|
|
|
print("Push 'Spacebar' to start immediately...")
|
|
|
|
local _x,_y = term.getCursorPos()
|
|
|
|
local buttmode = 0
|
|
|
|
local res = parallel.waitForAny(
|
|
|
|
function()
|
|
|
|
while true do
|
|
|
|
local _,char = os.pullEvent("char")
|
|
|
|
if char:lower() == "1" then
|
|
|
|
buttmode = 1
|
|
|
|
return
|
|
|
|
elseif char:lower() == "2" then
|
|
|
|
buttmode = 2
|
|
|
|
return
|
|
|
|
elseif char:lower() == " " then
|
|
|
|
okaythen = true
|
|
|
|
return
|
|
|
|
elseif char:lower() == "x" then
|
|
|
|
buttmode = -1
|
|
|
|
return
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end,
|
|
|
|
function()
|
|
|
|
for a = 1, 3*10 do
|
|
|
|
term.setCursorPos(_x,_y)
|
|
|
|
term.write("Starting in "..(3-(a/10)).." seconds...")
|
|
|
|
sleep(0.1)
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
if res == 1 then
|
|
|
|
term.clear()
|
|
|
|
term.setCursorPos(1,1)
|
|
|
|
if buttmode == 1 then
|
|
|
|
print("Turtle position input.")
|
|
|
|
colClearLine(colors.white)
|
|
|
|
write("\nX: ")
|
|
|
|
tew.x = tonumber(read()) or tew.x
|
|
|
|
write("Y: ")
|
|
|
|
tew.y = tonumber(read()) or tew.y
|
|
|
|
write("Z: ")
|
|
|
|
tew.z = tonumber(read()) or tew.z
|
|
|
|
print("Direction (F3 -> 'f'): ")
|
|
|
|
for k,v in pairs(directionNames) do
|
|
|
|
print(" "..k.." = '"..v.."'")
|
|
|
|
end
|
|
|
|
write(">")
|
|
|
|
tew.direction = tonumber(read()) or tew.direction
|
|
|
|
tps(true)
|
|
|
|
elseif buttmode == 2 then
|
|
|
|
print("Refuel Chest input.")
|
|
|
|
colClearLine(colors.white)
|
|
|
|
write("\nChest X: ")
|
|
|
|
chestX = tonumber(read()) or chestX
|
|
|
|
write("Chest Y: ")
|
|
|
|
chestY = tonumber(read()) or chestY
|
|
|
|
write("Chest Z: ")
|
|
|
|
chestZ = tonumber(read()) or chestZ
|
|
|
|
tps(true)
|
|
|
|
elseif buttmode == -1 then
|
|
|
|
print("Cancelled.")
|
|
|
|
error()
|
|
|
|
end
|
|
|
|
else
|
|
|
|
okaythen = true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
parallel.waitForAny(
|
|
|
|
handleRequests,
|
|
|
|
doTurtleMove,
|
|
|
|
displayData
|
|
|
|
)
|
|
|
|
|
|
|
|
term.setCursorPos(1, scr_y-2)
|
|
|
|
print("Thank you for using TPS!")
|
|
|
|
sleep(0)
|