random-stuff/computercraft/arc.lua

105 lines
2.6 KiB
Lua

--[[
ARC: AR Client
Uses Plethora overlay glasses and modems to display 3D signage transmitted from local "beacons"
]]
local m = peripheral.find "modem"
local mods = peripheral.wrap "back"
if not m then error "Modem required." end
if not mods then error "Is this even on a neural interface?" end
if not mods.canvas3d then error "Overlay glasses required." end
local canv = mods.canvas3d()
local object_channel = 666
m.open(object_channel)
local x, y, z
-- convert position to string for use as table key
local function serialize_position(p)
return string.format("%f,%f,%f", p[1], p[2], p[3])
end
-- Generate a string representation of a table, for easy comparison. Not really hashing, I guess.
local function hash_table(x)
if type(x) == "table" then
local out = ""
for k, v in pairs(x) do
if type(k) ~= "string" or not k:match "^_" then -- ignore keys beginning with _
out = out .. hash_table(k) .. ":" .. hash_table(v) .. ";"
end
end
return out
else
return tostring(x)
end
end
-- honestly not that elegant, but it works
-- TODO: do this more efficiently/nicely somehow?
local function tables_match(x, y)
return hash_table(x) == hash_table(y)
end
local objects = {}
local timers = {}
local function redraw(object)
local frame = object._frame
frame.clear()
end
local function process_object(object)
local pos = serialize_position(object.position)
if objects[pos] then
if not tables_match(object, objects[pos]) then
print("redrawing", pos)
objects[pos] = object
redraw(objects[pos])
end
local t = os.startTimer(20)
timers[t] = pos
else
print("new object at", pos)
if x then
local frame =
else
print("GPS error, cannot create object")
end
end
end
local function main_loop()
while true do
local event, timer, channel, reply_channel, message, distance = os.pullEvent()
if event == "modem_message" and channel == object_channel and distance and type(message) == "table" then -- ensure message is from this dimension and otherwise valid
for _, object in pairs(msg) do
local ok, err = pcall(process_object, object)
if not ok then printError(err) end
end
elseif event == "timer" then
local objpos = timers[timer]
if objpos then
local obj = objects[objpos]
if obj then
print(objpos, "timed out")
obj._frame.remove()
objects[objpos] = nil
end
end
end
end
end
-- Request location every second
local function GPS_loop()
while true do
x, y, z = gps.locate()
sleep(1)
end
end
parallel.waitForAll(GPS_loop, main_loop)