preparations for generator functions

master
Sokomine 2019-06-10 03:32:33 +02:00
parent 05e95a1e52
commit 205520cca0
5 changed files with 117 additions and 7 deletions

View File

@ -113,7 +113,7 @@ handle_schematics.restore_landscape = function( meta, player_name, force_place,
local axis = build_chest.building[ building_name ].axis;
local no_plotmarker = true;
local replacement_list = {};
local error_msg = handle_schematics.place_building_from_file( start_pos, end_pos, filename, replacement_list, "180", 3, 1, no_plotmarker, false, true, pos );
local error_msg = handle_schematics.place_building_from_file_or_cache( start_pos, end_pos, filename, replacement_list, "180", 3, 1, no_plotmarker, false, true, pos, nil );
if( error_msg ) then
error_msg = 'Error: '..tostring( error_msg );
minetest.chat_send_player( player_name, error_msg );

View File

@ -64,8 +64,26 @@ build_chest.read_building = function( building_name, building_data )
if( not( build_chest.building[ building_name ] )) then
build_chest.building[ building_name ] = building_data;
end
-- read data
local res = handle_schematics.analyze_file( building_name, nil, nil, build_chest.building[ building_name ]);
local res = {};
-- use a generator function instead of a file;
-- WARNING: This generates a new building each time this function is called!
if( building_data.generator
or (build_chest.building[ building_name ] and build_chest.building[ building_name ].generator)) then
print("USING generator function...");
-- TODO: those have to be read via the interface somehow...
local sizex = 11;
local sizez = 14;
local sizey = 20;
local seed = 2;
local fake_vm = handle_schematics.create_fake_vm(sizex, sizey, sizez);
fake_vm.generator = building_data.generator;
res = build_chest.building[ building_name ].generator({x=0,y=1,z=0}, sizex, sizez, sizey, seed, fake_vm );
build_chest.building[ building_name ] = res;
else
-- read data
res = handle_schematics.analyze_file( building_name, nil, nil, build_chest.building[ building_name ]);
end
if( not( res )) then
return;
end
@ -156,7 +174,9 @@ build_chest.show_size_data = function( building_name )
local size = build_chest.building[ building_name ].size;
-- the full path and name of the building is often too long and provides information about the filesystem, which is unsuitable for players
local shortened_building_name = building_name;
shortened_building_name = string.sub( building_name, string.len( building_name ) + 2 - string.find( string.reverse(building_name), "/", 1, true ));
if( string.find( string.reverse(building_name), "/", 1, true )) then
shortened_building_name = string.sub( building_name, string.len( building_name ) + 2 - string.find( string.reverse(building_name), "/", 1, true ));
end
-- show which building has been selected
return "label[0.3,9.5;Selected building:]"..
@ -760,7 +780,7 @@ mirror = nil;
if( not( minetest.check_player_privs( pname, {creative=true}))) then
use_scaffolding = true;
end
fields.error_msg = handle_schematics.place_building_from_file( start_pos, end_pos, building_name, replacement_list, rotate, axis, mirror, no_plotmarker, false, use_scaffolding, pos );
fields.error_msg = handle_schematics.place_building_from_file_or_cache( start_pos, end_pos, building_name, replacement_list, rotate, axis, mirror, no_plotmarker, false, use_scaffolding, pos, build_chest.building[ building_name ] );
if( fields.error_msg ) then
fields.error_msg = 'Error: '..tostring( fields.error_msg );
end

View File

@ -142,3 +142,7 @@ dofile(handle_schematics.modpath.."/fill_chest.lua");
-- helper functions for finding flat land to build on
dofile(handle_schematics.modpath.."/detect_flat_land_fast.lua");
-- provide an interface so that functions that generate houses/structures
-- can do so for handle_schematics
dofile(handle_schematics.modpath.."/interface_generator_functions.lua");

View File

@ -0,0 +1,84 @@
-- handle_schematics does a lot more than just read schematics and place
-- them on the map; there are such things as biome conservation (includig
-- snow), replacements, scaffolding etc.;
--
-- this here provides interface functions so that generator functions that
-- would normally operate on a VoxelManip area (or on the map directly) can
-- provide structures for handle_schematics
-- helper function that emulates the function VoxelManip:set_node_at
handle_schematics.fake_vm_set_node_at = function( self, p, node )
-- range check: self.scm_data_cache is prepared so that self.scm_data_cache[y][x]
-- is valid for valid p.x and p.y;
if( p.z<1 or not(self.scm_data_cache[p.y]) or not(self.scm_data_cache[p.y][p.x])) then
return;
end
if(not(node.name)) then
return;
end
-- a nil value would be problematic later on
if( not(node.param2)) then
node.param2 = 0;
end
-- translate nodename into id
local id = -1;
for i,name in ipairs(self.nodenames) do
if( name==node.name ) then
id = i;
end
end
-- new node name
if(id==-1) then
id = #self.nodenames+1;
self.nodenames[ id ] = node.name;
-- is it necessary to call on_construct or after_place_node?
local node_def = handle_schematics.node_defined( node.name );
if( node_def and node_def.on_construct) then
table.insert( self.on_constr, name_text );
end
if( node_def and node_def.after_place_node) then
table.insert( self.after_place_node, name_text );
end
end
-- bed positions may be of less intrest in generated houses;
-- however, it can't hurt to store them anyway
if( handle_schematics.bed_node_names[ node.name ]) then
self.bed_count = self.bed_count + 1;
table.insert( self.bed_list, {x=x, y=y, z=z, p2, id});
end
-- actually store the data in the data structure
self.scm_data_cache[p.y][p.x][p.z] = {id, node.param2};
end
-- create a fake VoxelManipulator data structure for generator functions
handle_schematics.create_fake_vm = function(sizex, sizey, sizez)
-- data structure as would be provided by analyze_mts_file
local vm = { size = { x=sizex, y=sizey, z=sizez},
scm="Procedurally generated structure", -- name of building
sizex=sizex, sizez=sizez, ysize=sizey, sizey=sizey,
nodenames = {},
on_constr = {},
after_place_node = {},
rotated=0, orients = {0},
burried=0, yoff=1, -- not burried
scm_data_cache = {},
bed_count = 0,
bed_list = {} };
-- prepare the table so that a schematic can be inserted
for y = 1, sizey do
vm.scm_data_cache[y] = {};
for x = 1, sizex do
vm.scm_data_cache[y][x] = {};
end
end
-- coordinates in this fake VoxelManip area do not represent real map
-- coordinates; the function using this data structure must not operate
-- on any real map metadata or anything like that
vm.is_fake_vm = true;
-- main function to actually set any nodes
vm.set_node_at = handle_schematics.fake_vm_set_node_at;
return vm;
end

View File

@ -1089,13 +1089,15 @@ end
-- places a building read from file "building_name" on the map between start_pos and end_pos using luavoxelmanip
-- returns error message on failure and nil on success
handle_schematics.place_building_from_file = function( start_pos, end_pos, building_name, replacement_list, rotate, axis, mirror, no_plotmarker, keep_ground, scaffolding_only, plotmarker_pos )
handle_schematics.place_building_from_file_or_cache = function( start_pos, end_pos, building_name, replacement_list, rotate, axis, mirror, no_plotmarker, keep_ground, scaffolding_only, plotmarker_pos, binfo )
--print ("scaffolding place_building_from_file: "..minetest.serialize( scaffolding_only ));
if( not( building_name )) then
return "No file name given. Cannot find the schematic.";
end
local binfo = handle_schematics.analyze_file( building_name, nil, nil );
if(not(binfo)) then
binfo = handle_schematics.analyze_file( building_name, nil, nil );
end
if( not( binfo )) then
return "Failed to import schematic. Only .mts and .we are supported!";
end