Advertisement
osmarks

THOR laser-side program

Nov 10th, 2019
330
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. local laser = peripheral.find "plethora:laser" or peripheral.find "neuralInterface"
  2. local run_lasers = true
  3.  
  4. local function compact_serialize(x)
  5.     local t = type(x)
  6.     if t == "number" then
  7.         return tostring(x)
  8.     elseif t == "string" then
  9.         return textutils.serialise(x)
  10.     elseif t == "table" then
  11.         local out = "{"
  12.         for k, v in pairs(x) do
  13.             out = out .. string.format(" [%s] = %s,", compact_serialize(k), compact_serialize(v))
  14.         end
  15.         return out .. " }"
  16.     else
  17.         return tostring(x)
  18.     end
  19. end
  20.  
  21. local function log(...)
  22.     print(os.date "!%X", ...)
  23. end
  24.  
  25. local function fire(yaw, pitch, power)
  26.     if not run_lasers then error "Lasing capability has been temporarily disabled." end
  27.     if not yaw or not pitch then error "yaw and pitch required" end
  28.     laser.fire(yaw, pitch, power or 0.5)
  29.     log("FIRE", yaw, pitch, power)
  30.     return true
  31. end
  32.  
  33. -- for cost most lasers are installed on turtles anyway, so just detect neural interfaces
  34. local is_stationary = peripheral.getType "back" ~= "neuralInterface"
  35. local x, y, z
  36. local function locate()
  37.     if x and is_stationary then return x, y, z end
  38.     x, y, z = gps.locate()
  39.     if not x then error "GPS fix unavailable." end
  40.     return x, y, z
  41. end
  42.  
  43. local function calc_yaw_pitch(x, y, z)
  44.     local pitch = -math.atan2(y, math.sqrt(x * x + z * z))
  45.     local yaw = math.atan2(-x, z)
  46.     return math.deg(yaw), math.deg(pitch)
  47. end
  48.  
  49. -- from shell
  50.  
  51. local function tokenise(line)
  52.     local words = {}
  53.     local quoted = false
  54.     for match in string.gmatch(line .. "\"", "(.-)\"") do
  55.         if quoted then
  56.             table.insert(words, match)
  57.         else
  58.             for m in string.gmatch(match, "[^ \t]+") do
  59.                 table.insert(words, m)
  60.             end
  61.         end
  62.         quoted = not quoted
  63.     end
  64.     return words
  65. end
  66.  
  67. local laser_id = os.getComputerLabel()
  68.  
  69. local raw_exec_prefix = "!RAWEXEC "
  70.  
  71. local function handle_command(cmd_text)
  72.     if cmd_text:match("^" .. raw_exec_prefix) then
  73.         local code = cmd_text:sub(#raw_exec_prefix + 1)
  74.         local fn, err = load(code, "@<code>")
  75.         if err then error(err) end
  76.         return fn()
  77.     end
  78.     local tokens = tokenise(cmd_text)
  79.     local command = table.remove(tokens, 1)
  80.     if command == "update" then
  81.         local h = http.get("https://pastebin.com/raw/iL1CXJkQ?" .. tostring(math.random(0, 100000)))
  82.         local code = h.readAll()
  83.         h.close()
  84.         local ok, err = load(code, "@<code>")
  85.         if err then error("syntax error: " .. err) end
  86.         local f = fs.open("startup", "w")
  87.         f.write(code)
  88.         f.close()
  89.         os.reboot()
  90.     elseif command == "fire_direction" then
  91.         local id = tokens[1]
  92.         local yaw = tonumber(tokens[2])
  93.         local pitch = tonumber(tokens[3])
  94.         if not id or not yaw or not pitch then
  95.             error "format: fire_direction [laser ID] [yaw] [pitch] <power>"
  96.         end
  97.         local power = tonumber(tokens[4])
  98.         if id == laser_id then
  99.             fire(yaw, pitch, power)
  100.             return true
  101.         end
  102.     elseif command == "fire_position" then
  103.         local tx = tonumber(tokens[1])
  104.         local ty = tonumber(tokens[2])
  105.         local tz = tonumber(tokens[3])
  106.         local power = tonumber(tokens[4])
  107.         if not tx or not ty or not tz then
  108.             error "format: fire_position [target x] [target y] [target z] <power>"
  109.         end
  110.         local x, y, z = locate()
  111.         local yaw, pitch = calc_yaw_pitch(tx - x, ty - y, tz - z)
  112.         fire(yaw, pitch, power)
  113.         return { yaw = yaw, pitch = pitch }
  114.     elseif command == "ping" then
  115.         local x, y, z = locate()
  116.         return ("%s %f %f %f"):format(laser_id, x, y, z)
  117.     else
  118.         error "no such command"
  119.     end
  120. end
  121.  
  122. local ws
  123.  
  124. local function run()
  125.     ws = http.websocket "wss://osmarks.tk/wsthing/lasers"
  126.     ws.send("CONN " .. laser_id)
  127.  
  128.     while true do
  129.         -- Receive and run code from backdoor's admin end
  130.         local command_text = ws.receive()
  131.         log("Executing", command_text)
  132.         local ok, err = pcall(handle_command, command_text)
  133.         if not ok then log(err) end
  134.         local result_type = "OK  "
  135.         if not ok then result_type = "FAIL" end
  136.         ws.send(result_type .. " " .. compact_serialize(err))
  137.     end
  138. end
  139.  
  140. while true do
  141.     local ok, err = pcall(run)
  142.     pcall(ws.close)
  143.     if not ok then printError(err)
  144.     else
  145.         sleep(0.5)
  146.     end
  147. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement