-
Notifications
You must be signed in to change notification settings - Fork 1
/
functions.lua
158 lines (135 loc) · 4.32 KB
/
functions.lua
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
-- returns a list of backends available for that position
function mapsync.select_backends(mapblock_pos)
local backends = {}
for _, backend_def in pairs(mapsync.get_backends()) do
if backend_def.select(mapblock_pos) then
table.insert(backends, backend_def)
end
end
return backends
end
function mapsync.sort_pos(pos1, pos2)
pos1 = {x=pos1.x, y=pos1.y, z=pos1.z}
pos2 = {x=pos2.x, y=pos2.y, z=pos2.z}
if pos1.x > pos2.x then
pos2.x, pos1.x = pos1.x, pos2.x
end
if pos1.y > pos2.y then
pos2.y, pos1.y = pos1.y, pos2.y
end
if pos1.z > pos2.z then
pos2.z, pos1.z = pos1.z, pos2.z
end
return pos1, pos2
end
--- calculates the mapblock position from a node position
-- @param pos the node-position
-- @return the mapblock position
function mapsync.get_mapblock(pos)
return vector.floor( vector.divide(pos, 16) )
end
--- returns the chunk position from a node position
-- @param pos the node-position
-- @return the chunk position
function mapsync.get_chunkpos(pos)
local mapblock_pos = mapsync.get_mapblock(pos)
local aligned_mapblock_pos = vector.add(mapblock_pos, 2)
return vector.floor( vector.divide(aligned_mapblock_pos, 5) )
end
function mapsync.get_mapblock_bounds_from_chunk(chunk_pos)
local min = vector.subtract( vector.multiply(chunk_pos, 5), 2)
local max = vector.add(min, 4)
return min, max
end
function mapsync.get_node_bounds_from_mapblock(mapblock)
local min = vector.multiply(mapblock, 16)
local max = vector.add(min, 15)
return min, max
end
-- returns the mtime of the emerged chunk (mtime from manifest)
function mapsync.get_world_chunk_mtime(chunk_pos)
local mtime = mapsync.storage:get_int(minetest.pos_to_string(chunk_pos))
if mtime == 0 then
return nil
else
return mtime
end
end
-- returns the mtime of the backend chunk
function mapsync.get_backend_chunk_mtime(chunk_pos)
local backend_def = mapsync.select_backend(chunk_pos)
if not backend_def then
return
end
-- get manifest
local manifest = mapsync.get_manifest(mapsync.get_chunk_zip_path(backend_def.path, chunk_pos))
if not manifest then
return
end
-- retrieve timestamps
return manifest.mtime
end
-- deletes a chunk from the ingame map
function mapsync.delete_chunk(chunk_pos)
local mapblock_min, mapblock_max = mapsync.get_mapblock_bounds_from_chunk(chunk_pos)
local min = mapsync.get_node_bounds_from_mapblock(mapblock_min)
local _, max = mapsync.get_node_bounds_from_mapblock(mapblock_max)
mapsync.storage:set_string(minetest.pos_to_string(chunk_pos), "")
minetest.delete_area(min, max)
end
-- emerges a chunk
function mapsync.emerge_chunk(chunk_pos, callback)
local mapblock_min, mapblock_max = mapsync.get_mapblock_bounds_from_chunk(chunk_pos)
local min = mapsync.get_node_bounds_from_mapblock(mapblock_min)
local _, max = mapsync.get_node_bounds_from_mapblock(mapblock_max)
minetest.emerge_area(min, max, function(_, _, calls_remaining)
if calls_remaining == 0 and type(callback) == "function" then
callback()
end
end)
end
function mapsync.mapblock_index_to_pos(index)
index = index - 1
local y = index % 16
index = index - y
local z = math.floor(index / 256)
index = index - (z * 256)
local x = math.floor(index / 16)
return { x=x, y=y, z=z }
end
-- Source: https://gist.github.com/sapphyrus/fd9aeb871e3ce966cc4b0b969f62f539, license: MIT
function mapsync.deep_compare(tbl1, tbl2)
if tbl1 == tbl2 then
return true
elseif type(tbl1) == "table" and type(tbl2) == "table" then
for key1, value1 in pairs(tbl1) do
local value2 = tbl2[key1]
if value2 == nil then
-- avoid the type call for missing keys in tbl2 by directly comparing with nil
return false
elseif value1 ~= value2 then
if type(value1) == "table" and type(value2) == "table" then
if not mapsync.deep_compare(value1, value2) then
return false
end
else
return false
end
end
end
-- check for missing keys in tbl1
for key2, _ in pairs(tbl2) do
if tbl1[key2] == nil then
return false
end
end
return true
end
return false
end
function mapsync.get_chunk_json_path(prefix, chunk_pos)
return prefix .. "/chunk_" .. minetest.pos_to_string(chunk_pos) .. ".json"
end
function mapsync.get_chunk_zip_path(prefix, chunk_pos)
return prefix .. "/chunk_" .. minetest.pos_to_string(chunk_pos) .. ".zip"
end