local global_env = ... local function save_worker(ctx) local chunk_pos = ctx.iterator() if not chunk_pos then -- done minetest.chat_send_player(ctx.playername, "Async saving done with " .. ctx.count .. " chunks") else -- save pos local success, err_msg = mapsync.save(chunk_pos) if not success then minetest.chat_send_player( ctx.playername, "Saving of chunk " .. minetest.pos_to_string(chunk_pos) .. "failed with: " .. err_msg ) else minetest.chat_send_player( ctx.playername, "Saving of chunk " .. minetest.pos_to_string(chunk_pos) .. " done (count: " .. ctx.count .. ")" ) ctx.count = ctx.count + 1 -- re-schedule minetest.after(0, save_worker, ctx) end end end minetest.register_chatcommand("mapsync_save", { description = "saves the current chunk or a range around the current chunk (cubic)", params = "[chunk-range]", privs = { mapsync = true }, func = function(name, param) local player = minetest.get_player_by_name(name) if not player then return end local range = tonumber(param) or 0 local ppos = player:get_pos() local chunk_pos = mapsync.get_chunkpos(ppos) local chunk_pos1 = vector.subtract(chunk_pos, range) local chunk_pos2 = vector.add(chunk_pos, range) if range == 0 then -- just the one block local success, err_msg = mapsync.save(chunk_pos) if success then return true, "Saved chunk: " .. minetest.pos_to_string(chunk_pos) else return true, "Error saving chunk: " .. minetest.pos_to_string(chunk_pos) .. ", error: " .. (err_msg and err_msg or "") end end -- multiple blocks, execute async minetest.after(0, save_worker, { playername = name, count = 0, iterator = mapsync.pos_iterator(chunk_pos1, chunk_pos2), }) return true, "dispatched saving to worker with range of " .. range .. " chunks around the current center" end }) function mapsync.save(chunk_pos) local backend_def = mapsync.select_backend(chunk_pos) if not backend_def then return true, "No backend available" end if not backend_def.patch_path then -- direct save return mapsync.serialize_chunk(chunk_pos, mapsync.get_chunk_zip_path(backend_def.path, chunk_pos)) else -- create patch file local baseline_chunk = mapsync.parse_chunk(mapsync.get_chunk_zip_path(backend_def.path, chunk_pos)) local filename = mapsync.get_chunk_json_path(backend_def.patch_path, chunk_pos) local f = global_env.io.open(filename, "w") local no_diff = true mapsync.create_diff(baseline_chunk, chunk_pos, function(changed_node) no_diff = false f:write(minetest.write_json(changed_node) .. '\n') end) f:close() if no_diff then -- remove empty diff file global_env.os.remove(filename) end return true end end