mirror of
https://github.com/osmarks/random-stuff
synced 2024-12-29 11:30:35 +00:00
105 lines
2.6 KiB
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)
|