blunty666

remoteMap

Dec 21st, 2015
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 5.17 KB | None | 0 0
  1. local REDNET_TIMEOUT = 1
  2.  
  3. local MESSAGE_TYPE = {
  4.     GET = 0,
  5.     SET = 1,
  6. }
  7.  
  8. local function newMessage(messageType, grid, data)
  9.     return {
  10.         type = messageType,
  11.         ID = math.random(0, 2^30),
  12.         grid = grid,
  13.         data = data,
  14.     }
  15. end
  16.  
  17. local function sendAndWaitForResponse(recipientID, message, protocol)
  18.     rednet.send(recipientID, message, protocol)
  19.     local attemptNumber = 1
  20.     while true do
  21.         local senderID, reply = rednet.receive(protocol, REDNET_TIMEOUT)
  22.         if senderID == recipientID and type(reply) == "table" and reply.type == message.type and reply.ID == message.ID then
  23.             return reply.data
  24.         elseif not senderID then
  25.             if attemptNumber < 3 then
  26.                 rednet.send(recipientID, message, protocol)
  27.                 attemptNumber = attemptNumber + 1
  28.             else
  29.                 return false
  30.             end
  31.         end
  32.     end
  33. end
  34.  
  35. local function isValidValue(value)
  36.     return value == nil or value == -1 or value == 1
  37. end
  38.  
  39. local function toGridCode(tVector)
  40.     return math.floor(tVector.x/16), math.floor(tVector.y/16), math.floor(tVector.z/16), tVector.x % 16, tVector.y % 16, tVector.z % 16
  41. end
  42.  
  43. local function getRemoteGrid(tMap, x, y, z)
  44.     if not tMap.remoteGrids[x] or not tMap.remoteGrids[x][y] or not tMap.remoteGrids[x][y][z] then
  45.         local message = newMessage(MESSAGE_TYPE.GET, {x, y, z}, nil)
  46.         local remoteGrid = sendAndWaitForResponse(tMap.serverID, message, tMap.protocol) or {}
  47.         tMap.remoteGridsAge[x..","..y..","..z] = os.clock()
  48.         if not tMap.remoteGrids[x] then
  49.             tMap.remoteGrids[x] = {}
  50.         end
  51.         if not tMap.remoteGrids[x][y] then
  52.             tMap.remoteGrids[x][y] = {}
  53.         end
  54.         tMap.remoteGrids[x][y][z] = remoteGrid
  55.         return remoteGrid
  56.     else
  57.         return tMap.remoteGrids[x][y][z]
  58.     end
  59. end
  60.  
  61. local function getUpdateGrid(tMap, x, y, z)
  62.     if not tMap.updateGrids[x] or not tMap.updateGrids[x][y] or not tMap.updateGrids[x][y][z] then
  63.         local updateGrid = {}
  64.         if not tMap.updateGrids[x] then
  65.             tMap.updateGrids[x] = {}
  66.         end
  67.         if not tMap.updateGrids[x][y] then
  68.             tMap.updateGrids[x][y] = {}
  69.         end
  70.         tMap.updateGrids[x][y][z] = updateGrid
  71.         return updateGrid
  72.     else
  73.         return tMap.updateGrids[x][y][z]
  74.     end
  75. end
  76.  
  77. local remoteMapMethods = {
  78.     get = function(self, coord)
  79.         local gX, gY, gZ, pX, pY, pZ = toGridCode(coord)
  80.         local grid = getRemoteGrid(self, gX, gY, gZ)
  81.         if grid[pX] and grid[pX][pY] then
  82.             return grid[pX][pY][pZ]
  83.         end
  84.     end,
  85.  
  86.     set = function(self, coord, value)
  87.         if not isValidValue(value) then
  88.             --should we throw an error or use a default value?
  89.             error("remoteMap set: value is not valid", 2)
  90.         end
  91.         local gX, gY, gZ, pX, pY, pZ = toGridCode(coord)
  92.         local grid = getUpdateGrid(self, gX, gY, gZ)
  93.         if not grid[pX] then
  94.             grid[pX] = {}
  95.         end
  96.         if not grid[pX][pY] then
  97.             grid[pX][pY] = {}
  98.         end
  99.         grid[pX][pY][pZ] = value
  100.     end,
  101.  
  102.     check = function(self)
  103.         local time = os.clock()
  104.         local newRemoteGridsAge = {}
  105.         for gridCode, gridAge in pairs(self.remoteGridsAge) do
  106.             if time - gridAge >= self.timeout then
  107.                 local x, y, z = string.match(gridCode, "([-]?%d+),([-]?%d+),([-]?%d+)")
  108.                 x, y, z = tonumber(x), tonumber(y), tonumber(z)
  109.                 if x and y and z then
  110.                     if self.remoteGrids[x] and self.remoteGrids[x][y] then
  111.                         self.remoteGrids[x][y][z] = nil
  112.                     end
  113.                 end
  114.             else
  115.                 newRemoteGridsAge[gridCode] = gridAge
  116.             end
  117.         end
  118.         local newUpdateGridsAge = {}
  119.         for gridCode, gridAge in pairs(self.updateGridsAge) do
  120.             if time - gridAge >= self.timeout then
  121.                 -- remove grid from updateGrids ???
  122.             else
  123.                 newUpdateGridsAge[gridCode] = gridAge
  124.             end
  125.         end
  126.         self.remoteGridsAge = newRemoteGridsAge
  127.         self.updateGridsAge = newUpdateGridsAge
  128.     end,
  129.  
  130.     pushUpdates = function(self, ignoreTimeout)
  131.         local newUpdateGrids = {}
  132.         for gX, YZmap in pairs(self.updateGrids) do
  133.             newUpdateGrids[gX] = {}
  134.             for gY, Zmap in pairs(YZmap) do
  135.                 newUpdateGrids[gX][gY] = {}
  136.                 for gZ, grid in pairs(Zmap) do
  137.                     local gridCode = gX..","..gY..","..gZ
  138.                     if next(grid) then
  139.                         if ignoreTimeout == true or (not self.updateGridsAge[gridCode]) or os.clock() - self.updateGridsAge[gridCode] >= self.timeout then
  140.                             local message = newMessage(MESSAGE_TYPE.SET, {gX, gY, gZ}, grid)
  141.                             local response = sendAndWaitForResponse(self.serverID, message, self.protocol)
  142.                             if response == true then
  143.                                 self.updateGridsAge[gridCode] = os.clock()
  144.                             else
  145.                                 newUpdateGrids[gX][gY][gZ] = grid
  146.                             end
  147.                         else
  148.                             newUpdateGrids[gX][gY][gZ] = grid
  149.                         end
  150.                     end
  151.                 end
  152.             end
  153.         end
  154.         self.updateGrids = newUpdateGrids
  155.     end,
  156. }
  157. local remoteMapMetatable = {__index = remoteMapMethods}
  158.  
  159. function new(mapName, timeout)
  160.     if type(mapName) ~= "string" then
  161.         error("mapName must be string")
  162.     end
  163.     if type(timeout) ~= "number" or timeout < 0 then
  164.         error("timeout must be positive number")
  165.     end
  166.    
  167.     local protocol = "map_share:"..mapName
  168.    
  169.     local serverID = rednet.lookup(protocol, "SERVER")
  170.     if not serverID then
  171.         error("could not find map share server")
  172.     end
  173.    
  174.     local remoteMap = {
  175.         mapName = mapName,
  176.         protocol = protocol,
  177.         serverID = serverID,
  178.         timeout = timeout,
  179.         remoteGrids = {},
  180.         remoteGridsAge = {},
  181.         updateGrids = {},
  182.         updateGridsAge = {},
  183.     }
  184.     return setmetatable(remoteMap, remoteMapMetatable)
  185. end
Add Comment
Please, Sign In to add comment