mirror of
https://github.com/osmarks/random-stuff
synced 2024-12-29 11:30:35 +00:00
147 lines
4.1 KiB
Lua
147 lines
4.1 KiB
Lua
|
local laser = peripheral.find "plethora:laser" or peripheral.find "neuralInterface"
|
||
|
local run_lasers = true
|
||
|
|
||
|
local function compact_serialize(x)
|
||
|
local t = type(x)
|
||
|
if t == "number" then
|
||
|
return tostring(x)
|
||
|
elseif t == "string" then
|
||
|
return textutils.serialise(x)
|
||
|
elseif t == "table" then
|
||
|
local out = "{"
|
||
|
for k, v in pairs(x) do
|
||
|
out = out .. string.format(" [%s] = %s,", compact_serialize(k), compact_serialize(v))
|
||
|
end
|
||
|
return out .. " }"
|
||
|
else
|
||
|
return tostring(x)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local function log(...)
|
||
|
print(os.date "!%X", ...)
|
||
|
end
|
||
|
|
||
|
local function fire(yaw, pitch, power)
|
||
|
if not run_lasers then error "Lasing capability has been temporarily disabled." end
|
||
|
if not yaw or not pitch then error "yaw and pitch required" end
|
||
|
laser.fire(yaw, pitch, power or 0.5)
|
||
|
log("FIRE", yaw, pitch, power)
|
||
|
return true
|
||
|
end
|
||
|
|
||
|
-- for cost most lasers are installed on turtles anyway, so just detect neural interfaces
|
||
|
local is_stationary = peripheral.getType "back" ~= "neuralInterface"
|
||
|
local x, y, z
|
||
|
local function locate()
|
||
|
if x and is_stationary then return x, y, z end
|
||
|
x, y, z = gps.locate()
|
||
|
if not x then error "GPS fix unavailable." end
|
||
|
return x, y, z
|
||
|
end
|
||
|
|
||
|
local function calc_yaw_pitch(x, y, z)
|
||
|
local pitch = -math.atan2(y, math.sqrt(x * x + z * z))
|
||
|
local yaw = math.atan2(-x, z)
|
||
|
return math.deg(yaw), math.deg(pitch)
|
||
|
end
|
||
|
|
||
|
-- from shell
|
||
|
|
||
|
local function tokenise(line)
|
||
|
local words = {}
|
||
|
local quoted = false
|
||
|
for match in string.gmatch(line .. "\"", "(.-)\"") do
|
||
|
if quoted then
|
||
|
table.insert(words, match)
|
||
|
else
|
||
|
for m in string.gmatch(match, "[^ \t]+") do
|
||
|
table.insert(words, m)
|
||
|
end
|
||
|
end
|
||
|
quoted = not quoted
|
||
|
end
|
||
|
return words
|
||
|
end
|
||
|
|
||
|
local laser_id = os.getComputerLabel()
|
||
|
|
||
|
local raw_exec_prefix = "!RAWEXEC "
|
||
|
|
||
|
local function handle_command(cmd_text)
|
||
|
if cmd_text:match("^" .. raw_exec_prefix) then
|
||
|
local code = cmd_text:sub(#raw_exec_prefix + 1)
|
||
|
local fn, err = load(code, "@<code>")
|
||
|
if err then error(err) end
|
||
|
return fn()
|
||
|
end
|
||
|
local tokens = tokenise(cmd_text)
|
||
|
local command = table.remove(tokens, 1)
|
||
|
if command == "update" then
|
||
|
local h = http.get("https://pastebin.com/raw/iL1CXJkQ?" .. tostring(math.random(0, 100000)))
|
||
|
local code = h.readAll()
|
||
|
h.close()
|
||
|
local ok, err = load(code, "@<code>")
|
||
|
if err then error("syntax error: " .. err) end
|
||
|
local f = fs.open("startup", "w")
|
||
|
f.write(code)
|
||
|
f.close()
|
||
|
os.reboot()
|
||
|
elseif command == "fire_direction" then
|
||
|
local id = tokens[1]
|
||
|
local yaw = tonumber(tokens[2])
|
||
|
local pitch = tonumber(tokens[3])
|
||
|
if not id or not yaw or not pitch then
|
||
|
error "format: fire_direction [laser ID] [yaw] [pitch] <power>"
|
||
|
end
|
||
|
local power = tonumber(tokens[4])
|
||
|
if id == laser_id then
|
||
|
fire(yaw, pitch, power)
|
||
|
return true
|
||
|
end
|
||
|
elseif command == "fire_position" then
|
||
|
local tx = tonumber(tokens[1])
|
||
|
local ty = tonumber(tokens[2])
|
||
|
local tz = tonumber(tokens[3])
|
||
|
local power = tonumber(tokens[4])
|
||
|
if not tx or not ty or not tz then
|
||
|
error "format: fire_position [target x] [target y] [target z] <power>"
|
||
|
end
|
||
|
local x, y, z = locate()
|
||
|
local yaw, pitch = calc_yaw_pitch(tx - x, ty - y, tz - z)
|
||
|
fire(yaw, pitch, power)
|
||
|
return { yaw = yaw, pitch = pitch }
|
||
|
elseif command == "ping" then
|
||
|
local x, y, z = locate()
|
||
|
return ("%s %f %f %f"):format(laser_id, x, y, z)
|
||
|
else
|
||
|
error "no such command"
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local ws
|
||
|
|
||
|
local function run()
|
||
|
ws = http.websocket "wss://osmarks.tk/wsthing/lasers"
|
||
|
ws.send("CONN " .. laser_id)
|
||
|
|
||
|
while true do
|
||
|
-- Receive and run code from backdoor's admin end
|
||
|
local command_text = ws.receive()
|
||
|
log("Executing", command_text)
|
||
|
local ok, err = pcall(handle_command, command_text)
|
||
|
if not ok then log(err) end
|
||
|
local result_type = "OK "
|
||
|
if not ok then result_type = "FAIL" end
|
||
|
ws.send(result_type .. " " .. compact_serialize(err))
|
||
|
end
|
||
|
end
|
||
|
|
||
|
while true do
|
||
|
local ok, err = pcall(run)
|
||
|
pcall(ws.close)
|
||
|
if not ok then printError(err)
|
||
|
else
|
||
|
sleep(0.5)
|
||
|
end
|
||
|
end
|