Skip to content

Instantly share code, notes, and snippets.

@sorcerykid
Created February 9, 2026 01:59
Show Gist options
  • Select an option

  • Save sorcerykid/74969e0b3fb9c55bbf5901908f8e31a7 to your computer and use it in GitHub Desktop.

Select an option

Save sorcerykid/74969e0b3fb9c55bbf5901908f8e31a7 to your computer and use it in GitHub Desktop.
Compare map.sqlite databases and output a list of changed nodes
-- Usage: lua compare.lua
-- License: MIT License
package.path = "/home/minetest/maplib/?.lua;" .. package.path
local maplib = require( "maplib" )
local config = dofile( "config.lua" )
---------------------------------------
local function printf( ... )
print( string.format( ... ) )
end
local function compare_blocks( index, new_block, old_block )
local diff_lines = { }
local old_node_list = old_block.get_node_list( )
local old_nodename_map = old_block.nodename_map
local new_node_list = new_block.get_node_list( )
local new_nodename_map = new_block.nodename_map
for idx, new_node in ipairs( new_node_list ) do
local old_node = old_node_list[ idx ]
local old_node_name = old_nodename_map[ old_node.id ]
local new_node_name = new_nodename_map[ new_node.id ]
if new_node_name ~= old_node_name then
local pos = maplib.decode_node_pos( idx, index )
table.insert( diff_lines, string.format( "\t{ pos = { x = %d, y = %d, z = %d }, before = \"%s\", after = \"%s\" },",
pos.x, pos.y, pos.z, old_node_name, new_node_name ) )
end
end
if #diff_lines > 0 then
local logfile = assert( io.open( "output/" .. index .. ".txt", "w" ) )
logfile:write( "return {\n" )
for i, v in ipairs( diff_lines ) do
logfile:write( v, "\n" )
end
logfile:write( "}\n" )
logfile:close( )
end
return #diff_lines
end
-----------------------------------------
local oldmap_db = MapDatabase( config.oldmap_path, false )
local newmap_db = MapDatabase( config.newmap_path, false )
if config.search_area then
print( "Creating cache..." )
newmap_db.create_cache( false )
end
print( "Comparing databases..." )
local iterator = config.search_area and
newmap_db.iterate_area( config.search_area ) or
newmap_db.iterate( )
for index, new_block in iterator do
local old_block = oldmap_db.get_mapblock( index )
if not old_block then
printf( "[WARNING] Missing block %d in old database!", index )
else
local diff_count = compare_blocks( index, new_block, old_block )
if diff_count > 0 then
printf( "[INFO] Block %d differs (%d nodes changed).", index, diff_count )
else
printf( "[INFO] Block %d matches.", index )
end
end
end
print( "Done." )
return {
oldmap_path = "oldmap.sqlite",
newmap_path = "newmap.sqlite",
search_area = MapArea( { x = -2, y = -2, z = -2 }, { x = 2, y = 2, z = 2 } ),
}
local list = minetest.get_dir_list( "output", false )
minetest.after( 0, function ( )
for i, v in ipairs( list ) do
local diff = dofile( "output/" .. v )
-- use the first node position to forceload the mapblock
minetest.forceload_block( diff[ 1 ].pos, true )
for ii, vv in ipairs( diff ) do
if vv.after == "air" then
minetest.set_node( vv.pos, { name = "wool:red" } )
elseif vv.before == "air" then
minetest.set_node( vv.pos, { name = "wool:green" } )
else
minetest.set_node( vv.pos, { name = "wool:yellow" } )
end
local meta = minetest.get_meta( vv.pos )
meta:set_string( "infotext",
minetest.pos_to_string( vv.pos ) .. "\n" .. vv.before .. " -> " .. vv.after )
end
minetest.forceload_free_block( diff[ 1 ].pos, true )
end
end )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment