2016-08-13 08:57:08 +01:00

156 lines
3.6 KiB
Lua

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, "r")
if handle then
local grid = handle.readAll()
handle.close()
grid = textutils.unserialise(grid)
if type(grid) == "table" then
return setGrid(self, gX, gY, gZ, grid)
end
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), "w")
if handle then
handle.write(textutils.serialise(grid))
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)
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 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("new: not a valid directory")
end
tMap.mapDir = mapDir
else
error("new: directory must be string")
end
tMap.map = {}
setmetatable(tMap, mapMetatable)
return tMap
end