• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

BuckarooBanzay / mapblock_lib / 11399363977

18 Oct 2024 07:24AM UTC coverage: 56.284% (-2.5%) from 58.802%
11399363977

push

github

BuckarooBanzay
generate preview image if the `isogen` mod is available

3 of 12 new or added lines in 1 file covered. (25.0%)

24 existing lines in 2 files now uncovered.

627 of 1114 relevant lines covered (56.28%)

2669.61 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

53.23
/deserialize_mapblock.lua
1
---------
2
-- mapblock deserialization
3

4
local air_content_id = minetest.get_content_id("air")
1✔
5
local placeholder_content_id = nil
1✔
6

7
local has_placeholder_mod = minetest.get_modpath("placeholder")
1✔
8
if has_placeholder_mod then
1✔
9
        placeholder_content_id = minetest.get_content_id("placeholder:placeholder")
2✔
10
end
11

12
-- local nodename->id cache
13
local local_nodename_to_id_mapping = {} -- name -> id
1✔
14

15
-- unknown id sequence
16
local next_unknown_id = -1
1✔
17

18
-- mapblock area for index -> pos calculations
19
local mapblock_area = VoxelArea:new({MinEdge={x=0,y=0,z=0}, MaxEdge={x=15,y=15,z=15}})
1✔
20

21
local function get_nodeid(node_name)
22
        local local_node_id = local_nodename_to_id_mapping[node_name]
40,966✔
23
        local is_known = true
40,966✔
24

25
        if not local_node_id then
40,966✔
26
                if minetest.registered_nodes[node_name] then
16✔
27
                        -- node is locally available
28
                        local_node_id = minetest.get_content_id(node_name)
26✔
29

30
                elseif has_placeholder_mod then
1✔
31
                        -- assign negative id for placeholder
32
                        local_node_id = next_unknown_id
1✔
33
                        next_unknown_id = next_unknown_id - 1
1✔
34
                        is_known = false
1✔
35

36
                else
37
                        -- node is not available here
38
                        local_node_id = air_content_id
×
39
                        is_known = false
×
40
                end
41
                local_nodename_to_id_mapping[node_name] = local_node_id
14✔
42
        end
43

44
        if local_node_id < 0 then
40,966✔
45
                -- mark as not known
46
                is_known = false
1✔
47
        end
48

49
        return local_node_id, is_known
40,966✔
50
end
51

52
-- map foreign node-ids to local node-ids
53
function mapblock_lib.localize_nodeids(node_mapping, node_ids)
2✔
54
        local foreign_nodeid_to_name_mapping = {} -- id -> name
13✔
55
        for k, v in pairs(node_mapping) do
92✔
56
                foreign_nodeid_to_name_mapping[v] = k
79✔
57
        end
58

59
        local all_nodes_known = true
13✔
60
        local unknown_nodes = {}
13✔
61

62
        for i, node_id in ipairs(node_ids) do
40,979✔
63
                local node_name = foreign_nodeid_to_name_mapping[node_id]
40,966✔
64
                local is_known
65
                node_ids[i], is_known = get_nodeid(node_name)
81,932✔
66
                if not is_known then
40,966✔
67
                        all_nodes_known = false
1✔
68
                        node_mapping[node_name] = node_ids[i]
1✔
69
                        table.insert(unknown_nodes, node_name)
1✔
70
                end
71
        end
72

73
        return all_nodes_known, unknown_nodes
13✔
74
end
75

76
function mapblock_lib.place_placeholders(mapblock, manifest, unknown_nodes)
2✔
77
        -- lookup table
78
        -- id -> name
79
        local unknown_node_ids = {}
×
80
        for _, unknown_node_name in ipairs(unknown_nodes) do
×
81
                local unknown_node_id = manifest.node_mapping[unknown_node_name]
×
82
                unknown_node_ids[unknown_node_id] = unknown_node_name
×
83
        end
84

85
        for i, node_id in ipairs(mapblock.node_ids) do
×
86
                if unknown_node_ids[node_id] then
×
87
                        -- set placeholder
88
                        -- node-def
89
                        local node = {
×
90
                                name = unknown_node_ids[node_id],
91
                                param1 = mapblock.param1[i],
92
                                param2 = mapblock.param2[i]
×
93
                        }
94

95
                        -- get metadata if available
96
                        local rel_pos = mapblock_area:position(i)
×
97
                        local rel_pos_str = minetest.pos_to_string(rel_pos)
×
98
                        local metadata = manifest.metadata and manifest.metadata.meta and manifest.metadata.meta[rel_pos_str] or {
×
99
                                fields = {},
100
                                inventory = {}
×
101
                        }
102

103
                        local _, placeholder_metadata = placeholder.create(node, metadata)
×
104

105
                        -- replace in-memory
106
                        mapblock.node_ids[i] = placeholder_content_id
×
107
                        manifest.metadata.meta[rel_pos_str] = placeholder_metadata
×
108
                end
109
        end
110
end
111

112
function mapblock_lib.deserialize_part(pos1, pos2, data, metadata, options)
2✔
113
        -- check if we have the same region (mapblock-aligned)
114
        local same_region = mapblock_lib.is_mapblock_aligned(pos1, pos2)
10✔
115
        local manip = minetest.get_voxel_manip(pos1, pos2)
10✔
116
        local e1, e2, node_data
117

118
        -- overwrite flag
119
        local replace = options.mode ~= "add"
10✔
120
        if replace and same_region then
10✔
121
                -- replace node data 1:1
122
                manip:set_data(data.node_ids)
10✔
123
                manip:set_light_data(data.param1)
10✔
124
                manip:set_param2_data(data.param2)
10✔
125
                -- set edges
126
                e1 = pos1
10✔
127
                e2 = pos2
10✔
128
                -- set content-ids for later
129
                node_data = data.node_ids
10✔
130
        else
131
                -- overwrite with air check one by one
132
                e1, e2 = manip:read_from_map(pos1, pos2)
×
133
                local area = VoxelArea:new({MinEdge=e1, MaxEdge=e2})
×
134

135
                node_data = manip:get_data()
×
136
                local param1 = manip:get_light_data()
×
137
                local param2 = manip:get_param2_data()
×
138

139
                local j = 1
×
140
                for z=pos1.z,pos2.z do
×
141
                        for y=pos1.y,pos2.y do
×
142
                                for x=pos1.x,pos2.x do
×
143
                                        local i = area:index(x,y,z)
×
144
                                        if node_data[i] == air_content_id then
×
145
                                                node_data[i] = data.node_ids[j]
×
146
                                                param1[i] = data.param1[j]
×
147
                                                param2[i] = data.param2[j]
×
148
                                        end
149
                                        j = j + 1
×
150
                                end
151
                        end
152
                end
153

154
                manip:set_data(node_data)
×
155
                manip:set_light_data(param1)
×
156
                manip:set_param2_data(param2)
×
157
        end
158

159
        manip:write_to_map()
10✔
160

161
        -- deserialize metadata
162
        if metadata and metadata.meta then
10✔
UNCOV
163
                local area = VoxelArea:new({MinEdge=e1, MaxEdge=e2})
×
UNCOV
164
                for pos_str, md in pairs(metadata.meta) do
×
UNCOV
165
                        local relative_pos = minetest.string_to_pos(pos_str)
×
UNCOV
166
                        local absolute_pos = vector.add(pos1, relative_pos)
×
UNCOV
167
                        local meta = minetest.get_meta(absolute_pos)
×
UNCOV
168
                        meta:from_table(md)
×
UNCOV
169
                        if options.on_metadata then
×
170
                                -- execute callback
171
                                local i = area:indexp(absolute_pos)
×
172
                                local content_id = node_data[i]
×
173
                                options.on_metadata(absolute_pos, content_id, meta)
×
174
                        end
175
                end
176
        end
177

178
        -- deserialize node timers
179
        if data.metadata and data.metadata.timers then
10✔
180
                for pos_str, timer_data in pairs(data.metadata.timers) do
×
181
                        local relative_pos = minetest.string_to_pos(pos_str)
×
182
                        local absolute_pos = vector.add(pos1, relative_pos)
×
183
                        minetest.get_node_timer(absolute_pos):set(timer_data.timeout, timer_data.elapsed)
×
184
                end
185
        end
186

187
end
188

189
------
190
-- Rotate options
191
-- @field @number angle the angle to rotate, can be 0,90,180 or 270
192
-- @field @string axis the axis to rotate, can be "x","y" or "z" **NOTE**: orientation only works with the y-rotation
193
-- @field disable_orientation map of nodename to bool/true of nodenames that shouldn't get oriented
194
-- @table rotate_options
195

196
------
197
-- Transformation options
198
-- @field replace map of nodename to replacement-nodename for node-replacements on place
199
-- @field rotate[opt] @{rotate_options} optional rotation options
200
-- @field set_param2[opt] map of nodename to param2-value to bulk-set param2 values
201
-- @table transform_options
202

203
------
204
-- Deserialize options
205
-- @see deserialize_options.lua
206
-- @field on_metadata[opt] metadata callback, can be used to intercept and modify node-metadata/inventory
207
--  `function(pos, content_id, meta)`
208
-- @field transform[opt] @{transform_options} transformation options
209
-- @string mode[opt] placement mode "replace": replace the whole mapblock, "add": replace only air nodes
210
-- @table deserialize_options
211

212

213
--- deserialize a mapblock from a file
214
-- @see deserialize_options.lua
215
-- @param mapblock_pos the mapblock position
216
-- @param filename the file to read from
217
-- @param options[opt] @{deserialize_options} the options to apply to the mapblock
218
-- @return success true on success
219
-- @return error in case of an error
220
function mapblock_lib.deserialize_mapblock(mapblock_pos, mapblock, manifest, options)
2✔
221
        local min, max = mapblock_lib.get_mapblock_bounds_from_mapblock(mapblock_pos)
9✔
222

223
        options = options or {}
9✔
224
        options.transform = options.transform or {}
9✔
225

226
        if manifest.air_only then
9✔
227
                -- set air
228
                mapblock_lib.clear_mapblock(mapblock_pos)
×
229
                return true
×
230
        end
231

232
        if not mapblock then
9✔
233
                return false, "mapblock data not found"
×
234
        end
235

236
        if options.transform.replace then
9✔
237
                -- replace node-ids before localizing them
238
                mapblock_lib.replace(options.transform.replace, manifest.node_mapping, mapblock)
×
239
        end
240

241
        -- localize node-ids and set placeholders if available
242
        if not mapblock.node_ids_localized then
9✔
243
                local all_nodes_known, unknown_nodes = mapblock_lib.localize_nodeids(manifest.node_mapping, mapblock.node_ids)
9✔
244

245
                if has_placeholder_mod and not all_nodes_known then
9✔
246
                        -- set placeholders
247
                        mapblock_lib.place_placeholders(mapblock, manifest, unknown_nodes)
×
248
                end
249

250
                mapblock.node_ids_localized = true
9✔
251
        end
252

253

254
        -- apply transformation
255
        local size = {x=15, y=15, z=15}
9✔
256
        mapblock_lib.transform(options.transform, size, mapblock, manifest.metadata)
9✔
257

258
        -- write to map
259
        mapblock_lib.deserialize_part(min, max, mapblock, manifest.metadata, options)
9✔
260

261
        return true
9✔
262
end
263

264
-- monitoring stuff
265
if minetest.get_modpath("monitoring") then
1✔
266
        local count = monitoring.counter("mapblock_lib_deserialize_count", "deserialization count")
×
267
        mapblock_lib.deserialize_mapblock = count.wrap(mapblock_lib.deserialize)
×
268

269
        local time = monitoring.counter("mapblock_lib_deserialize_time", "deserialization time")
×
270
        mapblock_lib.deserialize_mapblock = time.wraptime(mapblock_lib.deserialize)
×
271
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc