-- a Map is a 2d array of chunks -- it handles loading and unloading of chunks -- the specifics of which are then implemented separately for client and server -- it will probably also do things relating to entities and multiblock things local class = require"common.class" local chunk = require"common.chunk" local CHUNK_SIZE = require"common.constants".CHUNK_SIZE local Map = class() function Map.make(cls) return setmetatable({chunks={}},cls) end function Map.add_chunk(self,cp,the_chunk) print("adding chunk",cp) assert(the_chunk.cp == cp,"attempting to add chunk with the wrong cp") if not self.chunks[cp.u] then self.chunks[cp.u] = {} end self.chunks[cp.u][cp.v] = the_chunk end function Map.unload_chunk(self,cp) if not self.chunks[cp.u] then return end self.chunks[cp.u][cp.v] = nil -- remove list if empty if next(self.chunks[cp.u]) == nil then self.chunks[cp.u] = nil end end function Map.chunk(self,cp) -- return chunk at chunk coord cp -- if that chunk isn't loaded return nil return self:_chunkuv(cp.u,cp.v) end function Map._chunkuv(self,u,v) -- same as above but with numbers instead of objects -- to avoid allocations inside loop return self.chunks[u] and self.chunks[u][v] end function Map.at(self,hpos) -- returns tile at world coord hpos -- if that tile's containing chunk isn't loaded, return nil -- not using the methods for doing this, in order to avoid lots of allocations -- inside the main drawing loop local cpu,cpv = math.floor(hpos.q/CHUNK_SIZE),math.floor(hpos.r/CHUNK_SIZE) local hoffq,hoffr = hpos.q-(cpu*CHUNK_SIZE), hpos.r-(cpv*CHUNK_SIZE) local ch = self:_chunkuv(cpu,cpv) if ch == nil then return nil end return ch:_atqr(hoffq,hoffr) end function Map.set_at(self,hpos,tile) local cp,hoffs = hpos:chunk_and_offset() local ch = self:chunk(cp) -- setting a tile in an unloaded chunk is silently ignored -- this might change one day if ch == nil then return nil end ch:set_at(hoffs,tile) end return {Map=Map}