Update mg_villages and handle_schematics, update wood door textures

BadToad2000/master
Brandon 2016-07-09 14:57:39 -05:00
parent 0382ebf627
commit 3caca9b881
16 changed files with 658 additions and 180 deletions

View File

@ -461,7 +461,7 @@ end
function randomChance (percent)
math.randomseed( os.clock() )
return percent >= math.random(1, 100)
return percent >= ( math.random(1000, 100000) / 1000 )
end
function default.tprint (tbl, indent)

View File

@ -416,15 +416,10 @@ function doors.register(name, def)
end
doors.register("door_wood", {
tiles = {{ name = "doors_door_wood.png", backface_culling = true }},
tiles = {{ name = "[combine:32x38:0,0=default_wood.png:0,16=default_wood.png:0,32=default_wood.png:16,0=default_wood.png:16,16=default_wood.png:16,32=default_wood.png^[transformR270^[colorize:#fff:30^ts_doors_base.png^[noalpha^[makealpha:0,255,0", backface_culling = true }},
inventory_image = "[combine:32x38:0,0=default_wood.png:0,16=default_wood.png:16,0=default_wood.png:16,16=default_wood.png^[transformR270^[colorize:#fff:30^ts_doors_base_inv.png^[noalpha^[makealpha:0,255,0",
description = "Wooden Door",
inventory_image = "doors_item_wood.png",
groups = { snappy = 1, choppy = 2, oddly_breakable_by_hand = 2, flammable = 2 },
recipe = {
{"group:wood", "group:wood"},
{"group:wood", "group:wood"},
{"group:wood", "group:wood"},
}
groups = { snappy = 1, choppy = 2, flammable = 2 },
})
doors.register("door_steel", {
@ -724,33 +719,27 @@ doors.register_fencegate("doors:gate_wood", {
description = "Wooden Fence Gate",
texture = "default_wood.png",
material = "default:wood",
groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}
groups = {choppy = 2, flammable = 2}
})
doors.register_fencegate("doors:gate_acacia_wood", {
description = "Acacia Fence Gate",
texture = "default_acacia_wood.png",
material = "default:acacia_wood",
groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}
doors.register_fencegate("doors:gate_savanna_wood", {
description = "Savana Fence Gate",
texture = "mg_dry_wood.png",
material = "mg:savannawood",
groups = {choppy = 2, flammable = 2}
})
doors.register_fencegate("doors:gate_junglewood", {
description = "Junglewood Fence Gate",
texture = "default_junglewood.png",
material = "default:junglewood",
groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}
groups = {choppy = 2, flammable = 2}
})
doors.register_fencegate("doors:gate_pine_wood", {
description = "Pine Fence Gate",
texture = "default_pine_wood.png",
material = "default:pine_wood",
groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}
texture = "mg_pine_wood.png",
material = "mg:pinewood",
groups = {choppy = 2, flammable = 2}
})
doors.register_fencegate("doors:gate_aspen_wood", {
description = "Aspen Fence Gate",
texture = "default_aspen_wood.png",
material = "default:aspen_wood",
groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}
})

View File

@ -277,6 +277,38 @@ end
-- offer diffrent replacement groups
handle_schematics.get_formspec_group_replacement = function( pos, fields, formspec )
if( fields.set_wood and fields.set_wood ~= "" ) then
return formspec..
"label[1,2.2;Select replacement for "..tostring( fields.set_wood )..".]"..
"label[1,2.5;Trees, saplings and other blocks will be replaced accordingly as well.]"..
-- invisible field that encodes the value given here
"field[-20,-20;0.1,0.1;set_wood;;"..minetest.formspec_escape( fields.set_wood ).."]"..
build_chest.replacements_get_group_list_formspec( pos, 'wood', 'wood_selection' );
end
if( fields.set_farming and fields.set_farming ~= "" ) then
return formspec..
"label[1,2.5;Select the fruit the farm is going to grow:]"..
-- invisible field that encodes the value given here
"field[-20,-20;0.1,0.1;set_farming;;"..minetest.formspec_escape( fields.set_farming ).."]"..
build_chest.replacements_get_group_list_formspec( pos, 'farming', 'farming_selection' );
end
if( fields.set_roof and fields.set_roof ~= "" ) then
return formspec..
"label[1,2.5;Select a roof type for the house:]"..
-- invisible field that encodes the value given here
"field[-20,-20;0.1,0.1;set_roof;;"..minetest.formspec_escape( fields.set_roof ).."]"..
build_chest.replacements_get_group_list_formspec( pos, 'roof', 'roof_selection' );
end
return nil;
end
build_chest.update_formspec = function( pos, page, player, fields )
-- information about the village the build chest may belong to and about the owner
@ -286,10 +318,45 @@ build_chest.update_formspec = function( pos, page, player, fields )
local owner_name = meta:get_string( 'owner' );
local building_name = meta:get_string('building_name' );
-- are we dealing with a plotmarker inside a village?
local village_id = meta:get_string( 'village_id' );
local plot_nr = meta:get_int( 'plot_nr' );
if( village_id
and village_id~=""
and plot_nr
and plot_nr>0
and mg_villages.all_villages
and mg_villages.all_villages[ village_id ]
and mg_villages.all_villages[ village_id ].to_add_data.bpos
and mg_villages.all_villages[ village_id ].to_add_data.bpos[ plot_nr ]) then
local v = mg_villages.all_villages[ village_id ];
village_name = v.name;
-- the center of the village
village_pos = { x = v.vx, y = v.vh, z = v.vz };
-- who has bought the plot?
owner_name = v.to_add_data.bpos[ plot_nr ].owner;
building_name = v.to_add_data.bpos[ plot_nr ].btype;
-- get the name of the blueprint the building was created from
if( mg_villages.BUILDINGS[ building_name ] ) then
building_name = tostring( mg_villages.BUILDINGS[ building_name ].scm );
end
-- we also know where the building will start and end
-- TODO: these may need to be set
--local start_pos = meta:get_string('start_pos');
--local end_pos = minetest.deserialize( meta:get_string('end_pos'));
--local rotate = meta:get_string('rotate');
--local mirror = meta:get_string('mirror');
else
village_id = "";
plot_nr = -1;
end
-- distance from village center
local distance = math.floor( math.sqrt( (village_pos.x - pos.x ) * (village_pos.x - pos.x )
+ (village_pos.y - pos.y ) * (village_pos.x - pos.y )
+ (village_pos.z - pos.z ) * (village_pos.x - pos.z ) ));
+ (village_pos.y - pos.y ) * (village_pos.y - pos.y )
+ (village_pos.z - pos.z ) * (village_pos.z - pos.z ) ));
-- 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
@ -321,6 +388,28 @@ build_chest.update_formspec = function( pos, page, player, fields )
"label[3.3,1.6;Click on a menu entry to select it:]"..
build_chest.show_size_data( building_name );
if( fields.show_materials and fields.show_materials ~= "" ) then
-- do not allow any changes; just show the materials and their replacements
return formspec..build_chest.replacements_get_list_formspec( pos, nil, 0, meta, village_id, building_name, -1 );
end
-- are we dealing with a plotmarker? if so, we are finished here
-- (we mostly wanted the header and the option to see the replacements)
if( village_id and village_id ~= "" ) then
-- TODO: actually implement the villages_* functions
return formspec.."button[3,3;3,0.5;villages_create_backup;Create backup of current stage]"..
"button[3,4;3,0.5;show_materials;Show materials used]"..
"button[3,5;3,0.5;villages_reset_building;Reset building]"..
"button[3,3;3,0.5;villages_remove_building;Remove building]";
end
-- the building has been placed; offer to restore a backup
local backup_file = meta:get_string('backup');
if( backup_file and backup_file ~= "" ) then
return formspec.."button[3,3;3,0.5;restore_backup;Restore original landscape]"..
"button[3,4;3,0.5;show_materials;Show materials used]";
end
local current_path = minetest.deserialize( meta:get_string( 'current_path' ) or 'return {}' );
if( #current_path > 0 ) then
formspec = formspec.."button[9.9,0.4;2,0.5;back;Back]";
@ -340,46 +429,27 @@ build_chest.update_formspec = function( pos, page, player, fields )
end
-- offer diffrent replacement groups
if( fields.set_wood and fields.set_wood ~= "" ) then
return formspec..
"label[1,2.2;Select replacement for "..tostring( fields.set_wood )..".]"..
"label[1,2.5;Trees, saplings and other blocks will be replaced accordingly as well.]"..
-- invisible field that encodes the value given here
"field[-20,-20;0.1,0.1;set_wood;;"..minetest.formspec_escape( fields.set_wood ).."]"..
build_chest.replacements_get_group_list_formspec( pos, 'wood', 'wood_selection' );
end
if( fields.set_farming and fields.set_farming ~= "" ) then
return formspec..
"label[1,2.5;Select the fruit the farm is going to grow:]"..
-- invisible field that encodes the value given here
"field[-20,-20;0.1,0.1;set_farming;;"..minetest.formspec_escape( fields.set_farming ).."]"..
build_chest.replacements_get_group_list_formspec( pos, 'farming', 'farming_selection' );
end
if( fields.set_roof and fields.set_roof ~= "" ) then
return formspec..
"label[1,2.5;Select a roof type for the house:]"..
-- invisible field that encodes the value given here
"field[-20,-20;0.1,0.1;set_roof;;"..minetest.formspec_escape( fields.set_roof ).."]"..
build_chest.replacements_get_group_list_formspec( pos, 'roof', 'roof_selection' );
local formspec_group_replacement = handle_schematics.get_formspec_group_replacement( pos, fields, formspec );
if( formspec_group_replacement ) then
return formspec_group_replacement;
end
if( fields.preview and building_name ) then
return formspec..build_chest.preview_image_formspec( building_name,
minetest.deserialize( meta:get_string( 'replacements' )), fields.preview);
build_chest.replacements_get_current( meta, village_id ), fields.preview);
end
-- show list of all node names used
local start_pos = meta:get_string('start_pos');
if( building_name and building_name ~= '' and start_pos and start_pos ~= '' and meta:get_string('replacements')) then
return formspec..build_chest.replacements_get_list_formspec( pos );
-- allow changes to the replacement list
return formspec..build_chest.replacements_get_list_formspec( pos, nil, 1, meta, village_id, building_name, -1 );
end
-- find out where we currently are in the menu tree
local menu = build_chest.menu;
for i,v in pairs( current_path ) do
for i,v in ipairs( current_path ) do
if( menu and menu[ v ] ) then
menu = menu[ v ];
end
@ -408,9 +478,12 @@ build_chest.update_formspec = function( pos, page, player, fields )
-- do replacements for realtest where necessary (this needs to be done only once)
local replacements = {};
replacements_group['realtest'].replace( replacements );
-- do replacements for nodes that no longer exist
replacements_group['discontinued_nodes'].replace( replacements );
meta:set_string( 'replacements', minetest.serialize( replacements ));
return formspec..build_chest.replacements_get_list_formspec( pos );
-- allow changes to be made
return formspec..build_chest.replacements_get_list_formspec( pos, nil, 1, meta, village_id, building_name, -1 );
elseif( type(start_pos)=='string' ) then
return formspec.."label[3,3;Error reading building data:]"..
"label[3.5,3.5;"..start_pos.."]";
@ -560,21 +633,21 @@ build_chest.on_receive_fields = function(pos, formname, fields, player)
and fields.replace_row_with and fields.replace_row_with ~= ""
and fields.replace_row_material and fields.replace_row_material ~= "") then
build_chest.replacements_apply( pos, meta, fields.replace_row_material, fields.replace_row_with );
build_chest.replacements_apply( pos, meta, fields.replace_row_material, fields.replace_row_with, nil );
elseif( fields.replace_rest_with_air ) then
build_chest.replacements_replace_rest_with_air( pos, meta );
elseif( fields.wood_selection ) then
build_chest.replacements_apply_for_group( pos, meta, 'wood', fields.wood_selection, fields.set_wood );
build_chest.replacements_apply_for_group( pos, meta, 'wood', fields.wood_selection, fields.set_wood, nil );
fields.set_wood = nil;
elseif( fields.farming_selection ) then
build_chest.replacements_apply_for_group( pos, meta, 'farming', fields.farming_selection, fields.set_farming );
build_chest.replacements_apply_for_group( pos, meta, 'farming', fields.farming_selection, fields.set_farming, nil );
fields.set_farming = nil;
elseif( fields.roof_selection ) then
build_chest.replacements_apply_for_group( pos, meta, 'roof', fields.roof_selection, fields.set_roof );
build_chest.replacements_apply_for_group( pos, meta, 'roof', fields.roof_selection, fields.set_roof, nil );
fields.set_roof = nil;
@ -600,7 +673,7 @@ build_chest.on_receive_fields = function(pos, formname, fields, player)
end
-- TODO: use scaffolding here (exchange some replacements)
local replacement_list = minetest.deserialize( meta:get_string( 'replacements' ));
local replacement_list = build_chest.replacements_get_current( meta, village_id );
local rotate = meta:get_string('rotate');
local mirror = meta:get_string('mirror');
local axis = build_chest.building[ building_name ].axis;
@ -608,7 +681,7 @@ 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 );
fields.error_msg = handle_schematics.place_building_from_file( start_pos, end_pos, building_name, replacement_list, rotate, axis, mirror, no_plotmarker, false );
if( fields.error_msg ) then
fields.error_msg = 'Error: '..tostring( fields.error_msg );
end

View File

@ -41,12 +41,12 @@ end
-- search for mods and modpacks containing schematics in any form
local build_chest_check_all_directories_mods_and_modpacks = function( path, menu_title, gamename )
local d2 = minetest.get_dir_list( path..'/mods', true );
for _,modname in pairs( d2 ) do
for _,modname in ipairs( d2 ) do
local d3 = minetest.get_dir_list( path..'/mods/'..modname, true );
for _,subdir in pairs( d3 ) do
for _,subdir in ipairs( d3 ) do
if( subdir ~= 'textures' and subdir ~= 'sounds' and subdir ~= 'models' and subdir ~= '.git' and subdir ~= 'locale') then
local d4 = minetest.get_dir_list( path..'/mods/'..modname..'/'..subdir, false );
for _,filename in pairs( d4 ) do
for _,filename in ipairs( d4 ) do
build_chest_add_files_to_menu_from_directory(
filename,
path..'/mods/'..modname..'/'..subdir..'/',
@ -56,10 +56,10 @@ local build_chest_check_all_directories_mods_and_modpacks = function( path, menu
end
-- it might be a modpack
d4 = minetest.get_dir_list( path..'/mods/'..modname..'/'..subdir, true );
for _,subsubdir in pairs( d4 ) do
for _,subsubdir in ipairs( d4 ) do
if( subsubdir ~= 'textures' and subsubdir ~= 'sounds' and subsubdir ~= 'models' and subsubdir ~= '.git' and subsubdir ~= 'locale') then
local d5 = minetest.get_dir_list( path..'/mods/'..modname..'/'..subdir..'/'..subsubdir, false );
for _,filename in pairs( d5 ) do
for _,filename in ipairs( d5 ) do
build_chest_add_files_to_menu_from_directory(
filename,
path..'/mods/'..modname..'/'..subdir..'/'..subsubdir..'/',
@ -75,6 +75,28 @@ local build_chest_check_all_directories_mods_and_modpacks = function( path, menu
end
end
build_chest.add_files_from_path = function( worldpath, worldname )
-- get list of subdirectories
local path = worldpath..'/'..worldname;
local subdir_list = minetest.get_dir_list( path, true );
if( not( subdir_list )) then
return;
end
for _,subdir in ipairs( subdir_list ) do
if( subdir=='schems' ) then
local file_list = minetest.get_dir_list( path..'/schems', false );
for _,filename in ipairs( file_list ) do
build_chest_add_files_to_menu_from_directory(
filename,
path..'/schems/',
'import from world',
'landscape backups',
{'OVERWRITE THIS', worldname });
end
end
end
end
local build_chest_check_all_directories = function()
-- find the name of the directory directly above the current worldpath
@ -106,27 +128,12 @@ local build_chest_check_all_directories = function()
end
end
--]]
worldpath = string.sub( worldpath, 1, string.len( worldpath )-p );
-- worldpath = string.sub( worldpath, 1, string.len( worldpath )-p );
-- locate .mts, .wem and .we files in the worlds/WORLDNAME/schems/* folders
local d1 = minetest.get_dir_list( worldpath, true );
for _,worldname in pairs( d1 ) do
-- get list of subdirectories
local d2 = minetest.get_dir_list( worldpath..'/'..worldname, true );
for _,subdir in pairs( d2 ) do
if( subdir=='schems' ) then
local d3 = minetest.get_dir_list( worldpath..'/'..worldname..'/schems', false );
for _,filename in pairs( d3 ) do
build_chest_add_files_to_menu_from_directory(
filename,
worldpath..'/'..worldname..'/schems/',
'import from world',
'landscape backups',
{'OVERWRITE THIS', worldname });
end
end
end
for _,worldname in ipairs( d1 ) do
build_chest.add_files_from_path( worldpath, worldname );
end
local main_path = string.sub( worldpath, 1, string.len(worldpath)-string.len('/worlds'));
@ -137,7 +144,7 @@ local build_chest_check_all_directories = function()
-- search in all GAMES/* folders for mods containing schematics
local game_path = main_path..'/games';
d1 = minetest.get_dir_list( game_path, true );
for _,gamename in pairs( d1 ) do
for _,gamename in ipairs( d1 ) do
build_chest_check_all_directories_mods_and_modpacks( game_path..'/'..gamename, 'import from game', gamename );
end
end
@ -149,7 +156,7 @@ if( minetest.setting_getbool( 'secure.enable_security' )) then
local worldpath = minetest.get_worldpath();
local d3 = minetest.get_dir_list( worldpath..'/schems', false );
if( d3 ) then
for _,filename in pairs( d3 ) do
for _,filename in ipairs( d3 ) do
build_chest_add_files_to_menu_from_directory(
filename,
worldpath..'/schems/',

View File

@ -2,17 +2,52 @@
--- contains the handling of replacements for the build chest
-------------------------------------------------------------
build_chest.replacements_get_current = function( meta, village_id )
-- villages have their own replacement list for the entire village
if( village_id~=""
and mg_villages.all_villages
and mg_villages.all_villages[ village_id ]
and mg_villages.all_villages[ village_id ].to_add_data
and mg_villages.all_villages[ village_id ].to_add_data.replacements) then
return mg_villages.all_villages[ village_id ].to_add_data.replacements;
end
-- but usually, we store the replacement list in the build chest itself
return minetest.deserialize( meta:get_string( 'replacements' ));
end
-- store the new set of replacements
build_chest.replacements_set_current = function( meta, village_id, replacements )
-- villages have their own replacement list for the entire village
if( village_id~=""
and mg_villages.all_villages
and mg_villages.all_villages[ village_id ]
and mg_villages.all_villages[ village_id ].to_add_data
and mg_villages.all_villages[ village_id ].to_add_data.replacements) then
mg_villages.all_villages[ village_id ].to_add_data.replacements = replacements;
end
-- but usually, we store the replacement list in the build chest itself
meta:set_string( 'replacements', minetest.serialize( replacements ));
end
-- internal function
build_chest.replacements_get_extra_buttons = function( group, name, types_found_list, button_name, extra_buttons )
-- find out if there are any nodes that may need a group replacement
local found_type = "";
for k,w in pairs( replacements_group[ group ].all ) do
for k,w in ipairs( replacements_group[ group ].all ) do
-- we have found the full block of that group type
if( name == w ) then
found_type = w;
-- no primary node found; there may still be subordinate types
else
for nr,t in pairs( replacements_group[ group ].data[ w ] ) do
for nr,t in ipairs( replacements_group[ group ].data[ w ] ) do
if( name==t and not( types_found_list[ w ])) then
found_type = w;
end
@ -33,17 +68,18 @@ end
build_chest.replacements_get_list_formspec = function( pos, selected_row )
build_chest.replacements_get_list_formspec = function( pos, selected_row, allow_changes, meta, village_id, building_name, replace_row )
if( not( pos )) then
return "";
end
local meta = minetest.env:get_meta( pos );
local replacements = minetest.deserialize( meta:get_string( 'replacements' ));
local building_name = meta:get_string( 'building_name' );
local replacements = build_chest.replacements_get_current( meta, village_id );
if( replace_row == -1 and meta and (not( building_name ) or building_name =="" )) then
building_name = meta:get_string( 'building_name' );
replace_row = meta:get_int('replace_row');
end
if( not( building_name ) or not( build_chest.building[ building_name ])) then
return "";
end
local replace_row = meta:get_int('replace_row');
local formspec = "tableoptions[" ..
"color=#ff8000;" ..
@ -85,14 +121,14 @@ build_chest.replacements_get_list_formspec = function( pos, selected_row )
local types_found_list_roof = {};
local not_the_first_entry = false;
for i,v in pairs( build_chest.building[ building_name ].statistic ) do
for i,v in ipairs( build_chest.building[ building_name ].statistic ) do
local name = build_chest.building[ building_name ].nodenames[ v[1]];
-- nodes that are to be ignored do not need to be replaced
if( name ~= 'air' and name ~= 'ignore' and name ~= 'mg:ignore' and v[2] and v[2]>0) then
local anz = v[2];
-- find out if this node name gets replaced
local repl = name;
for j,r in pairs( replacements ) do
for j,r in ipairs( replacements ) do
if( r and r[1]==name ) then
repl = r[2];
end
@ -129,9 +165,11 @@ build_chest.replacements_get_list_formspec = function( pos, selected_row )
end
end
extra_buttons = build_chest.replacements_get_extra_buttons( 'wood', name, types_found_list_wood, 'set_wood', extra_buttons );
extra_buttons = build_chest.replacements_get_extra_buttons( 'farming', name, types_found_list_farming, 'set_farming', extra_buttons );
extra_buttons = build_chest.replacements_get_extra_buttons( 'roof', name, types_found_list_farming, 'set_roof', extra_buttons );
if( allow_changes==1 ) then
extra_buttons = build_chest.replacements_get_extra_buttons( 'wood', name, types_found_list_wood, 'set_wood', extra_buttons );
extra_buttons = build_chest.replacements_get_extra_buttons( 'farming', name, types_found_list_farming, 'set_farming', extra_buttons );
extra_buttons = build_chest.replacements_get_extra_buttons( 'roof', name, types_found_list_farming, 'set_roof', extra_buttons );
end
j=j+1;
@ -139,13 +177,20 @@ build_chest.replacements_get_list_formspec = function( pos, selected_row )
end
end
formspec = formspec.."]";
-- add the proceed-button as soon as all unkown materials have been replaced
if( may_proceed ) then
formspec = formspec.."button[9.9,9.0;2.0,0.5;proceed_with_scaffolding;Proceed]";
else
formspec = formspec.."button[9.9,9.0;3.2,0.5;replace_rest_with_air;Suggest air for unknown]";
if( allow_changes==0) then
return formspec.."label[0.5,2.1;Materials and replacements used:]"..
-- the back button returns a diffrent (unimportant) value here so that we don't accidently go too far back
"button[9.9,0.4;2,0.5;back_from_show_materials;Back]";
end
if( meta ) then
-- add the proceed-button as soon as all unkown materials have been replaced
if( may_proceed ) then
formspec = formspec.."button[9.9,9.0;2.0,0.5;proceed_with_scaffolding;Proceed]";
else
formspec = formspec.."button[9.9,9.0;3.2,0.5;replace_rest_with_air;Suggest air for unknown]";
end
formspec = formspec.."button[9.9,1.0;2.0,0.5;preview;Preview]";
end
formspec = formspec.."button[9.9,1.0;2.0,0.5;preview;Preview]";
if( extra_buttons.text and extra_buttons.text ~= "" ) then
formspec = formspec..extra_buttons.text..
"label[9.9,2.8;Replace by type:]";
@ -172,13 +217,13 @@ build_chest.replacements_replace_rest_with_air = function( pos, meta )
return;
end
local replacements_orig = minetest.deserialize( meta:get_string( 'replacements' ));
for i,v in pairs( build_chest.building[ building_name ].statistic ) do
for i,v in ipairs( build_chest.building[ building_name ].statistic ) do
local name = build_chest.building[ building_name ].nodenames[ v[1]];
-- nodes that are to be ignored do not need to be replaced
if( name ~= 'air' and name ~= 'ignore' and name ~= 'mg:ignore' and v[2] and v[2]>0) then
-- find out if this node name gets replaced
local repl = name;
for j,r in pairs( replacements_orig ) do
for j,r in ipairs( replacements_orig ) do
if( r and r[1]==name ) then
repl = r[2];
-- set replacements for inexisting nodes to air
@ -200,14 +245,14 @@ end
build_chest.replacements_apply = function( pos, meta, old_material, new_material )
build_chest.replacements_apply = function( pos, meta, old_material, new_material, village_id )
-- a new value has been entered - we do not need to remember the row any longer
meta:set_int('replace_row', 0 );
local found = false;
-- only accept replacements which can actually be placed
if( new_material=='air' or minetest.registered_nodes[ new_material ] ) then
local replacements_orig = minetest.deserialize( meta:get_string( 'replacements' ));
for i,v in pairs(replacements_orig) do
local replacements_orig = build_chest.replacements_get_current( meta, village_id );
for i,v in ipairs(replacements_orig) do
if( v and v[1]==old_material ) then
v[2] = new_material;
found = true;
@ -217,14 +262,14 @@ build_chest.replacements_apply = function( pos, meta, old_material, new_material
table.insert( replacements_orig, { old_material, new_material });
end
-- store the new set of replacements
meta:set_string( 'replacements', minetest.serialize( replacements_orig ));
build_chest.replacements_set_current( meta, village_id, replacements_orig );
end
end
build_chest.replacements_get_group_list_formspec = function( pos, group, button_name )
local formspec = "";
for i,v in pairs( replacements_group[ group ].found ) do
for i,v in ipairs( replacements_group[ group ].found ) do
formspec = formspec.."item_image_button["..tostring(((i-1)%8)+1)..","..
tostring(3+math.floor((i-1)/8))..";1,1;"..
tostring( v )..";"..tostring( button_name )..";"..tostring(i).."]";
@ -233,24 +278,24 @@ build_chest.replacements_get_group_list_formspec = function( pos, group, button_
end
build_chest.replacements_apply_for_group = function( pos, meta, group, selected, old_material )
build_chest.replacements_apply_for_group = function( pos, meta, group, selected, old_material, village_id )
local nr = tonumber( selected );
if( not(nr) or nr <= 0 or nr > #replacements_group[ group ].found ) then
return;
end
local new_material = replacements_group[ group ].found[ nr ];
if( old_material and old_material == new_material ) then
return;
end
-- if( old_material and old_material == new_material ) then
-- return;
-- end
local replacements = minetest.deserialize( meta:get_string( 'replacements' ));
local replacements = build_chest.replacements_get_current( meta, village_id );
if( not( replacements )) then
replacements = {};
end
replacements_group[ group ].replace_material( replacements, old_material, new_material );
-- store the new set of replacements
meta:set_string( 'replacements', minetest.serialize( replacements ));
build_chest.replacements_set_current( meta, village_id, replacements );
end

View File

@ -134,7 +134,7 @@ build_chest.preview_image_formspec = function( building_name, replacements, side
local side_names = {"front","right","back","left","top"};
local side = 1;
for i,v in pairs( side_names ) do
for i,v in ipairs( side_names ) do
if( side_name and side_name==v ) then
side = i;
end
@ -154,9 +154,9 @@ build_chest.preview_image_formspec = function( building_name, replacements, side
-- the draw_tile function is based on content_id
local content_ids = {};
for i,v in pairs( data.nodenames ) do
for i,v in ipairs( data.nodenames ) do
local found = false;
for j,w in pairs( replacements ) do
for j,w in ipairs( replacements ) do
if( w and w[1] and w[1]==v) then
found = true;
if( minetest.registered_nodes[ w[2]] ) then
@ -203,8 +203,8 @@ build_chest.preview_image_formspec = function( building_name, replacements, side
formspec = formspec.."label[3,3;Sorry, this schematic is too big for a preview image.]";
return formspec;
end
for y,y_values in pairs( preview ) do
for l,v in pairs( y_values ) do
for y,y_values in ipairs( preview ) do
for l,v in ipairs( y_values ) do
-- air, ignore and mg:ignore are not stored
if( v and content_ids[ v ]==-1 ) then
formspec = formspec..build_chest.preview_image_draw_tile( nil, "unknown_node.png", (l*scale), 9-(y*scale), scale*1.3, scale*1.2, tile_nr);

View File

@ -30,6 +30,7 @@ dofile(handle_schematics.modpath.."/handle_schematics_meta.lua");
replacements_group = {};
-- the replacement groups do add some non-ground nodes; needed by mg_villages
replacements_group.node_is_ground = {}
dofile(handle_schematics.modpath.."/replacements_discontinued_nodes.lua")
dofile(handle_schematics.modpath.."/replacements_wood.lua")
dofile(handle_schematics.modpath.."/replacements_realtest.lua")
dofile(handle_schematics.modpath.."/replacements_farming.lua")

View File

@ -1,11 +1,7 @@
-- TODO: this function also occours in replacements.lua
handle_schematics.get_content_id_replaced = function( node_name, replacements )
if( not( replacements ) or not(replacements.table )) then
if not( node_name ) then
return minetest.get_content_id( 'ignore' );
else
return minetest.get_content_id( node_name );
end
if( not( node_name ) or not( replacements ) or not(replacements.table )) then
return minetest.get_content_id( 'ignore' )
end
if( replacements.table[ node_name ]) then
return minetest.get_content_id( replacements.table[ node_name ] );
@ -113,7 +109,10 @@ local function generate_building_plotmarker( pos, minp, maxp, data, param2_data,
end
-- actually position the marker
if( p.x >= minp.x and p.x <= maxp.x and p.z >= minp.z and p.z <= maxp.z and p.y >= minp.y and p.y <= maxp.y) then
if( data[ a:index(p.x, p.y, p.z)] == cid.c_snow and p.y<maxp.y and moresnow and moresnow.c_snow_top and cid.c_snow_top ~= cid.c_ignore) then
if( handle_schematics.moresnow_installed
and data[ a:index(p.x, p.y, p.z)] == cid.c_snow
and p.y<maxp.y
and moresnow and moresnow.c_snow_top and cid.c_snow_top ~= cid.c_ignore) then
data[ a:index(p.x, p.y+1, p.z)] = moresnow.c_snow_top;
end
data[ a:index(p.x, p.y, p.z)] = cid.c_plotmarker;
@ -166,9 +165,9 @@ local function generate_building_translate_nodenames( nodenames, replacements, c
new_nodes[ i ].special_chest = node_name;
-- TODO: perhaps use a locked chest owned by the mob living there?
-- place a normal chest here
new_nodes[ i ].new_content = cid.c_chest;
new_nodes[ i ].special_chest = node_name;
new_node_name = 'default:chest';
new_nodes[ i ].new_content = cid.c_chest
new_nodes[ i ].special_chest = node_name
new_node_name = 'default:chest'
elseif(new_node_name == 'cottages:chest_private'
or new_node_name == 'cottages:chest_work'
@ -220,6 +219,15 @@ local function generate_building_translate_nodenames( nodenames, replacements, c
elseif( new_content == cid.c_sign ) then
-- the sign may require some text to be written on it
new_nodes[ i ].is_sign = 1;
-- doors need special treatment as they changed from 2 to 1 node
elseif( string.sub( node_name, 1, 6)=="doors:"
and string.sub( new_node_name, 1, 6)=="doors:" ) then
if( string.sub( new_node_name, -2 ) =="_a") then
new_nodes[ i ].is_door_a = 1;
elseif( string.sub( new_node_name, -2 ) =="_b") then
new_nodes[ i ].is_door_b = 1;
end
end
@ -431,7 +439,8 @@ local function generate_building(pos, minp, maxp, data, param2_data, a, extranod
end
if( not( t )) then
if( node_content ~= cid.c_plotmarker and (not(moresnow) or node_content ~= moresnow.c_snow_top )) 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;
end
else
@ -460,19 +469,6 @@ local function generate_building(pos, minp, maxp, data, param2_data, a, extranod
data[ a:index(ax, ay, az)] = new_content;
end
-- store that a tree is to be grown there
if( n.is_tree ) then
table.insert( extra_calls.trees, {x=ax, y=ay, z=az, typ=new_content, snow=has_snow});
-- we're dealing with a chest that might need filling
elseif( n.is_chestlike ) then
table.insert( extra_calls.chests, {x=ax, y=ay, z=az, typ=new_content, bpos_i=building_nr_in_bpos, typ_name=n.special_chest});
-- the sign may require some text to be written on it
elseif( n.is_sign ) then
table.insert( extra_calls.signs, {x=ax, y=ay, z=az, typ=new_content, bpos_i=building_nr_in_bpos});
end
-- handle rotation
if( n.paramtype2 ) then
local param2 = t[2];
@ -517,6 +513,26 @@ local function generate_building(pos, minp, maxp, data, param2_data, a, extranod
else
param2_data[a:index(ax, ay, az)] = t[2];
end
-- store that a tree is to be grown there
if( n.is_tree ) then
table.insert( extra_calls.trees, {x=ax, y=ay, z=az, typ=new_content, snow=has_snow});
-- we're dealing with a chest that might need filling
elseif( n.is_chestlike ) then
table.insert( extra_calls.chests, {x=ax, y=ay, z=az, typ=new_content, bpos_i=building_nr_in_bpos, typ_name=n.special_chest});
-- the sign may require some text to be written on it
elseif( n.is_sign ) then
table.insert( extra_calls.signs, {x=ax, y=ay, z=az, typ=new_content, bpos_i=building_nr_in_bpos});
-- doors need the state param to be set (which depends on param2)
elseif( n.is_door_a ) then
table.insert( extra_calls.door_a, {x=ax, y=ay, z=az, typ=new_content, p2=param2_data[a:index(ax, ay, az)]});
elseif( n.is_door_b ) then
table.insert( extra_calls.door_b, {x=ax, y=ay, z=az, typ=new_content, p2=param2_data[a:index(ax, ay, az)]});
end
end
end
end
@ -576,7 +592,7 @@ handle_schematics.place_buildings = function(village, minp, maxp, data, param2_d
--print('REPLACEMENTS: '..minetest.serialize( replacements.table )..' CHEST: '..tostring( minetest.get_name_from_content_id( cid.c_chest ))); -- TODO
--print("Chest CID" ..tostring(cid.c_chest))
local extranodes = {}
local extra_calls = { on_constr = {}, trees = {}, chests = {}, signs = {}, traders = {} };
local extra_calls = { on_constr = {}, trees = {}, chests = {}, signs = {}, traders = {}, door_a = {}, door_b = {} };
for i, pos in pairs(bpos) do
-- roads are only placed if there are at least mg_villages.MINIMAL_BUILDUNGS_FOR_ROAD_PLACEMENT buildings in the village
@ -625,7 +641,7 @@ end
--
-- replacement_list contains replacements in the same list format as place_schematic uses
--
handle_schematics.place_building_using_voxelmanip = function( pos, binfo, replacement_list)
handle_schematics.place_building_using_voxelmanip = function( pos, binfo, replacement_list, keep_ground)
if( not( replacement_list ) or type( replacement_list ) ~= 'table' ) then
return;
@ -681,10 +697,10 @@ handle_schematics.place_building_using_voxelmanip = function( pos, binfo, replac
cid.c_sign = handle_schematics.get_content_id_replaced( 'default:gravel', replacements );
local extranodes = {}
local extra_calls = { on_constr = {}, trees = {}, chests = {}, signs = {}, traders = {} };
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, false);
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);
-- store the changed map data
vm:set_data(data);
@ -702,7 +718,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 )
handle_schematics.place_building_from_file = function( start_pos, end_pos, building_name, replacement_list, rotate, axis, mirror, no_plotmarker, keep_ground )
if( not( building_name )) then
return "No file name given. Cannot find the schematic.";
end
@ -752,7 +768,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);
local res = handle_schematics.place_building_using_voxelmanip( start_pos, binfo, replacement_list, keep_ground);
if( not(res) or not( res.extra_calls )) then
return;
end
@ -768,6 +784,24 @@ handle_schematics.place_building_from_file = function( start_pos, end_pos, build
end
end
for k, v in pairs( res.extra_calls.door_b ) do
local meta = minetest.get_meta( v );
local l = 2 -- b
local h = meta:get_int("right") + 1
local replace = {
{ { type = "a", state = 0 }, { type = "a", state = 3 } },
{ { type = "b", state = 1 }, { type = "b", state = 2 } }
}
local new = replace[l][h]
-- minetest.swap_node(v, {name = name .. "_" .. new.type, param2 = v.p2})
meta:set_int("state", new.state)
-- wipe meta on top node as it's unused
minetest.set_node({x = v.x, y = v.y + 1, z = v.z}, { name = "doors:hidden" })
end
if( binfo.metadata ) then
-- if it is a .we/.wem file, metadata was included directly
handle_schematics.restore_meta( nil, binfo.metadata, start_pos, end_pos, start_pos.brotate, mirror);
@ -830,6 +864,51 @@ handle_schematics.place_road = function(minp, maxp, data, param2_data, a, c_road
end
-- the node layer at height "ground_level" is not touched; thus
-- dirt/sand/whatever can remain there (=biome dependant); this
-- also means that the foundations for the ex-building's walls
-- will keep standing
handle_schematics.clear_area = function( start_pos, end_pos, ground_level)
local vm = minetest.get_voxel_manip()
local minp, maxp = vm:read_from_map(
{x = start_pos.x, y = start_pos.y, z = start_pos.z},
{x = end_pos.x, y = end_pos.y, z = end_pos.z}
)
local a = VoxelArea:new({MinEdge = minp, MaxEdge = maxp})
local data = vm:get_data()
if( ground_level < start_pos.y or ground_level > end_pos.y ) then
ground_level = start_pos.y;
end
local cid_air = minetest.get_content_id("air");
for y=ground_level+1, end_pos.y do
for x=start_pos.x, end_pos.x do
for z=start_pos.z, end_pos.z do
data[ a:index( x, y, z ) ] = cid_air;
end
end
end
local cid_dirt = minetest.get_content_id("default:dirt");
for y=start_pos.y, ground_level-1 do
for x=start_pos.x, end_pos.x do
for z=start_pos.z, end_pos.z do
data[ a:index( x, y, z ) ] = cid_dirt;
end
end
end
-- store the changed map data
vm:set_data(data);
vm:write_to_map();
vm:update_liquids();
vm:update_map();
end
if( minetest.get_modpath('moresnow' )) then
handle_schematics.moresnow_installed = true;
end

View File

@ -0,0 +1,42 @@
replacements_group['discontinued_nodes'] = {}
replacements_group['discontinued_nodes'].doors = function( repl, door_type)
if( not( door_type )) then
return repl;
end
-- the upper part is no longer a seperate part
table.insert( repl, {'doors:door_'..door_type..'_t_1', 'doors:hidden'});
table.insert( repl, {'doors:door_'..door_type..'_t_2', 'doors:hidden'});
-- the lower part is now two nodes high
table.insert( repl, {'doors:door_'..door_type..'_b_1', 'doors:door_'..door_type..'_a'});
table.insert( repl, {'doors:door_'..door_type..'_b_2', 'doors:door_'..door_type..'_b'});
return repl;
end
replacements_group['discontinued_nodes'].replace = function( replacements )
local repl = {};
-- doors changed from two nodes for a door to one two-node-high mesh
replacements_group['discontinued_nodes'].doors( repl, 'wood' );
replacements_group['discontinued_nodes'].doors( repl, 'steel' );
replacements_group['discontinued_nodes'].doors( repl, 'glass' );
replacements_group['discontinued_nodes'].doors( repl, 'obsidian_glass');
for i,v in ipairs( repl ) do
if( v and v[2] and minetest.registered_nodes[ v[2]] ) then
local found = false;
for j,w in ipairs( replacements ) do
if( w and w[1] and w[1]==v[1] ) then
w[2] = v[2];
found = true;
end
end
if( not( found )) then
table.insert( replacements, {v[1],v[2]} );
end
end
end
return replacements;
end

View File

@ -165,10 +165,7 @@ replacements_group['wood'].construct_wood_type_list = function()
-- default tree and jungletree; no gates available
replacements_group['wood'].add_material( {'', 'jungle' }, 'default:', '','wood','', 'tree', '','leaves', '','sapling',
'stairs:stair_', 'wood', 'stairs:slab_', 'wood', 'default:fence_','wood', 'NONE', '' );
-- default:pine_needles instead of leaves; no gates available
replacements_group['wood'].add_material( {'pine' }, 'default:', '','wood','', 'tree', '','_needles','','_sapling',
'stairs:stair_', 'wood', 'stairs:slab_', 'wood', 'default:fence_','wood', 'NONE','' );
-- https://github.com/Novatux/mg
-- trees from nores mapgen
replacements_group['wood'].add_material( {'savanna', 'pine' },'mg:', '','wood','', 'tree', '','leaves', '','sapling',

View File

@ -20,7 +20,7 @@ mg_villages.MINIMAL_BUILDUNGS_FOR_ROAD_PLACEMENT = 4;
-- players without the mg_villages priv can only see villages which are less than that many blocks away
-- from them when using the /vmap command
mg_villages.VILLAGE_DETECT_RANGE = 400;
mg_villages.VILLAGE_DETECT_RANGE = 50;
-- if set to true, only players which have the mg_villages priv can use the "/visit <village nr>"
-- command which allows teleporting to the village with the given number
@ -68,12 +68,12 @@ mg_villages.medieval_subtype = false;
-- on average, every n.th node inside a village area may be one of these trees - and it will be a relatively dense packed forrest
mg_villages.sapling_probability = {};
mg_villages.sapling_probability[ minetest.get_content_id( 'default:sapling' ) ] = 25; -- suitable for a relatively dense forrest of normal trees
mg_villages.sapling_probability[ minetest.get_content_id( 'default:junglesapling' ) ] = 40; -- jungletrees are a bit bigger and need more space
mg_villages.sapling_probability[ minetest.get_content_id( 'default:pinesapling' ) ] = 30;
mg_villages.sapling_probability[ minetest.get_content_id( 'default:sapling' ) ] = 15; -- suitable for a relatively dense forrest of normal trees
mg_villages.sapling_probability[ minetest.get_content_id( 'default:junglesapling' ) ] = 30; -- jungletrees are a bit bigger and need more space
mg_villages.sapling_probability[ minetest.get_content_id( 'default:pinesapling' ) ] = 20;
if( minetest.get_modpath( 'mg' )) then
mg_villages.sapling_probability[ minetest.get_content_id( 'mg:savannasapling' ) ] = 30;
mg_villages.sapling_probability[ minetest.get_content_id( 'mg:pinesapling' ) ] = 35;
mg_villages.sapling_probability[ minetest.get_content_id( 'mg:savannasapling' ) ] = 20;
mg_villages.sapling_probability[ minetest.get_content_id( 'mg:pinesapling' ) ] = 25;
end
mg_villages.moretrees_treelist = nil;
if( minetest.get_modpath( 'moretrees' )) then
@ -159,9 +159,9 @@ mg_villages.prices = {
-- know exactly what you are doing.
-----------------------------------------------------------------------------
-- if set to false, villages will not be integrated into the terrain - which looks very bad
mg_villages.ENABLE_TERRAIN_BLEND = true;
mg_villages.ENABLE_TERRAIN_BLEND = false;
-- if set to false, holes digged by cavegen and mudflow inside the village will not be repaired; houses will be destroyed
mg_villages.UNDO_CAVEGEN_AND_MUDFLOW = true;
mg_villages.UNDO_CAVEGEN_AND_MUDFLOW = false;
-- internal variables for village generation

View File

@ -12,7 +12,7 @@ mg_villages.new_village_spawned = function( village_id )
if mg_villages.anz_villages < 2 then
mg_villages.all_villages[ village_id ].barbarians = false
else
if rptype <= 3 then
if rptype <= 3 then
mg_villages.all_villages[ village_id ].barbarians = true
else
mg_villages.all_villages[ village_id ].barbarians = false
@ -94,11 +94,8 @@ end
-- TODO: determine water level from mapgens?
local MG_VILLAGES_WATER_LEVEL = 1;
if( minetest.get_modpath( 'mg' )) then
MG_VILLAGES_WATER_LEVEL = 0;
end
local mg_params = minetest.get_mapgen_params()
local MG_VILLAGES_WATER_LEVEL = mg_params.water_level;
--replacements_group.node_is_ground = {}; -- store nodes which have previously been identified as ground
mg_villages.check_if_ground = function( ci )
@ -106,7 +103,7 @@ mg_villages.check_if_ground = function( ci )
-- pre-generate a list of no-ground-nodes for caching
if( replacements_group.node_is_ground[ minetest.get_content_id('air')]==nil) then
local no_ground_nodes = {'air','ignore','default:sandstonebrick','default:cactus','default:wood','default:junglewood',
'default:pine_wood','default:pine_tree','default:acacia_wood','default:acacia_tree',
'mg:pinewood','mg:pinetree','mg:savannawood','mg:savannatree',
'ethereal:mushroom_pore','ethereal:mushroom_trunk','ethereal:bamboo', 'ethereal:mushroom'};
-- TODO: add all those other tree and leaf nodes that might be added by mapgen
for _,name in pairs( no_ground_nodes ) do
@ -155,6 +152,7 @@ mg_villages.lower_or_raise_terrain_at_point = function( x, z, target_height, min
local jtree = false;
local ptree = false;
local atree = false;
local asptree = false;
local old_height = maxp.y;
local y = maxp.y;
@ -198,6 +196,9 @@ mg_villages.lower_or_raise_terrain_at_point = function( x, z, target_height, min
-- acacia
elseif( ci == cid.c_atree and data[a:index( x, y-1, z)]==cid.c_atree) then
atree = true;
-- aspen
elseif( ci == cid.c_asptree and data[a:index( x, y-1, z)]==cid.c_asptree) then
asptree = true;
elseif( not( surface_node) and ci ~= cid.c_air and ci ~= cid.c_ignore and mg_villages.check_if_ground( ci ) == true) then
-- we have found a surface of some kind
surface_node = ci;
@ -291,6 +292,9 @@ mg_villages.lower_or_raise_terrain_at_point = function( x, z, target_height, min
elseif( atree and not( mg_villages.ethereal_trees ) and treepos) then
data[ a:index( x, target_height+1, z)] = cid.c_asapling
table.insert( treepos, {x=x, y=target_height+1, z=z, typ=3, snow=has_artificial_snow});
elseif( asptree and not( mg_villages.ethereal_trees ) and treepos) then
data[ a:index( x, target_height+1, z)] = cid.c_aspsapling
table.insert( treepos, {x=x, y=target_height+1, z=z, typ=3, snow=has_artificial_snow});
elseif( has_snow ) then
data[ a:index( x, target_height+1, z)] = cid.c_snow;
end
@ -737,6 +741,10 @@ mg_villages.grow_a_tree = function( pos, plant_id, minp, maxp, data, a, cid, pr,
elseif( plant_id == cid.c_asapling and minetest.registered_nodes[ 'default:acacia_tree']) then
data[ a:index( pos.x, pos.y, pos.z )] = cid.c_asapling;
return true;
-- aspen tree from newer minetest game
elseif( plant_id == cid.c_aspsapling and minetest.registered_nodes[ 'default:aspen_tree']) then
data[ a:index( pos.x, pos.y, pos.z )] = cid.c_aspsapling;
return true;
-- a savannatree from the mg mod
elseif( plant_id == cid.c_savannasapling and mg_villages.add_savannatree) then
mg_villages.add_savannatree( data, a, pos.x, pos.y, pos.z, minp, maxp, pr) -- TODO: snow
@ -907,6 +915,8 @@ mg_villages.place_villages_via_voxelmanip = function( villages, minp, maxp, vm,
cid.c_psapling = minetest.get_content_id( 'default:pine_sapling');
cid.c_atree = minetest.get_content_id( 'default:acacia_tree');
cid.c_asapling = minetest.get_content_id( 'default:acacia_sapling');
cid.c_asptree = minetest.get_content_id( 'default:aspen_tree');
cid.c_aspsapling = minetest.get_content_id( 'default:aspen_sapling');
cid.c_water = minetest.get_content_id( 'default:water_source'); -- PM ^
cid.c_stone_with_coal = minetest.get_content_id( 'default:stone_with_coal');
cid.c_sandstone = minetest.get_content_id( 'default:sandstone');
@ -1104,6 +1114,29 @@ mg_villages.place_villages_via_voxelmanip = function( villages, minp, maxp, vm,
end
end
-- the doors need to be adjusted as well
for _, village in ipairs(villages) do
if( village.to_add_data.extra_calls.door_b ) then
for k, v in pairs( village.to_add_data.extra_calls.door_b ) do
local meta = minetest.get_meta( v );
local l = 2 -- b
local h = meta:get_int("right") + 1
local replace = {
{ { type = "a", state = 0 }, { type = "a", state = 3 } },
{ { type = "b", state = 1 }, { type = "b", state = 2 } }
}
local new = replace[l][h]
-- minetest.swap_node(v, {name = name .. "_" .. new.type, param2 = v.p2})
meta:set_int("state", new.state)
-- wipe meta on top node as it's unused
minetest.set_node({x = v.x, y = v.y + 1, z = v.z}, { name = "doors:hidden" })
end
end
end
local pr = PseudoRandom(mg_villages.get_bseed(minp));
for _, village in pairs(villages) do
for _,v in pairs( village.to_add_data.extra_calls.chests ) do

View File

@ -129,6 +129,8 @@ mg_villages.plotmarker_formspec = function( pos, formname, fields, player )
or not( mg_villages.all_villages )
or not( mg_villages.all_villages[ village_id ] )
or not( plot_nr )
or not( mg_villages.all_villages[ village_id ].to_add_data )
or not( mg_villages.all_villages[ village_id ].to_add_data.bpos )
or not( mg_villages.all_villages[ village_id ].to_add_data.bpos[ plot_nr ] )) then
minetest.chat_send_player( pname, 'Error. This plot marker is not configured correctly.'..minetest.serialize({village_id,plot_nr }));
return;
@ -137,8 +139,204 @@ mg_villages.plotmarker_formspec = function( pos, formname, fields, player )
local owner = mg_villages.all_villages[ village_id ].to_add_data.bpos[ plot_nr ].owner;
local btype = mg_villages.all_villages[ village_id ].to_add_data.bpos[ plot_nr ].btype;
--minetest.chat_send_player( player:get_player_name(),'DATA FOR '..tostring(plot_nr)..': '..minetest.serialize( mg_villages.all_villages[ village_id ].to_add_data.bpos[ plot_nr ] ));
local owner_name = plot.owner;
if( not( owner_name ) or owner_name == "" ) then
if( plot.btype=="road" ) then
owner_name = "- the village community -";
else
owner_name = "- for sale -";
end
end
local building_name = mg_villages.BUILDINGS[ plot.btype ].mts_path..mg_villages.BUILDINGS[ plot.btype ].scm;
-- show coordinates of the village center to the player
local village_pos = minetest.pos_to_string( {x=village.vx, y=village.vh, z=village.vz});
-- distance from village center
local distance = math.floor( math.sqrt( (village.vx - pos.x ) * (village.vx - pos.x )
+ (village.vh - pos.y ) * (village.vh - pos.y )
+ (village.vz - pos.z ) * (village.vz - pos.z ) ));
-- create the header
local formspec = "size[13,10]"..
"label[3.3,0.0;Plot No.: "..tostring( plot_nr )..", with "..tostring( mg_villages.BUILDINGS[ plot.btype ].scm ).."]"..
"label[0.3,0.4;Located at:]" .."label[3.3,0.4;"..(minetest.pos_to_string( pos ) or '?')..", which is "..tostring( distance ).." m away]"
.."label[7.3,0.4;from the village center]"..
"label[0.3,0.8;Part of village:]" .."label[3.3,0.8;"..(village.name or "- name unknown -").."]"
.."label[7.3,0.8;located at "..(village_pos).."]"..
"label[0.3,1.2;Owned by:]" .."label[3.3,1.2;"..(owner_name).."]"..
"label[3.3,1.6;Click on a menu entry to select it:]"..
"field[20,20;0.1,0.1;pos2str;Pos;"..minetest.pos_to_string( pos ).."]";
build_chest.show_size_data( building_name );
if( plot and plot.traders ) then
if( #plot.traders > 1 ) then
formspec = formspec.."label[0.3,7.0;Some traders live here. One works as a "..tostring(plot.traders[1].typ)..".]";
for i=2,#plot.traders do
formspec = formspec.."label[0.3,"..(6.0+i)..";Another trader works as a "..tostring(plot.traders[i].typ)..".]";
end
elseif( plot.traders[1] and plot.traders[1].typ) then
formspec = formspec..
"label[0.3,7.0;A trader lives here. He works as a "..tostring( plot.traders[1].typ )..".]";
else
formspec = formspec..
"label[0.3,7.0;No trader currently works at this place.]";
end
-- add buttons for visiting (teleport to trader), calling (teleporting trader to plot) and firing the trader
for i,trader in ipairs(plot.traders) do
local trader_entity = mg_villages.plotmarker_search_trader( trader, village.vh );
formspec = formspec..
"button[6.0,"..(6.0+i)..";1.2,0.5;visit_trader_"..i..";visit]"..
"button[7.4,"..(6.0+i)..";1.2,0.5;call_trader_"..i..";call]"..
"button[8.8,"..(6.0+i)..";1.2,0.5;fire_trader_"..i..";fire]";
if( fields[ "visit_trader_"..i ] ) then
player:moveto( {x=trader.x, y=(village.vh+1), z=trader.z} );
minetest.chat_send_player( pname, "You are visiting the "..tostring( trader.typ )..
" trader, who is supposed to be somewhere here. He might also be on a floor above you.");
return;
end
if( fields[ "visit_call_"..i ] ) then
-- TODO: spawning: mob_basics.spawn_mob( {x=v.x, y=v.y, z=v.z}, v.typ, nil, nil, nil, nil, true );
end
-- TODO: fire mob
end
formspec = formspec.."button[3.75,"..(7.0+math.max(1,#plot.traders))..";3.5,0.5;hire_trader;Hire a new random trader]";
-- TODO: hire mob
end
local replace_row = -1;
-- the player selected a material which ought to be replaced
if( fields.build_chest_replacements ) then
local event = minetest.explode_table_event( fields.build_chest_replacements );
if( event and event.row and event.row > 0 ) then
replace_row = event.row;
fields.show_materials = "show_materials";
end
-- the player provided the name of the material for the replacement of the currently selected
elseif( fields.store_replacement and fields.store_repalcement ~= ""
and fields.replace_row_with and fields.replace_row_with ~= ""
and fields.replace_row_material and fields.replace_row_material ~= "") then
build_chest.replacements_apply( pos, meta, fields.replace_row_material, fields.replace_row_with, village_id );
fields.show_materials = "show_materials";
-- group selections for easily changing several nodes at once
elseif( fields.wood_selection ) then
build_chest.replacements_apply_for_group( pos, meta, 'wood', fields.wood_selection, fields.set_wood, village_id );
fields.set_wood = nil;
fields.show_materials = "show_materials";
elseif( fields.farming_selection ) then
build_chest.replacements_apply_for_group( pos, meta, 'farming', fields.farming_selection, fields.set_farming, village_id );
fields.set_farming = nil;
fields.show_materials = "show_materials";
elseif( fields.roof_selection ) then
build_chest.replacements_apply_for_group( pos, meta, 'roof', fields.roof_selection, fields.set_roof, village_id );
fields.set_roof = nil;
fields.show_materials = "show_materials";
-- actually store the new group replacement
elseif( (fields.set_wood and fields.set_wood ~= "")
or (fields.set_farming and fields.set_farming ~= "" )
or (fields.set_roof and fields.set_roof ~= "" )) then
minetest.show_formspec( pname, "mg_villages:plotmarker",
handle_schematics.get_formspec_group_replacement( pos, fields, formspec ));
return;
end
-- show which materials (and replacements!) where used for the building
if( (fields.show_materials and fields.show_materials ~= "" )
or (fields.replace_row_with and fields.replace_row_with ~= "")
or (fields.replace_row_material and fields.replace_row_material ~= "")) then
formspec = formspec.."button[9.9,0.4;2,0.5;info;Back]";
if( not( minetest.check_player_privs( pname, {protection_bypass=true}))) then
-- do not allow any changes; just show the materials and their replacements
minetest.show_formspec( pname, "mg_villages:plotmarker",
formspec..build_chest.replacements_get_list_formspec( pos, nil, 0, meta, village_id, building_name, replace_row ));
else
minetest.show_formspec( pname, "mg_villages:plotmarker",
formspec..build_chest.replacements_get_list_formspec( pos, nil, 1, nil, village_id, building_name, replace_row ));
end
return;
-- place the building again
elseif( (fields.reset_building and fields.reset_building ~= "")
or (fields.remove_building and fields.remove_building ~= "")) then
formspec = formspec.."button[9.9,0.4;2,0.5;back;Back]";
if( not( minetest.check_player_privs( pname, {protection_bypass=true}))) then
minetest.show_formspec( pname, "mg_villages:plotmarker", formspec..
"label[3,3;You need the protection_bypass priv in order to use this functin.]" );
return;
end
local selected_building = build_chest.building[ building_name ];
local start_pos = {x=plot.x, y=plot.y, z=plot.z, brotate=plot.brotate};
if( selected_building.yoff ) then
start_pos.y = start_pos.y + selected_building.yoff;
end
local end_pos = {x=plot.x+plot.bsizex-1,
y=plot.y+selected_building.yoff-1+selected_building.ysize,
z=plot.z+plot.bsizez-1};
local replacements = build_chest.replacements_get_current( meta, village_id );
if( fields.remove_building and fields.remove_building ~= "" ) then
-- clear the space above ground, put dirt below ground, but keep the
-- surface intact
handle_schematics.clear_area( start_pos, end_pos, pos.y-1);
-- also clear the meta data to avoid strange effects
handle_schematics.clear_meta( start_pos, end_pos );
formspec = formspec.."label[3,3;The plot has been cleared.]";
else
-- actually place it (disregarding mirroring)
local error_msg = handle_schematics.place_building_from_file(
start_pos,
end_pos,
building_name,
replacements,
plot.o,
build_chest.building[ building_name ].axis, plot.mirror, 1, true );
formspec = formspec.."label[3,3;The building has been reset.]";
if( error_msg ) then
formspec = formspec..'label[4,3;Error: '..tostring( fields.error_msg ).."]";
end
end
minetest.show_formspec( pname, "mg_villages:plotmarker", formspec );
return;
elseif( fields.info and fields.info ~= "" ) then
local show_material_text = "Change materials used";
if( not( minetest.check_player_privs( pname, {protection_bypass=true}))) then
show_material_text = "Show materials used";
end
minetest.show_formspec( pname, "mg_villages:plotmarker",
formspec..
"button[9.9,0.4;2,0.5;back;Back]"..
"button[3,3;5,0.5;create_backup;Create backup of current stage]"..
"button[4,4;3,0.5;show_materials;"..show_material_text.."]"..
"button[4,5;3,0.5;reset_building;Reset building]"..
"button[4,6;3,0.5;remove_building;Remove building]");
return;
end
local owner = plot.owner;
local btype = plot.btype;
local original_formspec = "size[8,3]"..
"button[7.0,0.0;1.0,0.5;info;Info]"..
"label[1.0,0.5;Plot No.: "..tostring( plot_nr ).."]"..
"label[2.5,0.5;Building:]"..
"label[3.5,0.5;"..tostring( mg_villages.BUILDINGS[btype].scm ).."]"..

View File

@ -172,6 +172,8 @@ mg_villages.replace_tree_trunk = function( replacements, wood_type )
table.insert( replacements, {'default:tree', 'default:pine_tree'});
elseif( wood_type == 'default:acacia_wood' ) then
table.insert( replacements, {'default:tree', 'default:acacia_tree'});
elseif( wood_type == 'default:aspen_wood' ) then
table.insert( replacements, {'default:tree', 'default:aspen_tree'});
elseif( wood_type == 'mg:savannawood' ) then
table.insert( replacements, {'default:tree', 'mg:savannatree'});
elseif( wood_type == 'mg:pinewood' ) then
@ -272,6 +274,8 @@ mg_villages.replace_saplings = function( replacements, wood_type )
table.insert( replacements, {'default:sapling', 'default:pine_sapling'});
elseif( wood_type == 'default:acacia_wood' ) then
table.insert( replacements, {'default:sapling', 'default:acacia_sapling'});
elseif( wood_type == 'default:aspen_wood' ) then
table.insert( replacements, {'default:sapling', 'default:aspen_sapling'});
elseif( wood_type == 'mg:savannawood' ) then
table.insert( replacements, {'default:sapling', 'mg:savannasapling'});
elseif( wood_type == 'mg:pinewood' ) then
@ -309,6 +313,7 @@ mg_villages.replace_saplings = function( replacements, wood_type )
table.insert( replacements, {'default:sapling', "trees:"..v.."_sapling"});
table.insert( replacements, {'default:junglesapling', "trees:"..v.."_sapling"});
table.insert( replacements, {'default:pine_sapling', "trees:"..v.."_sapling"});
table.insert( replacements, {'default:aspen_sapling', "trees:"..v.."_sapling"});
end
end
@ -349,6 +354,14 @@ mg_villages.get_replacement_list = function( housetype, pr )
table.insert( replacements, {'default:apple', 'air' });
table.insert( replacements, {'default:cobble', 'default:stone_macadam' });
table.insert( replacements, {'default:obsidian_glass', 'default:glass' });
-- the default doors from minetest game have been changed since the schematics where built
-- TODO: the door replacement function needs to be more complex; doesn't really work this way
else
table.insert( replacements, {'doors:door_wood_t_1', 'doors:hidden'});
table.insert( replacements, {'doors:door_wood_b_1', 'doors:door_wood_a'});
table.insert( replacements, {'doors:door_wood_t_2', 'doors:hidden'});
table.insert( replacements, {'doors:door_wood_b_2', 'doors:door_wood_b'});
end
if( housetype and mg_villages.village_type_data[ housetype ] and mg_villages.village_type_data[ housetype ].replacement_function ) then

View File

@ -146,26 +146,28 @@ function mobs:register_mob(name, def)
end,
do_avoidance = function(self)
if self.avoid_nodes ~= nil then
local avoid_range = self.avoid_range
local avoid_nodes = self.avoid_nodes
local pos = self.object:getpos()
local minx = pos.x - math.ceil( avoid_range / 2 )
local maxx = pos.x + math.ceil( avoid_range / 2 )
local minx = pos.x - avoid_range
local maxx = pos.x + avoid_range
local minz = pos.z - math.ceil( avoid_range / 2 )
local maxz = pos.z + math.ceil( avoid_range / 2 )
local minz = pos.z - avoid_range
local maxz = pos.z + avoid_range
local npos = minetest.find_nodes_in_area({x=minx,y=(pos.y-1),z=minz},{x=maxx,y=(pos.y+1),z=maxz}, avoid_nodes)
local npos = minetest.find_nodes_in_area({x=minx,y=(pos.y-2),z=minz},{x=maxx,y=(pos.y+2),z=maxz}, avoid_nodes)
if #npos > 0 then
local fpos = { x=(npos[1].x * -1),y=npos[1].y,z=(npos[1].z*-1) }
mobs:face_pos(self,fpos)
self.state="walk"
self:set_animation("walk")
self:set_velocity(4)
self.set_velocity(self, self.walk_velocity)
self.pause_timer = 3
end
end
end,
@ -337,7 +339,7 @@ function mobs:register_mob(name, def)
tflp = 1
end
process_weapon(hitter,tflp,tool_capabilities)
self.pause_timer = 0
local hpos = hitter:getpos()
local pos = self.object:getpos()
if self.object:get_hp() <= 0 then

View File

@ -48,8 +48,7 @@ function mobs.on_step(self,dtime)
end
end
-- if pause state then this is where the loop ends
-- pause is only set after a monster is hit
-- if pause state then this is where the loop ends
if self.pause_timer > 0 then
self.pause_timer = self.pause_timer - dtime
if self.pause_timer <= 0 then