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

blockexchange / blockexchange / 13327716991

14 Feb 2025 10:53AM UTC coverage: 50.79% (+2.4%) from 48.384%
13327716991

push

github

web-flow
refactor to async/await (#74)

237 of 556 new or added lines in 15 files covered. (42.63%)

5 existing lines in 4 files now uncovered.

964 of 1898 relevant lines covered (50.79%)

1870.06 hits per line

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

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

3
local uploaded_blocks
4

5
if has_monitoring then
1✔
NEW
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✔
NEW
20
                return Promise.rejected("not logged in")
×
21
        end
22

23
        local ctx = {
1✔
24
                type = "upload",
25
                playername = playername,
1✔
26
                username = claims.username,
1✔
27
                schemaname = schemaname,
1✔
28
                progress_percent = 0,
NEW
29
                retries = 0
×
30
        }
31

32
        local schema = {
1✔
33
                size_x = pos2.x - pos1.x + 1,
1✔
34
                size_y = pos2.y - pos1.y + 1,
1✔
35
                size_z = pos2.z - pos1.z + 1,
1✔
36
                description = "",
37
                license = license,
1✔
38
                name = schemaname
1✔
39
        }
40

41
        local total_size = 0
1✔
42
        local mod_names = {}
1✔
43
        local total_parts = 0
1✔
44

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

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

58
                        ctx.progress_percent = math.floor(progress * 100 * 10) / 10
8✔
59

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

63
                        if not air_only then
8✔
64
                                local schemapart = {
8✔
65
                                        schema_uid = schema.uid,
8✔
66
                                        offset_x = relative_pos.x,
8✔
67
                                        offset_y = relative_pos.y,
8✔
68
                                        offset_z = relative_pos.z,
8✔
69
                                        data = minetest.encode_base64(blockexchange.compress_data(data)),
16✔
70
                                        metadata = minetest.encode_base64(blockexchange.compress_metadata(data))
16✔
71
                                }
72

73
                                total_size = total_size + #schemapart.data + #schemapart.metadata
8✔
74
                                total_parts = total_parts + 1
8✔
75

76
                                while true do
77
                                        -- retry loop
78
                                        _, err = await(blockexchange.api.create_schemapart(token, schemapart))
24✔
79
                                        if err then
8✔
NEW
80
                                                if ctx.retries > 12 then
×
NEW
81
                                                        error("create schemapart failed after " .. ctx.retries .. " retries: " .. err, 0)
×
82
                                                end
83
                                                -- retry again later
NEW
84
                                                await(Promise.after(5))
×
NEW
85
                                                ctx.retries = ctx.retries + 1
×
86
                                        else
87
                                                -- saved successfully
88
                                                if has_monitoring then
8✔
NEW
89
                                                        uploaded_blocks.inc(1)
×
90
                                                end
91
                                                break
92
                                        end
93
                                end
94

95
                                -- TODO
96
                        end
97

98
                        if ctx.cancel then
8✔
NEW
99
                                error("canceled", 0)
×
100
                        end
101

102
                        await(Promise.after(blockexchange.min_delay))
16✔
103
                end
104

105
                -- create an array with mod names
106
                local mod_names_list = {}
1✔
107
                for k in pairs(mod_names) do
2✔
108
                        table.insert(mod_names_list, k)
1✔
109
                end
110

111
                _, err = await(blockexchange.api.create_schemamods(token, schema.uid, mod_names_list))
3✔
112
                if err then
1✔
NEW
113
                        error("error creating mod-list: " .. err, 0)
×
114
                end
115

116
                _, err = await(blockexchange.api.update_schema_stats(token, schema.uid))
3✔
117
                if err then
1✔
NEW
118
                        error("error updating stats: " .. err, 0)
×
119
                end
120

121
                -- get updated schema
122
                schema, err = await(blockexchange.api.get_schema_by_name(claims.username, schemaname))
3✔
123
                if err then
1✔
NEW
124
                        error("error fetching updated schema: " .. err, 0)
×
125
                elseif not schema then
1✔
NEW
126
                        error("saved schema not found: " .. claims.username .. "/" .. schemaname, 0)
×
127
                end
128

129
                -- register area
130
                blockexchange.register_area(pos1, pos2, playername, claims.username, schema)
1✔
131

132
                return {
1✔
133
                        total_parts = total_parts,
1✔
134
                        total_size = total_size,
1✔
135
                        schema = schema
1✔
136
                }
1✔
137
        end)
138

139
        blockexchange.set_job_context(playername, ctx, promise)
1✔
140
        return promise
1✔
141
end
142

143

144
Promise.register_chatcommand("bx_save", {
2✔
145
        params = "<name>",
146
        description = "Uploads the selected region to the blockexchange server",
147
        func = function(name, schemaname)
NEW
148
                if blockexchange.get_job_context(name) then
×
NEW
149
                        return true, "There is a job already running"
×
150
                end
151

NEW
152
                local has_protected_upload_priv = minetest.check_player_privs(name, { blockexchange_protected_upload = true })
×
NEW
153
                local has_blockexchange_priv = minetest.check_player_privs(name, { blockexchange = true })
×
NEW
154
                local has_protection_bypass_priv = minetest.check_player_privs(name, { protection_bypass = true })
×
155

NEW
156
                if not has_blockexchange_priv and not has_protected_upload_priv then
×
NEW
157
                        return true, "Required privs: 'blockexchange' or 'blockexchange_protected_upload'"
×
158
                end
159

NEW
160
                if not schemaname then
×
NEW
161
                        return true, "Usage: /bx_save <schemaname>"
×
162
                end
163

NEW
164
                if not blockexchange.validate_name(schemaname) then
×
NEW
165
                        return true, "schema name can only contain letters, numbers and a handful of special chars: - _ ."
×
166
                end
167

NEW
168
                local token = blockexchange.get_token(name)
×
NEW
169
                if not token then
×
170
                        -- TODO check validity
NEW
171
                        return true, "Please login first to upload a schematic"
×
172
                end
173

NEW
174
                local pos1 = blockexchange.get_pos(1, name)
×
NEW
175
                local pos2 = blockexchange.get_pos(2, name)
×
176

NEW
177
                if not pos1 or not pos2 then
×
NEW
178
                        return true, "you need to set /bx_pos1 and /bx_pos2 first!"
×
179
                end
180

NEW
181
                if not blockexchange.check_size(pos1, pos2) then
×
NEW
182
                        return true, "axis size limit of " .. blockexchange.max_size .. " nodes exceeded"
×
183
                end
184

185
                -- force-enable player-hud
NEW
186
                blockexchange.set_player_hud(name, true)
×
187

NEW
188
                return Promise.async(function(await)
×
189
                        local err, result
NEW
190
                        if not has_blockexchange_priv and has_protected_upload_priv and not has_protection_bypass_priv then
×
191
                                -- check protection first
NEW
192
                                result, err = await(blockexchange.protectioncheck(name, pos1, pos2))
×
NEW
193
                                if err then
×
NEW
194
                                        error("protection check error: " .. err, 0)
×
NEW
195
                                elseif not result.success then
×
NEW
196
                                        local msg = "protection check failed between pos " .. minetest.pos_to_string(result.pos1) ..
×
NEW
197
                                                " and " .. minetest.pos_to_string(result.pos2)
×
NEW
198
                                        error(msg, 0)
×
199
                                end
200
                        end
201

NEW
202
                        result, err = await(blockexchange.save(name, pos1, pos2, schemaname))
×
NEW
203
                        if err then
×
NEW
204
                                error("save error: " .. err)
×
205
                        end
206

NEW
207
                        return "save complete with " .. result.total_parts .. " parts and " .. result.total_size .. " bytes"
×
208
                end)
209
        end
210
})
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