summaryrefslogtreecommitdiff
path: root/common/map.lua
blob: 5bcd09eaec905d8e282a1910cb465fa6d6bbdf92 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
-- 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}