Advertisement
kovakovi2000

CC: P++ GPPS Global Player Position System

Apr 9th, 2020
280
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.59 KB | None | 0 0
  1. os.loadAPI("rnc")
  2.  
  3. local function trilaterate( A, B, C )
  4.     local a2b = B.vPosition - A.vPosition
  5.     local a2c = C.vPosition - A.vPosition
  6.        
  7.     if math.abs( a2b:normalize():dot( a2c:normalize() ) ) > 0.999 then
  8.         return nil
  9.     end
  10.    
  11.     local d = a2b:length()
  12.     local ex = a2b:normalize( )
  13.     local i = ex:dot( a2c )
  14.     local ey = (a2c - (ex * i)):normalize()
  15.     local j = ey:dot( a2c )
  16.     local ez = ex:cross( ey )
  17.  
  18.     local r1 = A.nDistance
  19.     local r2 = B.nDistance
  20.     local r3 = C.nDistance
  21.        
  22.     local x = (r1*r1 - r2*r2 + d*d) / (2*d)
  23.     local y = (r1*r1 - r3*r3 - x*x + (x-i)*(x-i) + j*j) / (2*j)
  24.        
  25.     local result = A.vPosition + (ex * x) + (ey * y)
  26.  
  27.     local zSquared = r1*r1 - x*x - y*y
  28.     if zSquared > 0 then
  29.         local z = math.sqrt( zSquared )
  30.         local result1 = result + (ez * z)
  31.         local result2 = result - (ez * z)
  32.        
  33.         local rounded1, rounded2 = result1:round( 0.01 ), result2:round( 0.01 )
  34.         if rounded1.x ~= rounded2.x or rounded1.y ~= rounded2.y or rounded1.z ~= rounded2.z then
  35.             return rounded1, rounded2
  36.         else
  37.             return rounded1
  38.         end
  39.     end
  40.     return result:round( 0.01 )
  41.    
  42. end
  43.  
  44. local function narrow( p1, p2, fix )
  45.     local dist1 = math.abs( (p1 - fix.vPosition):length() - fix.nDistance )
  46.     local dist2 = math.abs( (p2 - fix.vPosition):length() - fix.nDistance )
  47.    
  48.     if math.abs(dist1 - dist2) < 0.01 then
  49.         return p1, p2
  50.     elseif dist1 < dist2 then
  51.         return p1:round( 0.01 )
  52.     else
  53.         return p2:round( 0.01 )
  54.     end
  55. end
  56.  
  57. function locate(_sName, _nTimeout, _bDebug )
  58.     if _nTimeout ~= nil and type( _nTimeout ) ~= "number" then
  59.         error( "bad argument #1 (expected number, got " .. type( _nTimeout ) .. ")", 2 )
  60.     end
  61.     if _bDebug ~= nil and type( _bDebug ) ~= "boolean" then
  62.         error( "bad argument #2 (expected boolean, got " .. type( _bDebug) .. ")", 2 )
  63.     end
  64.     -- Let command computers use their magic fourth-wall-breaking special abilities
  65.     if commands then
  66.         return commands.getBlockPosition()
  67.     end
  68.  
  69.     -- Find a modem
  70.     local sModemSide = nil
  71.     for n,sSide in ipairs( rs.getSides() ) do
  72.         if peripheral.getType( sSide ) == "modem" and peripheral.call( sSide, "isWireless" ) then  
  73.             sModemSide = sSide
  74.             break
  75.         end
  76.     end
  77.  
  78.     if sModemSide == nil then
  79.         if _bDebug then
  80.             print( "No wireless modem attached" )
  81.         end
  82.         return nil
  83.     end
  84.    
  85.     if _bDebug then
  86.         print( "Finding position..." )
  87.     end
  88.    
  89.     -- Open a channel
  90.     local modem = peripheral.wrap( sModemSide )
  91.     local bCloseChannel = false
  92.     if not modem.isOpen( os.getComputerID() ) then
  93.         modem.open( os.getComputerID() )
  94.         bCloseChannel = true
  95.     end
  96.    
  97.     -- Send a ping to listening GPS hosts
  98.     local msg = {}
  99.     msg.type = "PING"
  100.     msg.name = _sName
  101.    
  102.     rnc.setPort(65500)
  103.     rnc.setIdenty(45)
  104.     rnc.send(msg)
  105.    
  106.     -- Wait for the responses
  107.     local tFixes = {}
  108.     local pos1, pos2 = nil, nil
  109.     while true do
  110.         rnc.setPort(65500)
  111.         rnc.setIdenty(46)
  112.         rnc.setTimeOut(_nTimeout or 2)
  113.         tMessage = rnc.resive()
  114.         if tMessage ~= nil then
  115.             local tFix = { vPosition = vector.new( tMessage[1], tMessage[2], tMessage[3] ), nDistance = tMessage[4] }
  116.             if tFix.nDistance == nil then
  117.                 print( "No player founded" )
  118.                 return
  119.             end
  120.             if _bDebug then
  121.                 print( tFix.nDistance.." metres from "..tostring( tFix.vPosition ) )
  122.             end
  123.             if tFix.nDistance == 0 then
  124.                 pos1, pos2 = tFix.vPosition, nil
  125.             else
  126.                 table.insert( tFixes, tFix )
  127.                 if #tFixes >= 3 then
  128.                     if not pos1 then
  129.                         pos1, pos2 = trilaterate( tFixes[1], tFixes[2], tFixes[#tFixes] )
  130.                     else
  131.                         pos1, pos2 = narrow( pos1, pos2, tFixes[#tFixes] )
  132.                     end
  133.                 end
  134.             end
  135.             if pos1 and not pos2 then
  136.                 break
  137.             end
  138.         else
  139.             break
  140.         end
  141.     end
  142.    
  143.     -- Close the channel, if we opened one
  144.     if bCloseChannel then
  145.         modem.close( os.getComputerID() )
  146.     end
  147.    
  148.     -- Return the response
  149.     if pos1 and pos2 then
  150.         if _bDebug then
  151.             print( "Ambiguous position" )
  152.             print( "Could be "..pos1.x..","..pos1.y..","..pos1.z.." or "..pos2.x..","..pos2.y..","..pos2.z )
  153.         end
  154.         return nil
  155.     elseif pos1 then
  156.         if _bDebug then
  157.             print( "Position is "..pos1.x..","..pos1.y..","..pos1.z )
  158.         end
  159.         return pos1.x, pos1.y, pos1.z
  160.     else
  161.         if _bDebug then
  162.             print( "Could not determine position" )
  163.         end
  164.         return nil
  165.     end
  166. end
  167.  
  168. local function printUsage()
  169.     print( "Usages:" )
  170.     print( "gpps host" )
  171.     print( "gpps host <x> <y> <z> <player name>" )
  172.     print( "gpps locate" )
  173.     print( "gpps.locate(<player name>)" )
  174. end
  175.  
  176. local tArgs = { ... }
  177. if #tArgs < 1 then
  178.     return
  179. end
  180.  
  181. playerSensor = peripheral.find("playerSensor")
  182.  
  183. local function GetDistanceByName(name)
  184.     p = playerSensor.getNearbyPlayers(2147483647)
  185.    
  186.     length = table.getn(p)
  187.     for i=1, length do
  188.         if p[i].player == name then
  189.             return p[i].distance
  190.         end
  191.     end
  192.     return nil
  193. end
  194.  
  195. local function readNumber()
  196.     local num = nil
  197.     while num == nil do
  198.         num = tonumber(read())
  199.         if not num then
  200.             write( "Not a number. Try again: " )
  201.         end
  202.     end
  203.     return math.floor( num + 0.5 )
  204. end
  205.  
  206. local function open()
  207.     local bOpen, sFreeSide = false, nil
  208.     for n,sSide in pairs(rs.getSides()) do 
  209.         if peripheral.getType( sSide ) == "modem" then
  210.             sFreeSide = sSide
  211.             if rednet.isOpen( sSide ) then
  212.                 bOpen = true
  213.                 break
  214.             end
  215.         end
  216.     end
  217.    
  218.     if not bOpen then
  219.         if sFreeSide then
  220.             print( "No modem active. Opening "..sFreeSide.." modem" )
  221.             rednet.open( sFreeSide )
  222.             return true
  223.         else
  224.             print( "No modem attached" )
  225.             return false
  226.         end
  227.     end
  228.     return true
  229. end
  230.    
  231. local sCommand = tArgs[1]
  232. if sCommand == "locate" then
  233.     if open() then
  234.         gps.locate( 2, true, tArgs[5] )
  235.     end
  236.    
  237. elseif sCommand == "host" then
  238.     if turtle then
  239.         print( "Turtles cannot act as GPS hosts." )
  240.         return
  241.     end
  242.  
  243.     if open() then
  244.         local x,y,z
  245.         if #tArgs >= 4 then
  246.             x = tonumber(tArgs[2])
  247.             y = tonumber(tArgs[3])
  248.             z = tonumber(tArgs[4])
  249.             if x == nil or y == nil or z == nil then
  250.                 printUsage()
  251.                 return
  252.             end
  253.             print( "Position is "..x..","..y..","..z )
  254.         else
  255.             x,y,z = gps.locate( 2, true )
  256.             if x == nil then
  257.                 print( "Run \"gps host <x> <y> <z>\" to set position manually" )
  258.                 return
  259.             end
  260.         end
  261.    
  262.         print( "Serving GPPS requests" )
  263.    
  264.         local nServed = 0
  265.         while true do
  266.             rnc.setPort(65500)
  267.             rnc.setIdenty(45)
  268.             msg = rnc.resive()
  269.             if msg ~= nil then
  270.                 if msg.type == "PING" then
  271.                     rnc.setPort(65500)
  272.                     rnc.setIdenty(46)
  273.                     rnc.send( {x,y,z,GetDistanceByName(msg.name)} )
  274.                    
  275.                     nServed = nServed + 1
  276.                     if nServed > 1 then
  277.                         local x,y = term.getCursorPos()
  278.                         term.setCursorPos(1,y-1)
  279.                     end
  280.                     print( nServed.." GPPS Requests served" )
  281.                 end
  282.             end
  283.         end
  284.     end
  285.    
  286. else
  287.     printUsage()
  288.     return
  289. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement