Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local BIT_MASKS = {
- SET_COORD = bit.blshift(1, 7),
- SET_X_COORD = bit.blshift(1, 6),
- COORD = 15,
- COORD_DATA = bit.blshift(7, 4),
- }
- local function isValidValue(value)
- return value == nil or (type(value) == "number" and value % 1 == 0 and value >= 0 and value <= 7)
- end
- local function toGridCode(tVector)
- 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
- end
- local function setGrid(tMap, x, y, z, grid)
- if not tMap.map[x] then
- tMap.map[x] = {}
- end
- if not tMap.map[x][y] then
- tMap.map[x][y] = {}
- end
- tMap.map[x][y][z] = grid
- return tMap.map[x][y][z]
- end
- local function getGrid(tMap, x, y, z)
- if not tMap.map[x] or not tMap.map[x][y] or not tMap.map[x][y][z] then
- return tMap:load(x, y, z)
- else
- return tMap.map[x][y][z]
- end
- end
- local mapMethods = {
- getGrid = function(self, tVector, y, z)
- local gX, gY, gZ
- if y and z then
- gX, gY, gZ = tVector, y, z
- else
- gX, gY, gZ = toGridCode(tVector)
- end
- return getGrid(self, gX, gY, gZ)
- end,
- load = function(self, tVector, y, z)
- local gX, gY, gZ
- if y and z then
- gX, gY, gZ = tVector, y, z
- else
- gX, gY, gZ = toGridCode(tVector)
- end
- local gridPath = fs.combine(self.mapDir, gX..","..gY..","..gZ)
- if fs.exists(gridPath) then
- local handle = fs.open(gridPath, "rb")
- if handle then
- local grid = {}
- --load grid data
- local currX, currY, currZ
- local dataByte = handle.read()
- while dataByte do
- if bit.band(dataByte, BIT_MASKS.SET_COORD) == BIT_MASKS.SET_COORD then
- --we are changing our currX or currY coord
- if bit.band(dataByte, BIT_MASKS.SET_X_COORD) == BIT_MASKS.SET_X_COORD then
- --we are changing our currX coord
- currX = bit.band(dataByte, BIT_MASKS.COORD)
- else
- --we are changing our currY coord
- currY = bit.band(dataByte, BIT_MASKS.COORD)
- end
- else
- --we are setting the value for a proper coord
- currZ = bit.band(dataByte, BIT_MASKS.COORD)
- if currX and currY and currZ then
- if not grid[currX] then
- grid[currX] = {}
- end
- if not grid[currX][currY] then
- grid[currX][currY] = {}
- end
- grid[currX][currY][currZ] = bit.brshift(bit.band(dataByte, BIT_MASKS.COORD_DATA), 4)
- end
- end
- dataByte = handle.read()
- end
- handle.close()
- return setGrid(self, gX, gY, gZ, grid)
- end
- end
- return setGrid(self, gX, gY, gZ, {})
- end,
- loadAll = function(self)
- if fs.exists(self.mapDir) and fs.isDir(self.mapDir) then
- for _, gridFile in ipairs(fs.list(self.mapDir)) do
- local _, _, gX, gY, gZ = string.find(gridFile, "(.+)%,(.+)%,(.+)")
- if gX and gY and gX then
- self:load(tonumber(gX), tonumber(gY), tonumber(gZ))
- end
- end
- end
- end,
- save = function(self, tVector, y, z)
- local gX, gY, gZ
- if y and z then
- gX, gY, gZ = tVector, y, z
- else
- gX, gY, gZ = toGridCode(tVector)
- end
- if self.map[gX] and self.map[gX][gY] and self.map[gX][gY][gZ] then
- local grid = self.map[gX][gY][gZ]
- if next(grid) then
- local handle = fs.open(fs.combine(self.mapDir, gX..","..gY..","..gZ), "wb")
- if handle then
- for x, gridYZ in pairs(grid) do
- handle.write(BIT_MASKS.SET_COORD + BIT_MASKS.SET_X_COORD + x)
- for y, gridZ in pairs(gridYZ) do
- handle.write(BIT_MASKS.SET_COORD + y)
- for z, coordValue in pairs(gridZ) do
- handle.write(bit.blshift(coordValue, 4) + z)
- end
- end
- end
- handle.close()
- end
- else
- fs.delete(fs.combine(self.mapDir, gX..","..gY..","..gZ))
- end
- end
- end,
- saveAll = function(self)
- for gX, YZmap in pairs(self.map) do
- for gY, Zmap in pairs(YZmap) do
- for gZ, grid in pairs(Zmap) do
- self:save(gX, gY, gZ)
- end
- end
- end
- end,
- get = function(self, tVector)
- local gX, gY, gZ, pX, pY, pZ = toGridCode(tVector)
- local grid = getGrid(self, gX, gY, gZ)
- if grid[pX] and grid[pX][pY] then
- return grid[pX][pY][pZ]
- end
- end,
- set = function(self, tVector, value)
- if not isValidValue(value) then
- --should we throw an error or use a default value?
- error("compactMap set: value is not valid", 2)
- end
- local gX, gY, gZ, pX, pY, pZ = toGridCode(tVector)
- local grid = getGrid(self, gX, gY, gZ)
- if not grid[pX] then
- grid[pX] = {}
- end
- if not grid[pX][pY] then
- grid[pX][pY] = {}
- end
- grid[pX][pY][pZ] = value
- return grid[pX][pY][pZ]
- end,
- getOrSet = function(self, tVector, value)
- local gX, gY, gZ, pX, pY, pZ = toGridCode(tVector)
- local grid = getGrid(self, gX, gY, gZ)
- if grid[pX] and grid[pX][pY] and grid[pX][pY][pZ] then
- return grid[pX][pY][pZ], false
- else
- if not isValidValue(value) then
- --should we throw an error or use a default value?
- error("compactMap getOrSet: value is not valid", 2)
- end
- if not grid[pX] then
- grid[pX] = {}
- end
- if not grid[pX][pY] then
- grid[pX][pY] = {}
- end
- grid[pX][pY][pZ] = value
- return grid[pX][pY][pZ], true
- end
- end,
- }
- local mapMetatable = {__index = mapMethods}
- function new(mapDir)
- local tMap = {}
- if type(mapDir) == "string" then
- if not fs.exists(mapDir) then
- fs.makeDir(mapDir)
- elseif not fs.isDir(mapDir) then
- error("compactMap new: not a valid directory", 2)
- end
- tMap.mapDir = mapDir
- else
- error("compactMap new: directory must be string", 2)
- end
- tMap.map = {}
- setmetatable(tMap, mapMetatable)
- return tMap
- end
Add Comment
Please, Sign In to add comment