summaryrefslogtreecommitdiff
path: root/utils.lua
blob: b6a7ef9c9fc941a9e07fb7d29be003a1809af8e2 (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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
-- misc. utilities

-- returns a list of directions to where this cell in a structure is at the structure border.
-- returns an empty list for inner nodes
-- horizontal_only restricts search to only the horizontal plane (no y)
function cellworld.get_border_sides(rel_pos, str_size, horizontal_only)
	local borders = {}
	
	if rel_pos.z == str_size.z-1 then
		borders[#borders+1] = cellworld.NORTH
	end
	if rel_pos.x == str_size.x-1 then
		borders[#borders+1] = cellworld.EAST
	end
	
	if rel_pos.z == 0 then
		borders[#borders+1] = cellworld.SOUTH
	end
	if rel_pos.x == 0 then
		borders[#borders+1] = cellworld.WEST
	end
	
	if not horizontal_only then
		if rel_pos.y == str_size.y-1 then
			borders[#borders+1] = cellworld.UP
		end
		if rel_pos.y == 0 then
			borders[#borders+1] = cellworld.DOWN
		end
	end
	
	return borders
	
end

cellworld.opposite_directions = {
	[cellworld.EAST] = cellworld.WEST,
	[cellworld.WEST] = cellworld.EAST,
	[cellworld.NORTH]= cellworld.SOUTH,
	[cellworld.SOUTH]= cellworld.NORTH,
	[cellworld.UP]   = cellworld.DOWN,
	[cellworld.DOWN] = cellworld.UP,
}

cellworld.direction_to_vector = {
	[cellworld.EAST] = vector.new(1,0,0),
	[cellworld.WEST] = vector.new(-1,0,0),
	[cellworld.NORTH]= vector.new(0,0,1),
	[cellworld.SOUTH]= vector.new(0,0,-1),
	[cellworld.UP]   = vector.new(0,1,0),
	[cellworld.DOWN] = vector.new(0,-1,0),
}

-- quickly hash a position. Only suitable for relative positions, limited to a range of 0..255 each coordinate
function cellworld.small_pos_hash(x,y,z)
	return y*65536 + x*256 + z
end

-- returns the relative structure cell definition
function cellworld.get_structure_cell(struct, relpos)
	if struct.cells then
		local pstr = relpos.x.."|"..relpos.y.."|"..relpos.z
		if struct.cells[pstr] then
			return struct.cells[pstr]
		end
	end
	return struct.cell
end

cellworld.pcgrandom = PcgRandom(os.time())

function cellworld.random(min, max)
	return cellworld.pcgrandom:next(min,max)
end

-- returns random element from the list
function cellworld.select_random_element(list)
	local r = cellworld.random(1, #list)
	return list[r]
end

-- returns a for iterator that iterates from 'from' to 'to' integers but in random order
function iterate_random_order(from, to)
	local list = {}
	for i=from,to do
		list[#list+1] = i
	end
	return function()
		if #list==0 then return nil end
		local r = cellworld.random(1, #list)
		return table.remove(list, r)
	end
end

function cellworld.v_decompose(vec)
	return vec.x, vec.y, vec.z
end

-- convert back and forth
function cellworld.world_to_cell_pos(wpos)
	if not cellworld.grid_size then
		error("Grid size hasn't been configured yet, is a structure set loaded?")
	end
	return vector.new(
		math.floor(wpos.x / cellworld.grid_size),
		math.floor(wpos.y / cellworld.grid_size),
		math.floor(wpos.z / cellworld.grid_size)
	)
end

-- upper: output the upper corner of the cell
function cellworld.cell_to_world_pos(cpos, upper)
	if not cellworld.grid_size then
		error("Grid size hasn't been configured yet, is a structure set loaded?")
	end
	local wi=0
	if upper then
		wi = cellworld.grid_size-1
	end
	return vector.new(
		cpos.x * cellworld.grid_size + wi,
		cpos.y * cellworld.grid_size + wi,
		cpos.z * cellworld.grid_size + wi
	)
end