blunty666

compactMap

Feb 9th, 2016
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 5.51 KB | None | 0 0
  1. local BIT_MASKS = {
  2.     SET_COORD = bit.blshift(1, 7),
  3.     SET_X_COORD = bit.blshift(1, 6),
  4.     COORD = 15,
  5.     COORD_DATA = bit.blshift(7, 4),
  6. }
  7.  
  8. local function isValidValue(value)
  9.     return value == nil or (type(value) == "number" and value % 1 == 0 and value >= 0 and value <= 7)
  10. end
  11.  
  12. local function toGridCode(tVector)
  13.     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
  14. end
  15.  
  16. local function setGrid(tMap, x, y, z, grid)
  17.     if not tMap.map[x] then
  18.         tMap.map[x] = {}
  19.     end
  20.     if not tMap.map[x][y] then
  21.         tMap.map[x][y] = {}
  22.     end
  23.     tMap.map[x][y][z] = grid
  24.     return tMap.map[x][y][z]
  25. end
  26.  
  27. local function getGrid(tMap, x, y, z)
  28.     if not tMap.map[x] or not tMap.map[x][y] or not tMap.map[x][y][z] then
  29.         return tMap:load(x, y, z)
  30.     else
  31.         return tMap.map[x][y][z]
  32.     end
  33. end
  34.  
  35. local mapMethods = {
  36.  
  37.     getGrid = function(self, tVector, y, z)
  38.         local gX, gY, gZ
  39.         if y and z then
  40.             gX, gY, gZ = tVector, y, z
  41.         else
  42.             gX, gY, gZ = toGridCode(tVector)
  43.         end
  44.         return getGrid(self, gX, gY, gZ)
  45.     end,
  46.  
  47.     load = function(self, tVector, y, z)
  48.         local gX, gY, gZ
  49.         if y and z then
  50.             gX, gY, gZ = tVector, y, z
  51.         else
  52.             gX, gY, gZ = toGridCode(tVector)
  53.         end
  54.         local gridPath = fs.combine(self.mapDir, gX..","..gY..","..gZ)
  55.         if fs.exists(gridPath) then
  56.             local handle = fs.open(gridPath, "rb")
  57.             if handle then
  58.                 local grid = {}
  59.                
  60.                 --load grid data
  61.                 local currX, currY, currZ
  62.                 local dataByte = handle.read()
  63.                 while dataByte do
  64.                     if bit.band(dataByte, BIT_MASKS.SET_COORD) == BIT_MASKS.SET_COORD then
  65.                         --we are changing our currX or currY coord
  66.                         if bit.band(dataByte, BIT_MASKS.SET_X_COORD) == BIT_MASKS.SET_X_COORD then
  67.                             --we are changing our currX coord
  68.                             currX = bit.band(dataByte, BIT_MASKS.COORD)
  69.                         else
  70.                             --we are changing our currY coord
  71.                             currY = bit.band(dataByte, BIT_MASKS.COORD)
  72.                         end
  73.                     else
  74.                         --we are setting the value for a proper coord
  75.                         currZ = bit.band(dataByte, BIT_MASKS.COORD)
  76.                         if currX and currY and currZ then
  77.                             if not grid[currX] then
  78.                                 grid[currX] = {}
  79.                             end
  80.                             if not grid[currX][currY] then
  81.                                 grid[currX][currY] = {}
  82.                             end
  83.                             grid[currX][currY][currZ] = bit.brshift(bit.band(dataByte, BIT_MASKS.COORD_DATA), 4)
  84.                         end
  85.                     end
  86.                     dataByte = handle.read()
  87.                 end
  88.                 handle.close()
  89.                 return setGrid(self, gX, gY, gZ, grid)
  90.             end
  91.         end
  92.         return setGrid(self, gX, gY, gZ, {})
  93.     end,
  94.  
  95.     loadAll = function(self)
  96.         if fs.exists(self.mapDir) and fs.isDir(self.mapDir) then
  97.             for _, gridFile in ipairs(fs.list(self.mapDir)) do
  98.                 local _, _, gX, gY, gZ = string.find(gridFile, "(.+)%,(.+)%,(.+)")
  99.                 if gX and gY and gX then
  100.                     self:load(tonumber(gX), tonumber(gY), tonumber(gZ))
  101.                 end
  102.             end
  103.         end
  104.     end,
  105.  
  106.     save = function(self, tVector, y, z)
  107.         local gX, gY, gZ
  108.         if y and z then
  109.             gX, gY, gZ = tVector, y, z
  110.         else
  111.             gX, gY, gZ = toGridCode(tVector)
  112.         end
  113.         if self.map[gX] and self.map[gX][gY] and self.map[gX][gY][gZ] then
  114.             local grid = self.map[gX][gY][gZ]
  115.             if next(grid) then
  116.                 local handle = fs.open(fs.combine(self.mapDir, gX..","..gY..","..gZ), "wb")
  117.                 if handle then
  118.                     for x, gridYZ in pairs(grid) do
  119.                         handle.write(BIT_MASKS.SET_COORD + BIT_MASKS.SET_X_COORD + x)
  120.                         for y, gridZ in pairs(gridYZ) do
  121.                             handle.write(BIT_MASKS.SET_COORD + y)
  122.                             for z, coordValue in pairs(gridZ) do
  123.                                 handle.write(bit.blshift(coordValue, 4) + z)
  124.                             end
  125.                         end
  126.                     end
  127.                     handle.close()
  128.                 end
  129.             else
  130.                 fs.delete(fs.combine(self.mapDir, gX..","..gY..","..gZ))
  131.             end
  132.         end
  133.     end,
  134.    
  135.     saveAll = function(self)
  136.         for gX, YZmap in pairs(self.map) do
  137.             for gY, Zmap in pairs(YZmap) do
  138.                 for gZ, grid in pairs(Zmap) do
  139.                     self:save(gX, gY, gZ)
  140.                 end
  141.             end
  142.         end
  143.     end,
  144.  
  145.     get = function(self, tVector)
  146.         local gX, gY, gZ, pX, pY, pZ = toGridCode(tVector)
  147.         local grid = getGrid(self, gX, gY, gZ)
  148.         if grid[pX] and grid[pX][pY] then
  149.             return grid[pX][pY][pZ]
  150.         end
  151.     end,
  152.  
  153.     set = function(self, tVector, value)
  154.         if not isValidValue(value) then
  155.             --should we throw an error or use a default value?
  156.             error("compactMap set: value is not valid", 2)
  157.         end
  158.         local gX, gY, gZ, pX, pY, pZ = toGridCode(tVector)
  159.         local grid = getGrid(self, gX, gY, gZ)
  160.         if not grid[pX] then
  161.             grid[pX] = {}
  162.         end
  163.         if not grid[pX][pY] then
  164.             grid[pX][pY] = {}
  165.         end
  166.         grid[pX][pY][pZ] = value
  167.         return grid[pX][pY][pZ]
  168.     end,
  169.  
  170.     getOrSet = function(self, tVector, value)
  171.         local gX, gY, gZ, pX, pY, pZ = toGridCode(tVector)
  172.         local grid = getGrid(self, gX, gY, gZ)
  173.         if grid[pX] and grid[pX][pY] and grid[pX][pY][pZ] then
  174.             return grid[pX][pY][pZ], false
  175.         else
  176.             if not isValidValue(value) then
  177.                 --should we throw an error or use a default value?
  178.                 error("compactMap getOrSet: value is not valid", 2)
  179.             end
  180.             if not grid[pX] then
  181.                 grid[pX] = {}
  182.             end
  183.             if not grid[pX][pY] then
  184.                 grid[pX][pY] = {}
  185.             end
  186.             grid[pX][pY][pZ] = value
  187.             return grid[pX][pY][pZ], true
  188.         end
  189.     end,
  190.  
  191. }
  192. local mapMetatable = {__index = mapMethods}
  193.  
  194. function new(mapDir)
  195.     local tMap = {}
  196.     if type(mapDir) == "string" then
  197.         if not fs.exists(mapDir) then
  198.             fs.makeDir(mapDir)
  199.         elseif not fs.isDir(mapDir) then
  200.             error("compactMap new: not a valid directory", 2)
  201.         end
  202.         tMap.mapDir = mapDir
  203.     else
  204.         error("compactMap new: directory must be string", 2)
  205.     end
  206.     tMap.map = {}
  207.     setmetatable(tMap, mapMetatable)
  208.     return tMap
  209. end
Add Comment
Please, Sign In to add comment