SHOW:
|
|
- or go back to the newest paste.
| 1 | - | local function safe_serialize(data) |
| 1 | + | local laser = peripheral.find "plethora:laser" or peripheral.find "neuralInterface" |
| 2 | - | local ok, res = pcall(textutils.serialise, data) |
| 2 | + | local run_lasers = true |
| 3 | - | if ok then return res |
| 3 | + | |
| 4 | - | else return textutils.serialise(tostring(data)) end |
| 4 | + | local function compact_serialize(x) |
| 5 | local t = type(x) | |
| 6 | if t == "number" then | |
| 7 | - | local function websocket_backdoor() |
| 7 | + | return tostring(x) |
| 8 | - | if not http or not http.websocket then return "Websockets do not actually exist on this platform" end |
| 8 | + | elseif t == "string" then |
| 9 | - | |
| 9 | + | return textutils.serialise(x) |
| 10 | - | local ws = http.websocket "wss://osmarks.tk/wsthing/ShutdownOS" |
| 10 | + | elseif t == "table" then |
| 11 | - | |
| 11 | + | local out = "{"
|
| 12 | - | local function send(msg) |
| 12 | + | for k, v in pairs(x) do |
| 13 | - | ws.send(safe_serialize(msg)) |
| 13 | + | out = out .. string.format(" [%s] = %s,", compact_serialize(k), compact_serialize(v))
|
| 14 | end | |
| 15 | - | |
| 15 | + | return out .. " }" |
| 16 | - | local function recv() |
| 16 | + | else |
| 17 | - | return ws.receive() |
| 17 | + | return tostring(x) |
| 18 | end | |
| 19 | - | |
| 19 | + | |
| 20 | ||
| 21 | local function log(...) | |
| 22 | - | local code = recv() |
| 22 | + | print(os.date "!%X", ...) |
| 23 | - | local f, error = load(code, "@<backdoor>", "t") |
| 23 | + | |
| 24 | - | if f then -- run safely in background, send back response |
| 24 | + | |
| 25 | - | send {pcall(f)}
|
| 25 | + | local function fire(yaw, pitch, power) |
| 26 | if not run_lasers then error "Lasing capability has been temporarily disabled." end | |
| 27 | - | send {false, error}
|
| 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 |