ldd-CC/tps.lua

573 lines
12 KiB
Lua

--[[
Turtle Positioning System
Use two turtles as an expensive and crappy GPS server! Use ALL the fuel!
wget https://raw.githubusercontent.com/LDDestroier/CC/master/tps.lua
std ld tps tps.lua
--]]
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)