-
Notifications
You must be signed in to change notification settings - Fork 1
/
serialize_chunk.lua
103 lines (85 loc) · 2.78 KB
/
serialize_chunk.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
local global_env = ...
-- local vars for faster access
local char, encode_uint16, insert = string.char, mapsync.encode_uint16, table.insert
function mapsync.serialize_chunk(chunk_pos, filename)
local chunk_empty = true
local blockdata_list = {}
local node_mapping = {}
-- collect all non-empty block-datas
local min, max = mapsync.get_mapblock_bounds_from_chunk(chunk_pos)
for x=min.x,max.x do
for y=min.y,max.y do
for z=min.z,max.z do
local mapblock_pos = {x=x, y=y, z=z}
local blockdata = mapsync.serialize_mapblock(mapblock_pos, node_mapping)
blockdata.rel_pos = vector.subtract(mapblock_pos, min)
if not blockdata.empty then
chunk_empty = false
insert(blockdata_list, blockdata)
end
end
end
end
if chunk_empty then
-- skip empty chunks
return true
end
local node_mapping_count = 0
for _ in pairs(node_mapping) do
node_mapping_count = node_mapping_count + 1
end
if node_mapping_count == 1 and node_mapping["air"] then
-- only light changed and just air, skip
return true
end
-- open zip for writing
local f = global_env.io.open(filename, "wb")
if not f then
return false, "could not open '" .. filename .. "'"
end
local zip = mtzip.zip(f)
-- marshal blockdata to export-entries
local mapdata = {}
-- node_ids
for _, blockdata in ipairs(blockdata_list) do
for i=1,#blockdata.node_ids do
insert(mapdata, encode_uint16(blockdata.node_ids[i]))
end
end
-- param1
for _, blockdata in ipairs(blockdata_list) do
for i=1,#blockdata.param1 do
insert(mapdata, char(blockdata.param1[i]))
end
end
-- param2
for _, blockdata in ipairs(blockdata_list) do
for i=1,#blockdata.param2 do
insert(mapdata, char(blockdata.param2[i]))
end
end
-- metadata / manifest
local manifest = {
-- nodename => node_id
node_mapping = node_mapping,
-- seconds utc
mtime = os.time(),
-- { pos1, pos2, ... }
block_pos = {},
-- mapsync version
mapsync_version = mapsync.version
}
local metadata = {}
for _, blockdata in ipairs(blockdata_list) do
insert(manifest.block_pos, blockdata.rel_pos)
if blockdata.has_metadata then
metadata[minetest.pos_to_string(blockdata.rel_pos)] = blockdata.metadata
end
end
zip:add("mapdata.bin", table.concat(mapdata))
zip:add("metadata.json", minetest.write_json(metadata))
zip:add("manifest.json", minetest.write_json(manifest))
zip:close()
f:close()
return true
end