added scaffolding and dig here indicators if player has no creative priv

This commit is contained in:
Sokomine 2016-12-28 22:31:16 +01:00
parent df5c3a5639
commit 9d2f9b5f95
2 changed files with 48 additions and 13 deletions

View File

@ -116,7 +116,8 @@ build_chest.get_start_pos = function( pos )
-- save the data for later removal/improvement of the building in the chest
meta:set_string( 'start_pos', minetest.serialize( param2_rotated.start_pos ));
meta:set_string( 'end_pos', minetest.serialize( param2_rotated.end_pos ));
-- one higher so that there is place for "dig here" indicators
meta:set_string( 'end_pos', minetest.serialize( {x=param2_rotated.end_pos.x, y=param2_rotated.end_pos.y+1, z=param2_rotated.end_pos.z} ));
meta:set_string( 'rotate', tostring(param2_rotated.rotate ));
meta:set_int( 'mirror', mirror );
-- no replacements yet
@ -571,7 +572,7 @@ build_chest.on_receive_fields = function(pos, formname, fields, player)
local building_name = meta:get_string('building_name' );
-- the statistic is needed for all the replacements later on as it also contains the list of nodenames
if( building_name and building_name~="" and not( build_chest.building[ building_name ].size )) then
if( building_name and building_name~="" and (not( build_chest.building[ building_name ]) or not( build_chest.building[ building_name ].size ))) then
build_chest.read_building( building_name );
end
@ -673,7 +674,6 @@ build_chest.on_receive_fields = function(pos, formname, fields, player)
minetest.chat_send_player( pname, 'CREATING backup schematic for this place in \"schems/'..base_filename..'.mts\".');
end
-- TODO: use scaffolding here (exchange some replacements)
local replacement_list = build_chest.replacements_get_current( meta, village_id );
local rotate = meta:get_string('rotate');
local mirror = meta:get_string('mirror');
@ -682,7 +682,13 @@ build_chest.on_receive_fields = function(pos, formname, fields, player)
-- actually place the building
--minetest.place_schematic( start_pos, building_name..'.mts', rotate, replacement_list, true );
mirror = nil;
fields.error_msg = handle_schematics.place_building_from_file( start_pos, end_pos, building_name, replacement_list, rotate, axis, mirror, no_plotmarker, false );
-- players who do not have the creative priv cannot produce nodes out of thin air
local use_scaffolding = false;
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 );
if( fields.error_msg ) then
fields.error_msg = 'Error: '..tostring( fields.error_msg );
end

View File

@ -270,7 +270,7 @@ local function generate_building_translate_nodenames( nodenames, replacements, c
end
local function generate_building(pos, minp, maxp, data, param2_data, a, extranodes, replacements, cid, extra_calls, building_nr_in_bpos, village_id, binfo_extra, road_node, keep_ground)
local function generate_building(pos, minp, maxp, data, param2_data, a, extranodes, replacements, cid, extra_calls, building_nr_in_bpos, village_id, binfo_extra, road_node, keep_ground, scaffolding_only)
local binfo = binfo_extra;
if( not( binfo ) and mg_villages) then
@ -338,6 +338,9 @@ local function generate_building(pos, minp, maxp, data, param2_data, a, extranod
local c_dirt_with_grass = minetest.get_content_id( "default:dirt_with_grass" );
local c_dirt_with_snow = minetest.get_content_id( "default:dirt_with_snow" );
local c_scaffolding = minetest.get_content_id( "handle_schematics:support" );
local c_dig_here = minetest.get_content_id( "handle_schematics:dig_here" );
local scm_x = 0;
local scm_z = 0;
local step_x = 1;
@ -428,7 +431,6 @@ local function generate_building(pos, minp, maxp, data, param2_data, a, extranod
local new_content = c_air;
local t = scm[y+1][xoff][zoff];
local node_content = data[a:index(ax, ay, az)];
if( binfo.yoff+y == 0 ) then
-- no snow on the gravel roads
if( node_content == c_dirt_with_snow or data[a:index(ax, ay+1, az)]==c_snow) then
@ -438,7 +440,30 @@ local function generate_building(pos, minp, maxp, data, param2_data, a, extranod
ground_type = node_content;
end
if( not( t )) then
-- scaffolding nodes are only placed when there is air and there ought to be some node
if( scaffolding_only ) then
local current_content = data[a:index(ax, ay, az)];
-- there is air there right now, but there ought to be a node from the building
if( current_content == cid.c_air and t) then
data[ a:index(ax, ay, az)] = c_scaffolding;
-- we have the wrong node there
elseif( ((not(t) and current_content ~= cid.c_air)
or (t and new_nodes[t[1]] and not(new_nodes[t[1]].ignore) and current_content ~= new_nodes[ t[1]].new_content))
-- TODO: detect wrong rotation (param2)
and current_content ~= c_scaffolding
and current_content ~= c_dig_here
and ay<maxp.y) then
-- there is air above; we can place a digging indicator
if( data[a:index(ax, ay+1, az)] == cid.c_air or data[a:index(ax, ay+1, az)]==c_scaffolding) then
data[ a:index(ax, ay+1, az)] = c_dig_here;
end
end
-- normal operations
elseif( not( t )) then
if( node_content ~= cid.c_plotmarker
and (not(handle_schematics.moresnow_installed) or not(moresnow) or node_content ~= moresnow.c_snow_top )) then
data[ a:index(ax, ay, az)] = cid.c_air;
@ -602,7 +627,8 @@ handle_schematics.place_buildings = function(village, minp, maxp, data, param2_d
if( pos.road_material ) then
road_material = pos.road_material;
end
generate_building(pos, minp, maxp, data, param2_data, a, extranodes, replacements, cid, extra_calls, i, village_id, nil, road_material, true )
-- do not use scaffolding here; place the building directly
generate_building(pos, minp, maxp, data, param2_data, a, extranodes, replacements, cid, extra_calls, i, village_id, nil, road_material, true, false )
end
end
@ -640,8 +666,10 @@ end
-- binfo.axis optional; relevant for some mirroring operations
--
-- replacement_list contains replacements in the same list format as place_schematic uses
-- keep_ground keep biome-specific ground nodes
-- scaffolding_only when true: place a scaffolding node where there is air; place nothing if there is a solid node
--
handle_schematics.place_building_using_voxelmanip = function( pos, binfo, replacement_list, keep_ground)
handle_schematics.place_building_using_voxelmanip = function( pos, binfo, replacement_list, keep_ground, scaffolding_only)
if( not( replacement_list ) or type( replacement_list ) ~= 'table' ) then
return;
@ -658,7 +686,8 @@ handle_schematics.place_building_using_voxelmanip = function( pos, binfo, replac
local vm = minetest.get_voxel_manip()
local minp, maxp = vm:read_from_map(
{x = pos.x, y = pos.y, z = pos.z},
{x = pos.x+pos.bsizex, y = pos.y+binfo.ysize, z = pos.z+pos.bsizez} -- TODO
-- add one in height in case we need to add a dig_here-indicator
{x = pos.x+pos.bsizex, y = pos.y+binfo.ysize+1, z = pos.z+pos.bsizez} -- TODO
)
local a = VoxelArea:new({MinEdge = minp, MaxEdge = maxp})
local data = vm:get_data()
@ -700,7 +729,7 @@ handle_schematics.place_building_using_voxelmanip = function( pos, binfo, replac
local extra_calls = { on_constr = {}, trees = {}, chests = {}, signs = {}, traders = {}, door_a = {}, door_b = {} };
-- last parameter false -> place dirt nodes instead of trying to keep the ground nodes
generate_building(pos, minp, maxp, data, param2_data, a, extranodes, replacements, cid, extra_calls, pos.building_nr, pos.village_id, binfo, cid.c_gravel, keep_ground);
generate_building(pos, minp, maxp, data, param2_data, a, extranodes, replacements, cid, extra_calls, pos.building_nr, pos.village_id, binfo, cid.c_gravel, keep_ground, scaffolding_only);
-- store the changed map data
vm:set_data(data);
@ -718,7 +747,7 @@ 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 )
handle_schematics.place_building_from_file = function( start_pos, end_pos, building_name, replacement_list, rotate, axis, mirror, no_plotmarker, keep_ground, scaffolding_only )
if( not( building_name )) then
return "No file name given. Cannot find the schematic.";
end
@ -768,7 +797,7 @@ handle_schematics.place_building_from_file = function( start_pos, end_pos, build
start_pos.no_plotmarker = no_plotmarker;
-- all those calls to on_construct need to be done now
local res = handle_schematics.place_building_using_voxelmanip( start_pos, binfo, replacement_list, keep_ground);
local res = handle_schematics.place_building_using_voxelmanip( start_pos, binfo, replacement_list, keep_ground, scaffolding_only);
if( not(res) or not( res.extra_calls )) then
return;
end