mapsync-cd2025/create_diff.lua
2023-06-30 14:15:10 +02:00

161 lines
5.3 KiB
Lua

local c_air = minetest.get_content_id("air")
local function create_mapblock(mapblock_pos, mapblock, callback)
assert(#mapblock.node_ids == 4096)
assert(#mapblock.param2 == 4096)
for i=1,4096 do
local nodeid = mapblock.node_ids[i]
if nodeid ~= c_air then
-- relative position in the mapblock
local rel_pos = mapsync.mapblock_index_to_pos(i)
-- relative position in the chunk
local rel_chunk_pos = vector.add(rel_pos, vector.multiply(mapblock_pos, 16))
local nodename = minetest.get_name_from_content_id(nodeid)
local node = {
x=rel_chunk_pos.x,
y=rel_chunk_pos.y,
z=rel_chunk_pos.z,
name = nodename,
param2 = mapblock.param2[i]
}
if mapblock.metadata then
local rel_pos_str = minetest.pos_to_string(rel_pos)
if mapblock.metadata.meta then
node.meta = mapblock.metadata.meta[rel_pos_str]
end
if mapblock.metadata.meta then
node.timer = mapblock.metadata.timers[rel_pos_str]
end
end
callback(node)
end
end
end
local function air_mapblock(mapblock_pos, callback)
for i=1,4096 do
-- relative position in the mapblock
local rel_pos = mapsync.mapblock_index_to_pos(i)
-- relative position in the chunk
local rel_chunk_pos = vector.add(rel_pos, vector.multiply(mapblock_pos, 16))
local node = {
x=rel_chunk_pos.x,
y=rel_chunk_pos.y,
z=rel_chunk_pos.z,
name = "air",
param2 = 0
}
callback(node)
end
end
local function diff_mapblock(mapblock_pos, baseline_mapblock, mapblock, callback)
assert(#baseline_mapblock.node_ids == 4096)
assert(#baseline_mapblock.param2 == 4096)
assert(#mapblock.node_ids == 4096)
assert(#mapblock.param2 == 4096)
for i=1,4096 do
-- relative position in the mapblock
local rel_pos = mapsync.mapblock_index_to_pos(i)
-- relative position in the chunk
local rel_chunk_pos = vector.add(rel_pos, vector.multiply(mapblock_pos, 16))
local baseline_nodeid = baseline_mapblock.node_ids[i]
local new_nodeid = mapblock.node_ids[i]
local node = { x=rel_chunk_pos.x, y=rel_chunk_pos.y, z=rel_chunk_pos.z }
local changed = false
-- node id
if baseline_nodeid ~= new_nodeid then
local new_nodename = minetest.get_name_from_content_id(new_nodeid)
node.name = new_nodename
changed = true
end
-- param2
if baseline_mapblock.param2[i] ~= mapblock.param2[i] then
node.param2 = mapblock.param2[i]
changed = true
end
-- metadata
local rel_pos_str = minetest.pos_to_string(rel_pos)
local baseline_meta = baseline_mapblock.metadata
and baseline_mapblock.metadata.meta
and baseline_mapblock.metadata.meta[rel_pos_str]
local new_meta = mapblock.metadata
and mapblock.metadata.meta
and mapblock.metadata.meta[rel_pos_str]
if new_meta then
-- add empty inventory to baseline if not already there
if baseline_meta then
baseline_meta.inventory = baseline_meta.inventory or {}
end
if not mapsync.deep_compare(baseline_meta, new_meta) then
-- metadata not equal or new
node.meta = new_meta
changed = true
end
end
local timer = mapblock.metadata and mapblock.metadata.timers and mapblock.metadata.timers[rel_pos_str]
if timer then
node.timer = timer
end
if changed then
callback(node)
end
end
return true
end
function mapsync.create_diff(baseline_chunk, chunk_pos, callback)
local node_mapping = {}
local mb_pos1, mb_pos2 = mapsync.get_mapblock_bounds_from_chunk(chunk_pos)
for x=mb_pos1.x,mb_pos2.x do
for y=mb_pos1.y,mb_pos2.y do
for z=mb_pos1.z,mb_pos2.z do
local mapblock_pos = {x=x, y=y, z=z}
local rel_mapblock_pos = vector.subtract(mapblock_pos, mb_pos1)
local blockdata = mapsync.serialize_mapblock(mapblock_pos, node_mapping)
local baseline_mapblock = baseline_chunk and
baseline_chunk.mapblocks[minetest.pos_to_string(rel_mapblock_pos)]
if blockdata.empty and baseline_mapblock then
-- block removed
air_mapblock(rel_mapblock_pos, callback)
elseif not blockdata.empty and not baseline_mapblock then
-- block added
create_mapblock(rel_mapblock_pos, blockdata, callback)
elseif not blockdata.empty and baseline_mapblock then
-- both blocks exist, compare
local success, err_msg = diff_mapblock(rel_mapblock_pos,baseline_mapblock,blockdata,callback)
if not success then
return false, err_msg
end
end
end
end
end
return true
end