save only metadata of nodes that are not empty (provided that can be determined)
parent
a52149a1e6
commit
01c3df0a08
|
@ -570,16 +570,12 @@ build_chest.on_receive_fields = function(pos, formname, fields, player)
|
|||
tostring( start_pos.x )..':'..tostring( start_pos.y )..':'..tostring( start_pos.z )..'_'..
|
||||
'0_0';
|
||||
|
||||
-- TODO: handle metadata
|
||||
-- create directory for the schematics (same path as WorldEdit uses)
|
||||
save_restore.create_directory( '/schems' );
|
||||
-- store a backup of the original landscape
|
||||
-- <worldname>/backup_PLAYERNAME_x_y_z_burried_rotation.mts
|
||||
filename = minetest.get_worldpath()..'/schems/'..base_filename..'.mts';
|
||||
minetest.create_schematic( start_pos, end_pos, nil, filename, nil);
|
||||
-- save metadata and clear it so that the new building can be placed
|
||||
handle_schematics.save_meta( start_pos, end_pos, base_filename, true );
|
||||
handle_schematics.create_schematic_with_meta( start_pos, end_pos, base_filename );
|
||||
meta:set_string('backup', base_filename );
|
||||
-- clear metadata so that the new building can be placed
|
||||
handle_schematics.clear_meta( start_pos, end_pos );
|
||||
|
||||
minetest.chat_send_player( pname, 'CREATING backup schematic for this place in \"schems/'..base_filename..'.mts\".');
|
||||
end
|
||||
|
@ -717,12 +713,8 @@ mirror = nil;
|
|||
-- TODO: forbid overwriting existing files?
|
||||
local worldpath = minetest.get_worldpath();
|
||||
local filename_complete = worldpath..'/schems/'..filename..'.mts';
|
||||
-- create directory for the schematics (same path as WorldEdit uses)
|
||||
save_restore.create_directory( '/schems' );
|
||||
-- really save it with probability_list and slice_prob_list both as nil
|
||||
minetest.create_schematic( p1, p2, nil, filename_complete, nil);
|
||||
-- save metadata, but do not clear it
|
||||
handle_schematics.save_meta( start_pos, end_pos, base_filename, false);
|
||||
|
||||
handle_schematics.create_schematic_with_meta( p1, p2, filename );
|
||||
|
||||
-- store that we have saved this area
|
||||
meta:set_string('saved_as_filename', filename);
|
||||
|
|
|
@ -18,53 +18,86 @@ handle_schematics.sort_pos_get_size = function( p1, p2 )
|
|||
end
|
||||
|
||||
|
||||
local handle_schematics_get_meta_table = function( pos, all_meta )
|
||||
|
||||
local handle_schematics_get_meta_table = function( pos, all_meta, start_pos )
|
||||
local m = minetest.get_meta( pos ):to_table();
|
||||
local empty_meta = true;
|
||||
|
||||
-- TODO: do not save known nodes if they contain the same values as a default node of that type
|
||||
--local n = minetest.get_node( pos );
|
||||
-- the inventory part contains functions and cannot be fed to minetest.serialize directly
|
||||
local invlist = {};
|
||||
local count_inv = 0;
|
||||
local inv_is_empty = true;
|
||||
for name, list in pairs( m.inventory ) do
|
||||
invlist[ name ] = {};
|
||||
count_inv = count_inv + 1;
|
||||
for i, stack in ipairs(list) do
|
||||
if( not( stack:is_empty())) then
|
||||
invlist[ name ][ i ] = stack:to_string();
|
||||
empty_meta = false;
|
||||
inv_is_empty = false;
|
||||
end
|
||||
end
|
||||
end
|
||||
-- the fields part at least is unproblematic
|
||||
local count_fields = 0;
|
||||
if( empty_meta and m.fields ) then
|
||||
for k,v in pairs( m.fields ) do
|
||||
empty_meta = false;
|
||||
count_fields = count_fields + 1;
|
||||
end
|
||||
end
|
||||
|
||||
-- only
|
||||
|
||||
-- ignore default:sign_wall without text on it
|
||||
if( count_inv==0
|
||||
and count_fields<=3 and m.fields.formspec and m.fields.infotext
|
||||
and m.fields.formspec == "field[text;;${text}]"
|
||||
and m.fields.infotext == "\"\"") then
|
||||
-- also consider signs empty if their text has been set once and deleted afterwards
|
||||
if( not( m.fields.text ) or m.fields.text == "" ) then
|
||||
print('SKIPPING empty sign AT '..minetest.pos_to_string( pos)..' while saving metadata.');
|
||||
empty_meta = true;
|
||||
end
|
||||
|
||||
elseif( count_inv > 0 and inv_is_empty
|
||||
and count_fields>0 and m.fields.formspec ) then
|
||||
|
||||
local n = minetest.get_node( pos );
|
||||
if( n and n.name
|
||||
and (n.name=='default:chest' or n.name=='default:chest_locked' or n.name=='default:bookshelf'
|
||||
or n.name=='default:furnace' or n.name=='default:furnace_active'
|
||||
or n.name=='cottages:shelf' or n.name=='cottages:anvil' or n.name=='cottages:threshing_floor' )) then
|
||||
print('SKIPPING empty '..tostring(n.name)..' AT '..minetest.pos_to_string( pos )..' while saving metadata.');
|
||||
empty_meta = true;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- only save if there is something to be saved
|
||||
if( not( empty_meta )) then
|
||||
-- TODO: use relative positions instead of absolute ones
|
||||
all_meta[ #all_meta+1 ] = { x=pos.x, y=pos.y, z=pos.z, fields = m.fields, inventory = invlist};
|
||||
-- positions are stored as relative positions
|
||||
all_meta[ #all_meta+1 ] = {
|
||||
x=pos.x-start_pos.x,
|
||||
y=pos.y-start_pos.y,
|
||||
z=pos.z-start_pos.z,
|
||||
fields = m.fields,
|
||||
inventory = invlist};
|
||||
end
|
||||
end
|
||||
|
||||
-- reads metadata values from start_pos to end_pos and stores them in a file
|
||||
-- if clear_meta is set, all metadata values will be deleted after saving,
|
||||
-- making the area ready for new voxelmanip/schematic data
|
||||
handle_schematics.save_meta = function( start_pos, end_pos, filename, clear_meta )
|
||||
handle_schematics.save_meta = function( start_pos, end_pos, filename )
|
||||
local all_meta = {};
|
||||
local p = handle_schematics.sort_pos_get_size( start_pos, end_pos );
|
||||
|
||||
if( minetest.find_nodes_with_meta ) then
|
||||
for _,pos in ipairs( minetest.find_nodes_with_meta( start_pos, end_pos )) do
|
||||
handle_schematics_get_meta_table( pos, all_meta );
|
||||
handle_schematics_get_meta_table( pos, all_meta, p );
|
||||
end
|
||||
else
|
||||
local p = handle_schematics.sort_pos_get_size( start_pos, end_pos );
|
||||
for x=p.x, p.x+p.sizex do
|
||||
for y=p.y, p.y+p.sizey do
|
||||
for z=p.z, p.z+p.sizez do
|
||||
handle_schematics_get_meta_table( {x=x, y=y, z=z}, all_meta );
|
||||
handle_schematics_get_meta_table( {x=x, y=y, z=z}, all_meta, p );
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -72,10 +105,17 @@ handle_schematics.save_meta = function( start_pos, end_pos, filename, clear_meta
|
|||
|
||||
if( #all_meta > 0 ) then
|
||||
save_restore.save_data( 'schems/'..filename..'.meta', all_meta );
|
||||
end
|
||||
end
|
||||
|
||||
local empty_meta = { inventory = {}, fields = {} };
|
||||
for _, pos in ipairs( all_meta ) do
|
||||
local meta = minetest.get_meta( {x=pos.x, y=pos.y, z=pos.z} );
|
||||
-- all metadata values will be deleted when this function is called,
|
||||
-- making the area ready for new voxelmanip/schematic data
|
||||
handle_schematics.clear_meta = function( start_pos, end_pos )
|
||||
local empty_meta = { inventory = {}, fields = {} };
|
||||
|
||||
if( minetest.find_nodes_with_meta ) then
|
||||
for _,pos in ipairs( minetest.find_nodes_with_meta( start_pos, end_pos )) do
|
||||
local meta = minetest.get_meta( pos );
|
||||
meta:from_table( empty_meta );
|
||||
end
|
||||
end
|
||||
|
@ -92,3 +132,18 @@ handle_schematics.restore_meta = function( filename )
|
|||
meta:from_table( {inventory = pos.inventory, fields = pos.fields });
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- return true on success; will overwrite existing files
|
||||
handle_schematics.create_schematic_with_meta = function( p1, p2, base_filename )
|
||||
|
||||
-- create directory for the schematics (same path as WorldEdit uses)
|
||||
save_restore.create_directory( '/schems' );
|
||||
local complete_filename = minetest.get_worldpath()..'/schems/'..base_filename..'.mts';
|
||||
-- actually create the schematic
|
||||
minetest.create_schematic( p1, p2, nil, complete_filename, nil);
|
||||
-- save metadata; the file will only be created if there is any metadata that is to be saved
|
||||
handle_schematics.save_meta( p1, p2, base_filename );
|
||||
|
||||
return save_restore.file_exists( complete_filename );
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue