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

blockexchange / blockexchange / 13331571900

14 Feb 2025 02:48PM UTC coverage: 52.251% (+0.4%) from 51.84%
13331571900

push

github

BuckarooBanzay
deduplicate schemapart code

12 of 13 new or added lines in 5 files covered. (92.31%)

48 existing lines in 8 files now uncovered.

975 of 1866 relevant lines covered (52.25%)

1898.59 hits per line

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

57.41
/commands/save.lua
1
local has_monitoring = minetest.get_modpath("monitoring")
1✔
2

3
local uploaded_blocks
4

5
if has_monitoring then
1✔
6
        uploaded_blocks = monitoring.counter(
×
7
                "blockexchange_uploaded_blocks",
8
                "number of successfully uploaded mapblocks"
9
        )
10
end
11

12
function blockexchange.save(playername, pos1, pos2, schemaname)
2✔
13
        pos1, pos2 = blockexchange.sort_pos(pos1, pos2)
2✔
14

15
        local token = blockexchange.get_token(playername)
1✔
16
        local claims = blockexchange.get_claims(playername)
1✔
17
        local license = blockexchange.get_license(playername)
1✔
18

19
        if not token or not claims then
1✔
20
                return Promise.rejected("not logged in")
×
21
        end
22

23
        local ctx = {
1✔
24
                hud_icon = "blockexchange_upload.png",
25
                hud_text = "Saving '" .. claims.username .. "/" .. schemaname .. "'"
1✔
26
        }
27

28
        local schema = {
1✔
29
                size_x = pos2.x - pos1.x + 1,
1✔
30
                size_y = pos2.y - pos1.y + 1,
1✔
31
                size_z = pos2.z - pos1.z + 1,
1✔
32
                description = "",
33
                license = license,
1✔
34
                name = schemaname
1✔
35
        }
36

37
        local total_size = 0
1✔
38
        local retries = 0
1✔
39
        local mod_names = {}
1✔
40
        local total_parts = 0
1✔
41

42
        local promise = Promise.async(function(await)
2✔
43
                local _, err
44
                schema, err = await(blockexchange.api.create_schema(token, schema))
3✔
45
                if err then
1✔
46
                        error("error creating schema: " .. err, 0)
×
47
                end
48

49
                for current_pos, relative_pos, progress in blockexchange.iterator(pos1, pos1, pos2) do
19✔
50
                        local current_pos2 = vector.add(current_pos, 15)
8✔
51
                        current_pos2.x = math.min(current_pos2.x, pos2.x)
8✔
52
                        current_pos2.y = math.min(current_pos2.y, pos2.y)
8✔
53
                        current_pos2.z = math.min(current_pos2.z, pos2.z)
8✔
54

55
                        local progress_percent = math.floor(progress * 100 * 10) / 10
8✔
56
                        ctx.hud_text = "Saving '" .. claims.username .. "/" .. schemaname ..
8✔
57
                                "', progress: " .. progress_percent .. " %"
8✔
58

59
                        local data, node_count, air_only = blockexchange.serialize_part(current_pos, current_pos2)
8✔
60
                        blockexchange.collect_node_count(node_count, mod_names)
8✔
61

62
                        if not air_only then
8✔
63
                                local schemapart = blockexchange.create_schemapart(data, relative_pos, schema.uid)
8✔
64

65
                                total_size = total_size + #schemapart.data + #schemapart.metadata
8✔
66
                                total_parts = total_parts + 1
8✔
67

68
                                while true do
69
                                        -- retry loop
70
                                        _, err = await(blockexchange.api.create_schemapart(token, schemapart))
24✔
71
                                        if err then
8✔
72
                                                if retries > 12 then
×
73
                                                        error("create schemapart failed after " .. retries .. " retries: " .. err, 0)
×
74
                                                end
75
                                                -- retry again later
76
                                                await(Promise.after(5))
×
77
                                                retries = retries + 1
×
78
                                        else
79
                                                -- saved successfully
80
                                                if has_monitoring then
8✔
81
                                                        uploaded_blocks.inc(1)
×
82
                                                end
83
                                                break
84
                                        end
85
                                end
86

87
                                -- TODO
88
                        end
89

90
                        if ctx.cancel then
8✔
91
                                error("canceled", 0)
×
92
                        end
93

94
                        await(Promise.after(blockexchange.min_delay))
16✔
95
                end
96

97
                -- create an array with mod names
98
                local mod_names_list = {}
1✔
99
                for k in pairs(mod_names) do
2✔
100
                        table.insert(mod_names_list, k)
1✔
101
                end
102

103
                _, err = await(blockexchange.api.create_schemamods(token, schema.uid, mod_names_list))
3✔
104
                if err then
1✔
105
                        error("error creating mod-list: " .. err, 0)
×
106
                end
107

108
                _, err = await(blockexchange.api.update_schema_stats(token, schema.uid))
3✔
109
                if err then
1✔
110
                        error("error updating stats: " .. err, 0)
×
111
                end
112

113
                -- get updated schema
114
                schema, err = await(blockexchange.api.get_schema_by_name(claims.username, schemaname))
3✔
115
                if err then
1✔
116
                        error("error fetching updated schema: " .. err, 0)
×
117
                elseif not schema then
1✔
118
                        error("saved schema not found: " .. claims.username .. "/" .. schemaname, 0)
×
119
                end
120

121
                -- register area
122
                blockexchange.register_area(pos1, pos2, playername, claims.username, schema)
1✔
123

124
                return {
1✔
125
                        total_parts = total_parts,
1✔
126
                        total_size = total_size,
1✔
127
                        schema = schema
1✔
128
                }
1✔
129
        end)
130

131
        blockexchange.set_job_context(playername, ctx, promise)
1✔
132
        return promise
1✔
133
end
134

135

136
Promise.register_chatcommand("bx_save", {
2✔
137
        params = "<name>",
138
        description = "Uploads the selected region to the blockexchange server",
139
        func = function(name, schemaname)
140
                if blockexchange.get_job_context(name) then
×
141
                        return true, "There is a job already running"
×
142
                end
143

144
                local has_protected_upload_priv = minetest.check_player_privs(name, { blockexchange_protected_upload = true })
×
145
                local has_blockexchange_priv = minetest.check_player_privs(name, { blockexchange = true })
×
146
                local has_protection_bypass_priv = minetest.check_player_privs(name, { protection_bypass = true })
×
147

148
                if not has_blockexchange_priv and not has_protected_upload_priv then
×
149
                        return true, "Required privs: 'blockexchange' or 'blockexchange_protected_upload'"
×
150
                end
151

152
                if not schemaname then
×
153
                        return true, "Usage: /bx_save <schemaname>"
×
154
                end
155

156
                if not blockexchange.validate_name(schemaname) then
×
157
                        return true, "schema name can only contain letters, numbers and a handful of special chars: - _ ."
×
158
                end
159

160
                local token = blockexchange.get_token(name)
×
161
                if not token then
×
162
                        -- TODO check validity
163
                        return true, "Please login first to upload a schematic"
×
164
                end
165

166
                local pos1 = blockexchange.get_pos(1, name)
×
167
                local pos2 = blockexchange.get_pos(2, name)
×
168

169
                if not pos1 or not pos2 then
×
170
                        return true, "you need to set /bx_pos1 and /bx_pos2 first!"
×
171
                end
172

173
                if not blockexchange.check_size(pos1, pos2) then
×
174
                        return true, "axis size limit of " .. blockexchange.max_size .. " nodes exceeded"
×
175
                end
176

UNCOV
177
                return Promise.async(function(await)
×
178
                        local err, result
UNCOV
179
                        if not has_blockexchange_priv and has_protected_upload_priv and not has_protection_bypass_priv then
×
180
                                -- check protection first
UNCOV
181
                                result, err = await(blockexchange.protectioncheck(name, pos1, pos2))
×
182
                                if err then
×
UNCOV
183
                                        error("protection check error: " .. err, 0)
×
184
                                elseif not result.success then
×
185
                                        local msg = "protection check failed between pos " .. minetest.pos_to_string(result.pos1) ..
×
186
                                                " and " .. minetest.pos_to_string(result.pos2)
×
187
                                        error(msg, 0)
×
188
                                end
189
                        end
190

UNCOV
191
                        result, err = await(blockexchange.save(name, pos1, pos2, schemaname))
×
UNCOV
192
                        if err then
×
UNCOV
193
                                error("save error: " .. err)
×
194
                        end
195

196
                        return "save complete with " .. result.total_parts .. " parts and " .. result.total_size .. " bytes"
×
197
                end)
198
        end
199
})
1✔
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

© 2026 Coveralls, Inc