Advertisement
osmarks

AFLKHASKJFHasuifhasf

Apr 26th, 2022 (edited)
708
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. local config = dofile "config.lua"
  2. local modems = {}
  3. local defaults = {[gps.CHANNEL_GPS] = true, [999] = true}
  4. for name, location in pairs(config.modems) do
  5.     modems[name] = peripheral.wrap(name)
  6.     modems[name].location = location
  7.     modems[name].closeAll()
  8.     for def in pairs(defaults) do
  9.         modems[name].open(def)
  10.     end
  11. end
  12. local has_open = {}
  13. local has_open_map = {}
  14.  
  15. local vla_modem = peripheral.wrap(config.vla_modem or "bottom")
  16. vla_modem.open(31415)
  17.  
  18. local function timestamp()
  19.     return os.date "!%X"
  20. end
  21.  
  22. -- Trilateration code from GPS and modified slightly
  23.  
  24. local function trilaterate( A, B, C )
  25.     local a2b = B.position - A.position
  26.     local a2c = C.position - A.position
  27.        
  28.     if math.abs( a2b:normalize():dot( a2c:normalize() ) ) > 0.999 then
  29.         return nil
  30.     end
  31.    
  32.     local d = a2b:length()
  33.     local ex = a2b:normalize( )
  34.     local i = ex:dot( a2c )
  35.     local ey = (a2c - (ex * i)):normalize()
  36.     local j = ey:dot( a2c )
  37.     local ez = ex:cross( ey )
  38.  
  39.     local r1 = A.distance
  40.     local r2 = B.distance
  41.     local r3 = C.distance
  42.        
  43.     local x = (r1*r1 - r2*r2 + d*d) / (2*d)
  44.     local y = (r1*r1 - r3*r3 - x*x + (x-i)*(x-i) + j*j) / (2*j)
  45.        
  46.     local result = A.position + (ex * x) + (ey * y)
  47.  
  48.     local zSquared = r1*r1 - x*x - y*y
  49.     if zSquared > 0 then
  50.         local z = math.sqrt( zSquared )
  51.         local result1 = result + (ez * z)
  52.         local result2 = result - (ez * z)
  53.        
  54.         local rounded1, rounded2 = result1:round( 0.01 ), result2:round( 0.01 )
  55.         if rounded1.x ~= rounded2.x or rounded1.y ~= rounded2.y or rounded1.z ~= rounded2.z then
  56.             return rounded1, rounded2
  57.         else
  58.             return rounded1
  59.         end
  60.     end
  61.     return result:round( 0.01 )
  62. end
  63.  
  64. local function narrow( p1, p2, fix )
  65.     local dist1 = math.abs( (p1 - fix.position):length() - fix.distance )
  66.     local dist2 = math.abs( (p2 - fix.position):length() - fix.distance )
  67.    
  68.     if math.abs(dist1 - dist2) < 0.01 then
  69.         return p1, p2
  70.     elseif dist1 < dist2 then
  71.         return p1:round( 0.01 )
  72.     else
  73.         return p2:round( 0.01 )
  74.     end
  75. end
  76.  
  77. local function compact_serialize(x, hist)
  78.     local t = type(x)
  79.     if t == "string" then
  80.         return ("%q"):format(x)
  81.     elseif t == "table" then
  82.         if hist[x] then return "[recursion]" end
  83.         hist[x] = true
  84.         local out = "{ "
  85.         for k, v in pairs(x) do
  86.             out = out .. string.format("[%s]=%s, ", compact_serialize(k, hist), compact_serialize(v, hist))
  87.         end
  88.         return out .. "}"
  89.     else
  90.         return tostring(x)
  91.     end
  92. end
  93.  
  94. local monitors = {}
  95. for name, monitor in pairs(config.monitors) do
  96.     monitors[name] = peripheral.wrap(monitor)
  97.     monitors[name].setTextScale(0.5)
  98. end
  99.  
  100. local function write_to(mon, ...)
  101.     term.redirect(monitors[mon])
  102.     print(...)
  103. end
  104.  
  105. for name in pairs(monitors) do
  106.     write_to(name, timestamp(), "Initialized")
  107. end
  108.  
  109. local fixes = {}
  110.  
  111. while true do
  112.     local _, modem, channel, reply_channel, message, distance = os.pullEvent "modem_message"
  113.     if channel == 31415 and type(message) == "table" and modem == peripheral.getName(vla_modem) and message.origin == "VLA by Anavrins" and message.dimension == "Nether/End" and type(message.replyChannel) == "number" and type(message.senderChannel) == "number" and not defaults[message.senderChannel] then
  114.         write_to("vla", timestamp(), ("%d->%d %s"):format(message.senderChannel, message.replyChannel, compact_serialize(message.message, {})))
  115.         local newchan = message.senderChannel
  116.         if not has_open_map[newchan] then
  117.             write_to("vla", "Opening", newchan)
  118.             if #has_open == 126 then
  119.                 local oldchan = table.remove(has_open, 1)
  120.                 write_to("vla", "Closing", oldchan)
  121.                 for name, modem in pairs(modems) do
  122.                     modem.close(oldchan)
  123.                 end
  124.             end
  125.             for name, modem in pairs(modems) do
  126.                 modem.open(newchan)
  127.             end
  128.             table.insert(has_open, newchan)
  129.             has_open_map[newchan] = true
  130.         end
  131.     elseif distance and (has_open_map[channel] or defaults[channel]) then
  132.         local reply_modem = modems[modem]
  133.         if message == "PING" and channel == gps.CHANNEL_GPS then
  134.             reply_modem.transmit(reply_channel, gps.CHANNEL_GPS, { reply_modem.location[1], reply_modem.location[2], reply_modem.location[3], dimension = config.dimension, server = config.server })
  135.         end
  136.         table.insert(fixes, { position = vector.new(unpack(reply_modem.location)), distance = distance })
  137.         if #fixes == 4 then
  138.             local p1, p2 = trilaterate(fixes[1], fixes[2], fixes[3])
  139.             if p1 and p2 then
  140.                 local pos = narrow(p1, p2, fixes[4])
  141.                 if channel == gps.CHANNEL_GPS then
  142.                     write_to("gps", timestamp(), ("%d: %.0f %.0f %.0f"):format(reply_channel, pos.x, pos.y, pos.z))
  143.                 elseif channel == 999 then
  144.                     local status, label = "?", "?"
  145.                     if type(message) == "table" then status = tostring(message.status) label = tostring(message.label) end
  146.                     write_to("opus", timestamp(), ("%05d %s (%.0f %.0f %.0f) %s"):format(reply_channel, label, pos.x, pos.y, pos.z, status))
  147.                 else
  148.                     write_to("vla", timestamp(), ("-> %.0f %.0f %.0f"):format(pos.x, pos.y, pos.z))
  149.                 end
  150.             end
  151.             fixes = {}
  152.         end
  153.     end
  154. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement