aboutsummaryrefslogtreecommitdiff
path: root/handle_schematics.lua
diff options
context:
space:
mode:
authorSokomine <wegwerf@anarres.dyndns.org>2014-02-25 21:41:29 +0100
committerSokomine <wegwerf@anarres.dyndns.org>2014-02-25 21:41:29 +0100
commit0da4a93f95284d6c876c71b2e7a1a8b0e6662e94 (patch)
tree5e00f8c8243d72c362f0d29a01a5bf4f46d0da5b /handle_schematics.lua
parent702ad26499ccad6fb037d1a1f0d26d56230ca00b (diff)
downloadapartment-0da4a93f95284d6c876c71b2e7a1a8b0e6662e94.tar.gz
apartment-0da4a93f95284d6c876c71b2e7a1a8b0e6662e94.tar.bz2
apartment-0da4a93f95284d6c876c71b2e7a1a8b0e6662e94.zip
improved building spawner chest
Diffstat (limited to 'handle_schematics.lua')
-rw-r--r--handle_schematics.lua339
1 files changed, 285 insertions, 54 deletions
diff --git a/handle_schematics.lua b/handle_schematics.lua
index 2cd0035..18e0bee 100644
--- a/handle_schematics.lua
+++ b/handle_schematics.lua
@@ -148,11 +148,12 @@ end
-- set up steel doors in a usable way;
-- set up apartments from the apartment mod;
-- placer is the player who initialized the placement of the schematic (placer will be passed on to after_place_node etc)
-handle_schematics.update_nodes = function( start_pos, end_pos, on_constr, after_place_node, placer )
+handle_schematics.update_nodes = function( start_pos, end_pos, on_constr, after_place_node, placer, extra_params )
local p={};
local i=0;
local v=0;
+
-- call on_construct for all the nodes that require it
for i, v in ipairs( on_constr ) do
@@ -187,34 +188,80 @@ handle_schematics.update_nodes = function( start_pos, end_pos, on_constr, after_
meta:set_string("infotext", "Owned by "..player_name)
end
+
-- prepare apartment rental panels
local nodes = minetest.find_nodes_in_area( start_pos, end_pos, {'apartment:apartment'} );
- for _, p in ipairs(nodes ) do
- local meta = minetest.get_meta( p );
- meta:set_string( 'original_owner', player_name );
+ if( extra_params and extra_params.apartment_type and extra_params.apartment_name ) then
+ for _, p in ipairs(nodes ) do
+ local meta = minetest.get_meta( p );
+ meta:set_string( 'original_owner', player_name );
+
+ -- lua can't count variables of this type on its own...
+ local nr = 1;
+ for _, _ in pairs( apartment.apartments ) do
+ nr = nr+1;
+ end
+ -- this depends on relative position and param2 of the formspec
+ local fields = {
+ quit=true, store=true,
+
+ size_up = math.abs( end_pos.y - p.y-1),
+ size_down = math.abs(start_pos.y - p.y),
+
+ norm_right = math.abs( end_pos.x - p.x-1),
+ norm_left = math.abs(start_pos.x - p.x),
+ norm_back = math.abs( end_pos.z - p.z-1),
+ norm_front = math.abs(start_pos.z - p.z),
+
+ category = extra_params.apartment_type,
+ -- numbering them all seems best
+ descr = extra_params.apartment_name
+ };
+
+ -- up and down are independent of rotation
+ fields.size_up = math.abs( end_pos.y - p.y-1);
+ fields.size_down = math.abs(start_pos.y - p.y);
+
+ local node = minetest.get_node( p );
+ if( node.param2 == 0 ) then -- z gets larger
+ fields.size_left = fields.norm_left; fields.size_right = fields.norm_right;
+ fields.size_back = fields.norm_back; fields.size_front = fields.norm_front;
+
+ elseif( node.param2 == 1 ) then -- x gets larger
+ fields.size_left = fields.norm_back; fields.size_right = fields.norm_front;
+ fields.size_back = fields.norm_right; fields.size_front = fields.norm_left;
- -- lua can't count variables of this type on its own...
- local nr = 1;
- for _, _ in pairs( apartment.apartments ) do
- nr = nr+1;
+ elseif( node.param2 == 2 ) then -- z gets smaller
+ fields.size_left = fields.norm_right; fields.size_right = fields.norm_left;
+ fields.size_back = fields.norm_front; fields.size_front = fields.norm_back;
+
+ elseif( node.param2 == 3 ) then -- x gets smaller
+ fields.size_left = fields.norm_front; fields.size_right = fields.norm_back;
+ fields.size_back = fields.norm_left; fields.size_front = fields.norm_right;
+ end
+
+ -- configure and prepare the apartment
+ apartment.on_receive_fields( p, nil, fields, placer);
end
- -- TODO: this depends on relative position and param2 of the formspec
- local fields = {
- quit=true, store=true,
- size_left=2, size_right=1, size_up=2, size_down=1, size_front=1, size_back=6,
- category='apartment',
- -- numbering them all seems best
- descr='Apartment #'..tostring( nr ) };
-
- -- configure and prepare the apartment
- apartment.on_receive_fields( p, nil, fields, placer);
end
+ end
+end
+
+-- this is lua...it doesn't contain the basic functions
+handle_schematics.table_contains = function( table, value )
+ local i = 1;
+ local v;
+ for i, v in ipairs( table ) do
+ if( v==value ) then
+ return true;
+ end
end
+ return false;
end
-handle_schematics.place_schematic = function( pos, param2, path, mirror, replacement_function, replacement_param, placer, do_copies )
+handle_schematics.place_schematic = function( pos, param2, path, mirror, replacement_function, replacement_param, placer, do_copies, extra_params )
local node = minetest.env:get_node( pos );
if( not( node ) or not( node.param2 ) or node.name=="air") then
@@ -225,6 +272,12 @@ handle_schematics.place_schematic = function( pos, param2, path, mirror, replace
end
local building_data = handle_schematics.analyze_mts_file( path );
+ if( not( building_data ) or not( building_data.size )) then
+ if( placer ) then
+ minetest.chat_send_player( placer:get_player_name(), 'Could not place schematic. Please check the filename.');
+ end
+ return;
+ end
local position_data = handle_schematics.translate_param2_to_rotation( node.param2, mirror, pos, building_data.size, building_data.rotated, building_data.burried );
local replacements = {};
@@ -241,13 +294,47 @@ handle_schematics.place_schematic = function( pos, param2, path, mirror, replace
force_place = false;
end
- table.insert( building_data.on_constr, 'default:chest' );
+
+ -- it is possible that replacements require calls to on_constr/after_place_node
+ -- and that the nodes that are introduced through replacements where not present in the original schematic
+ local all_replacements = {};
+ for i, v in ipairs( replacements ) do
+ table.insert( all_replacements, v[2] );
+ end
+ if( replacement_param and replacement_param.even and replacement_param.odd ) then
+ for i, v in ipairs( replacement_param.even ) do
+ table.insert( all_replacements, v[2] );
+ end
+ for i, v in ipairs( replacement_param.odd ) do
+ table.insert( all_replacements, v[2] );
+ end
+ end
+ for i, v in ipairs( all_replacements ) do
+
+ if( minetest.registered_nodes[ v ] and minetest.registered_nodes[ v ].on_construct
+ and not(handle_schematics.table_contains( building_data.on_constr, v ))) then
+ table.insert( building_data.on_constr, v );
+ end
+ -- some nodes need after_place_node to be called for initialization
+ if( minetest.registered_nodes[ v ] and minetest.registered_nodes[ v ].after_place_node
+ and not(handle_schematics.table_contains( building_data.after_place_node, v ))) then
+ table.insert( building_data.after_place_node, v );
+ end
+ end
+
+
+ -- apartments need a name if they are to be configured
+ if( extra_params and not( extra_params.apartment_type )) then
+ extra_params.apartment_type = 'apartment';
+ end
+
-- actually place the schematic
if( not( do_copies ) or not( do_copies.h ) or not( do_copies.v )) then
minetest.place_schematic( position_data.start_pos, path..'.mts', tostring(position_data.rotate), replacements, force_place );
handle_schematics.update_nodes( position_data.start_pos, position_data.end_pos,
- building_data.on_constr, building_data.after_place_node, placer );
+ building_data.on_constr, building_data.after_place_node, placer,
+ extra_params );
else
-- place multiple copies
local vector = {h=-1,v=1};
@@ -275,8 +362,39 @@ handle_schematics.place_schematic = function( pos, param2, path, mirror, replace
minetest.place_schematic( p, path..'.mts', tostring(position_data.rotate), replacements_odd, force_place );
end
+ -- generate apartment name
+ if( extra_params and extra_params.apartment_type and extra_params.apartment_house_name ) then
+ local nr = i-1;
+ local apartment_name = '';
+
+ -- find the first free number for an apartment with this apartment_house_name
+ while( nr < 99 and apartment_name == '' ) do
+ nr = nr+1;
+ apartment_name = extra_params.apartment_house_name..' '..tostring(j);
+ if( nr < 10 ) then
+ apartment_name = apartment_name..'0'..tostring(nr);
+ elseif( nr<100 ) then
+ apartment_name = apartment_name..tostring(nr);
+ else
+ apartment_name = '';
+ end
+
+ -- avoid duplicates
+ if( apartment.apartments[ apartment_name ] ) then
+ apartment_name = '';
+ end
+ end
+ if( apartment_name ) then
+ extra_params.apartment_name = apartment_name;
+ else
+ extra_params.apartment_name = nil;
+ extra_params.apartment_type = nil;
+ end
+
+ end
+ -- replacements_even/replacements_odd ought to affect only DECORATIVE nodes - and none that have on_construct/after_place_node!
handle_schematics.update_nodes( p, {x=p.x+position_data.max.x, y=p.y+position_data.max.y*j, z=p.z+position_data.max.z},
- building_data.on_constr, building_data.after_place_node, placer );
+ building_data.on_constr, building_data.after_place_node, placer, extra_params );
if( node.param2 == 0 or node.param2 == 2 ) then
p.x = p.x + vector.h*position_data.max.x;
@@ -322,6 +440,121 @@ handle_schematics.replacement_function_decay = function( nodenames )
return replacements;
end
+
+
+handle_schematics.update_apartment_spawner_formspec = function( pos )
+
+ local meta = minetest.get_meta( pos );
+
+ if( not( meta ) or not( meta:get_string('path')) or meta:get_string('path')=='') then
+ return 'size[9,7]'..
+ 'label[2.0,-0.3;Apartment Spawner]'..
+ 'label[0.5,0.5;Load schematic from file:]'..
+ 'field[5.0,0.9;4.0,0.5;path;;apartment_4x10_0_270]'..
+ 'label[0.5,1.5;Name for this apartment house:]'..
+ 'field[5.0,1.9;4.0,0.5;apartment_house_name;;Enter house name]'..
+ 'label[0.5,2.0;Category (i.e. house, shop):]'..
+ 'field[5.0,2.4;4.0,0.5;apartment_type;;apartment]'..
+ 'label[0.5,2.5;Horizontal copies (to the left):]'..
+ 'field[5.0,2.9;0.5,0.5;h;;1]'..
+ 'label[0.5,3.0;Vertical copies (upwards):]'..
+ 'field[5.0,3.4;0.5,0.5;v;;1]'..
+ 'label[0.5,3.5;Replace clay in 1st building:]'..
+ 'field[5.0,3.9;4.0,0.5;replacement_1;;default:sandstonebrick]'..
+ 'label[0.5,4.0;Replace clay in 2nd building:]'..
+ 'field[5.0,4.4;4.0,0.5;replacement_2;;default:brick]'..
+ 'button_exit[4,6.0;2,0.5;store;Spawn building]'..
+ 'button_exit[1,6.0;1,0.5;abort;Abort]';
+ end
+ return 'size[9,7]'..
+ 'label[2.0,-0.3;Information about the spawned Apartment]'..
+ 'label[0.5,0.5;The schematic was loaded from:]'..
+ 'label[5.0,0.5;'..tostring( meta:get_string('path'))..']'..
+ 'label[0.5,1.5;Name for this apartment house:]'..
+ 'label[5.0,1.5;'..tostring( meta:get_string('apartment_house_name'))..']'..
+ 'label[0.5,2.0;Category (i.e. house, shop):]'..
+ 'label[5.0,2.0;'..tostring( meta:get_string('apartment_type'))..']'..
+ 'label[0.5,2.5;Horizontal copies (to the left):]'..
+ 'label[5.0,2.5;'..tostring( meta:get_string('h'))..']'..
+ 'label[0.5,3.0;Vertical copies (upwards):]'..
+ 'label[5.0,3.0;'..tostring( meta:get_string('v'))..']'..
+ 'label[0.5,3.5;Replace clay in 1st building:]'..
+ 'label[5.0,3.5;'..tostring( meta:get_string('replacement_1'))..']'..
+ 'label[0.5,4.0;Replace clay in 2nd building:]'..
+ 'label[5.0,4.0;'..tostring( meta:get_string('replacement_2'))..']'..
+ 'label[0.5,4.5;This building was spawned by:]'..
+ 'label[5.0,4.5;'..tostring( meta:get_string('placed_by'))..']'..
+ 'button_exit[4,6.0;2,0.5;store;Remove building]'..
+ 'button_exit[1,6.0;1,0.5;abort;OK]';
+end
+
+
+handle_schematics.on_receive_fields = function(pos, formname, fields, sender)
+
+ local meta = minetest.get_meta( pos );
+
+ if( not( sender )) then
+ return;
+ end
+
+ pname = sender:get_player_name();
+ if( not( minetest.check_player_privs(pname, {apartment_unrent=true}))) then
+ minetest.chat_send_player( pname, 'You do not have the necessary privileges.');
+ return;
+ end
+
+ if( meta and (not( meta:get_string('path')) or meta:get_string('path')=='') and fields.store) then
+
+ -- check if all params have been supplied
+ if( not( fields.path )
+ or not( fields.apartment_house_name ) or not( fields.apartment_type )
+ or not( fields.h ) or not( fields.v )
+ or not( fields.replacement_1 ) or not( fields.replacement_2 )) then
+ minetest.chat_send_player( pname, 'Please fill all fields with information.');
+ return;
+ end
+
+ fields.h = tonumber( fields.h );
+ if( fields.h < 1 or fields.h > 20 ) then
+ fields.h = 1;
+ end
+ fields.h = tostring( fields.h );
+ fields.v = tonumber( fields.v );
+ if( fields.v < 1 or fields.v > 20 ) then
+ fields.v = 1;
+ end
+ fields.v = tostring( fields.v );
+
+ meta:set_string('path', fields.path );
+ meta:set_string('apartment_house_name', fields.apartment_house_name );
+ meta:set_string('apartment_type', fields.apartment_type );
+ meta:set_string('h', fields.h );
+ meta:set_string('v', fields.v );
+ meta:set_string('replacement_1', fields.replacement_1 );
+ meta:set_string('replacement_2', fields.replacement_2 );
+ meta:set_string('placed_by', pname );
+
+ meta:set_string('formspec', handle_schematics.update_apartment_spawner_formspec( pos ));
+ minetest.chat_send_player( pname, 'Placing building '..tostring( fields.path ));
+
+ local path = minetest.get_modpath("apartment")..'/schems/'..fields.path;
+ local mirror = 0;
+ local replacement_function = nil;
+ local replacement_param = { odd={{'default:clay',fields.replacement_1}},
+ even={{'default:clay',fields.replacement_2}}};
+
+ handle_schematics.place_schematic( pos, nil, path, mirror,
+ replacement_function, replacement_param,
+ sender, {h=fields.h,v=fields.v},
+ { apartment_type = fields.apartment_type, apartment_house_name = fields.apartment_house_name})
+ return;
+ end
+ -- TODO
+ minetest.chat_send_player( pname, 'NOT YET IMPLEMENTED.');
+end
+
+
+
local filename = "apartment_4x10_0_270";
--local filename = "apartment_4x6_0_90";
@@ -334,54 +567,52 @@ minetest.register_node("apartment:build_chest", {
legacy_facedir_simple = true,
after_place_node = function(pos, placer, itemstack)
-
--- TODO: check if placement is allowed; read parameters (how many? what to replace? which schematic?) etc.
--- local path = minetest.get_modpath("apartment")..'/schems/apartment_4x6_0_90';
- local path = minetest.get_modpath("apartment")..'/schems/'..filename;
- local mirror = 0;
- local replacement_function = nil;
- local replacement_param = { odd={{'default:clay','default:sandstonebrick'},
- {'inbox:empty','default:chest'},
- {'travelnet:travelnet','default:furnace'},
- {'stairs:slab_junglewood','stairs:slab_wood'},
- {'stairs:stair_junglewood','stairs:stair_wood'}},
- even={{'default:clay','default:brick'},
- {'inbox:empty','default:chest'},
- {'travelnet:travelnet','default:furnace'},
- {'stairs:slab_junglewood','stairs:slab_wood'},
- {'stairs:stair_junglewood','stairs:stair_wood'}}};
-
--- replacement_param = { odd={{'default:clay','default:desert_stone'},{'stairs:slab_junglewood','stairs:slab_sandstone'},{'stairs:stair_junglewood','stairs:stair_sandstone'}},
--- even={{'default:clay','default:desert_stone'},{'stairs:slab_junglewood','stairs:slab_sandstone'},{'stairs:stair_junglewood','stairs:stair_sandstone'}}};
-
- minetest.chat_send_player( placer:get_player_name(), 'Placing building '..tostring( path ));
-
- minetest.chat_send_player( placer:get_player_name(), 'Placing building '..tostring( path ));
- handle_schematics.place_schematic( pos, nil, path, mirror, replacement_function, replacement_param, placer, {h=8,v=6} )
+ local meta = minetest.get_meta( pos );
+ meta:set_string('formspec', handle_schematics.update_apartment_spawner_formspec( pos ));
end,
+ on_receive_fields = function( pos, formname, fields, sender )
+ handle_schematics.on_receive_fields(pos, formname, fields, sender)
+ end,
+
-- if the building chest is removed, remove the building as well - and place nodes looking like leaves and autodecaying in order
-- to indicate where the building has been
after_dig_node = function(pos, oldnode, oldmetadata, digger)
+ local meta = minetest.get_meta( pos );
+
+ -- TODO: remove the correct building
local path = minetest.get_modpath("apartment")..'/schems/'..filename;
local mirror = 0;
local replacement_function = handle_schematics.replacement_function_decay;
local replacement_param = nil;
minetest.chat_send_player( digger:get_player_name(), 'Removing building '..tostring( path ));
- handle_schematics.place_schematic( pos, oldnode.param2, path, mirror, replacement_function, replacement_param, digger, {h=8,v=6} )
+ handle_schematics.place_schematic( pos, oldnode.param2, path, mirror, replacement_function, replacement_param, digger, {h=4,v=3} )
end,
--- TODO: check if digging is allowed
+
+ -- check if digging is allowed
+ can_dig = function(pos,player)
+
+ if( not( player )) then
+ return false;
+ end
+ local pname = player:get_player_name();
+ if( not( minetest.check_player_privs(pname, {apartment_unrent=true}))) then
+ minetest.chat_send_player( pname, 'You do not have the apartment_unrent priv which is necessary to dig this node.');
+ return false;
+ end
+ local meta = minetest.get_meta( pos );
+ local old_placer = meta:get_string('placed_by');
+ if( old_placer and old_placer ~= '' and old_placer ~= pname ) then
+ minetest.chat_send_player( pname, 'Only '..tostring( old_placer )..' can dig this node.');
+ return false;
+ end
+ return true;
+ end,
})
--- local p1={x=position_data.start_pos.x, y=position_data.start_pos.y, z=position_data.start_pos.z };
--- local p2={x=position_data.end_pos.x, y=position_data.end_pos.y, z=position_data.end_pos.z };
--- minetest.set_node( {x=p1.x, y=p1.y, z=p1.z }, {name='wool:red'} );
--- minetest.set_node( {x=p1.x, y=p1.y, z=p2.z }, {name='wool:red'} );
--- minetest.set_node( {x=p2.x, y=p1.y, z=p1.z }, {name='wool:red'} );
--- minetest.set_node( {x=p2.x, y=p2.y, z=p2.z }, {name='wool:red'} );
minetest.register_node( handle_schematics.AUTODECAY, {
description = "decaying building",