metadata is now saved as well
parent
b68e2a95b5
commit
a52149a1e6
|
@ -126,6 +126,25 @@ end
|
|||
|
||||
|
||||
|
||||
build_chest.show_size_data = function( building_name )
|
||||
|
||||
if( not( building_name )
|
||||
or building_name == ''
|
||||
or not( build_chest.building[ building_name ] )
|
||||
or not( build_chest.building[ building_name ].size )) then
|
||||
return "";
|
||||
end
|
||||
|
||||
local size = build_chest.building[ building_name ].size;
|
||||
-- show which building has been selected
|
||||
return "label[0.3,9.5;Selected building:]"..
|
||||
"label[2.3,9.5;"..minetest.formspec_escape(building_name).."]"..
|
||||
-- size of the building
|
||||
"label[0.3,9.8;Size ( wide x length x height ):]"..
|
||||
"label[4.3,9.8;"..tostring( size.x )..' x '..tostring( size.z )..' x '..tostring( size.y ).."]";
|
||||
end
|
||||
|
||||
|
||||
|
||||
build_chest.update_formspec = function( pos, page, player, fields )
|
||||
|
||||
|
@ -164,19 +183,8 @@ build_chest.update_formspec = function( pos, page, player, fields )
|
|||
"label[0.3,0.8;Part of village:]" .."label[3.3,0.8;"..(village_name or "?").."]"
|
||||
.."label[7.3,0.8;located at "..(minetest.pos_to_string( village_pos ) or '?').."]"..
|
||||
"label[0.3,1.2;Owned by:]" .."label[3.3,1.2;"..(owner_name or "?").."]"..
|
||||
"label[3.3,1.6;Click on a menu entry to select it:]";
|
||||
|
||||
|
||||
if( building_name and building_name ~= '' and build_chest.building[ building_name ] and build_chest.building[ building_name ].size) then
|
||||
local size = build_chest.building[ building_name ].size;
|
||||
formspec = formspec..
|
||||
-- show which building has been selected
|
||||
"label[0.3,9.5;Selected building:]"..
|
||||
"label[2.3,9.5;"..minetest.formspec_escape(building_name).."]"..
|
||||
-- size of the building
|
||||
"label[0.3,9.8;Size ( wide x length x height ):]"..
|
||||
"label[4.3,9.8;"..tostring( size.x )..' x '..tostring( size.z )..' x '..tostring( size.y ).."]";
|
||||
end
|
||||
"label[3.3,1.6;Click on a menu entry to select it:]"..
|
||||
build_chest.show_size_data( building_name );
|
||||
|
||||
local current_path = minetest.deserialize( meta:get_string( 'current_path' ) or 'return {}' );
|
||||
if( #current_path > 0 ) then
|
||||
|
@ -383,7 +391,9 @@ build_chest.update_formspec = function( pos, page, player, fields )
|
|||
meta:set_string( 'building_name', options[1] );
|
||||
local start_pos = build_chest.get_start_pos( pos );
|
||||
if( type(start_pos)=='table' and start_pos and start_pos.x and build_chest.building[ options[1]].size) then
|
||||
-- TODO: also show size and such
|
||||
-- size information has just been read; we can now display it
|
||||
formspec = formspec..build_chest.show_size_data( building_name );
|
||||
|
||||
-- do replacements for realtest where necessary (this needs to be done only once)
|
||||
local replacements = {};
|
||||
replacements_group['realtest'].replace( replacements );
|
||||
|
@ -555,20 +565,23 @@ build_chest.on_receive_fields = function(pos, formname, fields, player)
|
|||
local end_pos = minetest.deserialize( meta:get_string('end_pos'));
|
||||
local filename = meta:get_string('backup' );
|
||||
if( not( filename ) or filename == "" ) then
|
||||
-- <worldname>/backup_PLAYERNAME_x_y_z_burried_rotation.mts
|
||||
filename = minetest.get_worldpath()..'/backup_'..
|
||||
local base_filename = 'backup_'..
|
||||
meta:get_string('owner')..'_'..
|
||||
tostring( start_pos.x )..':'..tostring( start_pos.y )..':'..tostring( start_pos.z )..'_'..
|
||||
'0_0.mts';
|
||||
'0_0';
|
||||
|
||||
-- TODO: handle metadata
|
||||
-- create directory for the schematics (same path as WorldEdit uses)
|
||||
os.execute("mkdir \""..minetest.get_worldpath().."/schems".. "\"");
|
||||
save_restore.create_directory( '/schems' );
|
||||
-- store a backup of the original landscape
|
||||
minetest.create_schematic( start_pos, end_pos, nil, filename, nil);
|
||||
meta:set_string('backup', filename );
|
||||
-- <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 );
|
||||
meta:set_string('backup', base_filename );
|
||||
|
||||
minetest.chat_send_player( pname, 'CREATING backup schematic for this place in '..tostring( filename )..'.');
|
||||
minetest.chat_send_player( pname, 'CREATING backup schematic for this place in \"schems/'..base_filename..'.mts\".');
|
||||
end
|
||||
|
||||
-- TODO: use scaffolding here (exchange some replacements)
|
||||
|
@ -590,9 +603,13 @@ mirror = nil;
|
|||
local start_pos = minetest.deserialize( meta:get_string('start_pos'));
|
||||
local end_pos = minetest.deserialize( meta:get_string('end_pos'));
|
||||
local backup_file = meta:get_string( 'backup' );
|
||||
if( start_pos and end_pos and start_pos.x and end_pos.x and backup_file and backup_file ~= "") then
|
||||
minetest.place_schematic( start_pos, backup_file, "0", {}, true );
|
||||
meta:set_string('backup', nil );
|
||||
if( start_pos and end_pos and start_pos.x and end_pos.x and backup_file and backup_file ~= "" ) then
|
||||
if( save_restore.file_exists( 'schems/'..backup_file..'.mts' )) then
|
||||
filename = minetest.get_worldpath()..'/schems/'..backup_file..'.mts';
|
||||
minetest.place_schematic( start_pos, filename, "0", {}, true );
|
||||
handle_schematics.restore_meta( backup_file );
|
||||
meta:set_string('backup', nil );
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
@ -700,10 +717,12 @@ mirror = nil;
|
|||
-- TODO: forbid overwriting existing files?
|
||||
local worldpath = minetest.get_worldpath();
|
||||
local filename_complete = worldpath..'/schems/'..filename..'.mts';
|
||||
-- make sure the directory exists...
|
||||
os.execute("mkdir \""..minetest.get_worldpath().."/schems".. "\"");
|
||||
-- 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);
|
||||
|
||||
-- store that we have saved this area
|
||||
meta:set_string('saved_as_filename', filename);
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
|
||||
|
||||
handle_schematics.sort_pos_get_size = function( p1, p2 )
|
||||
local res = {x=p1.x, y=p1.y, z=p1.z,
|
||||
sizex = math.abs( p1.x - p2.x )+1,
|
||||
sizey = math.abs( p1.y - p2.y )+1,
|
||||
sizez = math.abs( p1.z - p2.z )+1};
|
||||
if( p2.x < p1.x ) then
|
||||
res.x = p2.x;
|
||||
end
|
||||
if( p2.y < p1.y ) then
|
||||
res.y = p2.y;
|
||||
end
|
||||
if( p2.z < p1.z ) then
|
||||
res.z = p2.z;
|
||||
end
|
||||
return res;
|
||||
end
|
||||
|
||||
|
||||
local handle_schematics_get_meta_table = function( pos, all_meta )
|
||||
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 = {};
|
||||
for name, list in pairs( m.inventory ) do
|
||||
invlist[ name ] = {};
|
||||
for i, stack in ipairs(list) do
|
||||
if( not( stack:is_empty())) then
|
||||
invlist[ name ][ i ] = stack:to_string();
|
||||
empty_meta = false;
|
||||
end
|
||||
end
|
||||
end
|
||||
-- the fields part at least is unproblematic
|
||||
if( empty_meta and m.fields ) then
|
||||
for k,v in pairs( m.fields ) do
|
||||
empty_meta = false;
|
||||
end
|
||||
end
|
||||
|
||||
-- only
|
||||
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};
|
||||
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 )
|
||||
local all_meta = {};
|
||||
|
||||
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 );
|
||||
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 );
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if( #all_meta > 0 ) then
|
||||
save_restore.save_data( 'schems/'..filename..'.meta', all_meta );
|
||||
|
||||
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} );
|
||||
meta:from_table( empty_meta );
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- restore metadata from file
|
||||
-- TODO: use relative instead of absolute positions
|
||||
handle_schematics.restore_meta = function( filename )
|
||||
|
||||
local all_meta = save_restore.restore_data( 'schems/'..filename..'.meta' );
|
||||
for _,pos in ipairs( all_meta ) do
|
||||
local meta = minetest.get_meta( {x=pos.x, y=pos.y, z=pos.z} );
|
||||
meta:from_table( {inventory = pos.inventory, fields = pos.fields });
|
||||
end
|
||||
end
|
4
init.lua
4
init.lua
|
@ -17,6 +17,10 @@ dofile(handle_schematics.modpath.."/rotate.lua")
|
|||
-- count nodes, take param2 into account for rotation etc.
|
||||
dofile(handle_schematics.modpath.."/handle_schematics_misc.lua")
|
||||
|
||||
-- store and restore metadata
|
||||
dofile(handle_schematics.modpath.."/save_restore.lua");
|
||||
dofile(handle_schematics.modpath.."/handle_schematics_meta.lua");
|
||||
|
||||
-- uses replacements_group.* namespace
|
||||
-- these functions are responsible for the optional dependencies; they check
|
||||
-- which nodes are available and may be offered as possible replacements
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
|
||||
-- reserve the namespace
|
||||
save_restore = {}
|
||||
|
||||
-- TODO: if this gets more versatile, add sanity checks for filename
|
||||
-- TODO: apart from allowing filenames, schems/<filename> also needs to be allowed
|
||||
|
||||
-- TODO: save and restore ought to be library functions and not implemented in each individual mod!
|
||||
save_restore.save_data = function( filename, data )
|
||||
|
||||
local path = minetest.get_worldpath()..'/'..filename;
|
||||
|
||||
local file = io.open( path, 'w' );
|
||||
if( file ) then
|
||||
file:write( minetest.serialize( data ));
|
||||
file:close();
|
||||
else
|
||||
print("[save_restore] Error: Savefile '"..tostring( path ).."' could not be written.");
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
save_restore.restore_data = function( filename )
|
||||
|
||||
local path = minetest.get_worldpath()..'/'..filename;
|
||||
|
||||
local file = io.open( path, 'r' );
|
||||
if( file ) then
|
||||
local data = file:read("*all");
|
||||
file:close();
|
||||
return minetest.deserialize( data );
|
||||
else
|
||||
print("[save_restore] Error: Savefile '"..tostring( path ).."' not found.");
|
||||
return {}; -- return empty table
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
save_restore.file_exists = function( filename )
|
||||
|
||||
local path = minetest.get_worldpath()..'/'..filename;
|
||||
|
||||
local file = io.open( path, 'r' );
|
||||
if( file ) then
|
||||
file:close();
|
||||
return true;
|
||||
end
|
||||
return;
|
||||
end
|
||||
|
||||
|
||||
save_restore.create_directory = function( filename )
|
||||
|
||||
local path = minetest.get_worldpath()..'/'..filename;
|
||||
|
||||
if( not( save_restore.file_exists( filename ))) then
|
||||
os.execute("mkdir \""..minetest.get_worldpath().."/schems".. "\"");
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue