seperated village structure generation and placement of buildings; lowered village height to 1-5; added special road node that will not be removed by cavegen

master
Sokomine 2014-08-05 19:49:02 +02:00
parent ace2ac5b8b
commit 7fa94dc66f
5 changed files with 87 additions and 40 deletions

View File

@ -337,7 +337,8 @@ mg_villages.buildings_init();
--local gravel = minetest.get_content_id("default:gravel")
local gravel = minetest.get_content_id("default:gravel")
-- this special "gravel" will not be removed by mapgen and will not fall down like gravel usually does
local gravel = minetest.get_content_id('mg_villages:road'); --"default:gravel")
local c_air = minetest.get_content_id("air");
local rgravel = {}
for i = 1, 2000 do

View File

@ -19,6 +19,9 @@ dofile(mg_villages.modpath.."/rotate.lua")
-- analyze_mts_file.lua uses handle_schematics.* namespace
dofile(mg_villages.modpath.."/analyze_mts_file.lua")
-- adds a special gravel node which will neither fall nor be griefed by mapgen
dofile(mg_villages.modpath.."/nodes.lua")
-- Note: the "buildings" talbe is not in the mg_villages.* namespace
dofile(mg_villages.modpath.."/buildings.lua")

View File

@ -129,6 +129,28 @@ mg_villages.place_villages_via_voxelmanip = function( villages, minp, maxp, vm,
param2_data = vm:get_param2_data()
end
-- generate the village structure: determine positions of buildings and roads
for _, village in ipairs(villages) do
village = mg_villages.generate_village( village, village_noise);
-- mark the roads and the area between buildings and road in the village_area table as "road" (=2)
end
-- determine which coordinates are inside the village and which are not
local village_area = {};
for x = minp.x, maxp.x do
village_area[ x ] = {};
for z = minp.z, maxp.z do
for _, village in ipairs(villages) do
if( mg_villages.inside_village(x, z, village, village_noise)) then
village_area[ x ][ z ] = 1;
else
village_area[ x ][ z ] = 0;
end
end
end
end
mg_villages.flatten_village_area( villages, village_noise, minp, maxp, vm, data, param2_data, a );
local top_node = 'default:dirt_with_grass';
@ -141,7 +163,7 @@ mg_villages.place_villages_via_voxelmanip = function( villages, minp, maxp, vm,
end
for _, village in ipairs(villages) do
village.to_add_data = mg_villages.generate_village(village, minp, maxp, data, param2_data, a, village_noise, top_node)
village.to_add_data = mg_villages.place_buildings( village, minp, maxp, data, param2_data, a, village_noise);
end
vm:set_data(data)

13
nodes.lua Normal file
View File

@ -0,0 +1,13 @@
minetest.register_node("mg_villages:road", {
description = "village road",
tiles = {"default_gravel.png", "default_dirt.png"},
is_ground_content = false, -- will not be removed by the cave generator
groups = {crumbly=2}, -- does not fall
sounds = default.node_sound_dirt_defaults({
footstep = {name="default_gravel_footstep", gain=0.5},
dug = {name="default_gravel_footstep", gain=1.0},
}),
})
mg_villages.road_node = minetest.get_content_id( 'mg_villages:road' );

View File

@ -59,7 +59,8 @@ mg_villages.villages_at_point = function(minp, noise1)
mg_villages.village_sizes[ village_type ] = { min = VILLAGE_MIN_SIZE, max = VILLAGE_MAX_SIZE };
end
local size = pr:next(mg_villages.village_sizes[ village_type ].min, mg_villages.village_sizes[ village_type ].max)
local height = pr:next(5, 20)
-- local height = pr:next(5, 20)
local height = pr:next(1, 5)
-- print("A village of type \'"..tostring( village_type ).."\' of size "..tostring( size ).." spawned at: x = "..x..", z = "..z)
--print("A village spawned at: x = "..x..", z = "..z)
@ -475,7 +476,7 @@ mg_villages.mg_drop_moresnow = function( x, z, y_top, y_bottom, a, data, param2_
end
end
if( not(node_below.content)
or node_below.content == moresnow.c_gravel
or node_below.content == mg_villages.road_node
or node_below.content == moresnow.c_snow ) then
return;
end
@ -540,7 +541,6 @@ local function generate_building(pos, minp, maxp, data, param2_data, a, pr, extr
local c_dirt = minetest.get_content_id( "default:dirt" );
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_gravel = minetest.get_content_id( "default:gravel");
for x = 0, pos.bsizex-1 do
for z = 0, pos.bsizez-1 do
local has_snow = false;
@ -796,7 +796,9 @@ local function generate_walls(bpos, data, a, minp, maxp, vh, vx, vz, vs, vnoise)
end
end
mg_villages.generate_village = function(village, minp, maxp, data, param2_data, a, vnoise, dirt_with_grass_replacement)
-- determine which building is to be placed where
-- also choose which blocks to replace with which other blocks (to make villages more intresting)
mg_villages.generate_village = function(village, vnoise)
local vx, vz, vs, vh = village.vx, village.vz, village.vs, village.vh
local village_type = village.village_type;
local seed = mg_villages.get_bseed({x=vx, z=vz})
@ -805,34 +807,47 @@ mg_villages.generate_village = function(village, minp, maxp, data, param2_data,
-- only generate a new village if the data is not already stored
-- (the algorithm is fast, but village types and houses which are available may change later on,
-- and that might easily cause chaos if the village is generated again with diffrent input)
local new_village = false;
local bpos = {};
local replacement_list = {};
if( not( village.to_add_data ) or not( village.to_add_data.bpos ) or not( village.to_add_data.replacements )) then
bpos = generate_bpos( village, pr_village, vnoise)
-- set fruits for all buildings in the village that need it - regardless weather they will be spawned
-- now or later; after the first call to this function here, the village data will be final
for _, pos in ipairs( bpos ) do
local binfo = buildings[pos.btype];
if( binfo.farming_plus and binfo.farming_plus == 1 and mg_villages.fruit_list and not pos.furit) then
pos.fruit = mg_villages.fruit_list[ pr_village:next( 1, #mg_villages.fruit_list )];
end
end
replacement_list = nil;
new_village = true;
--print('VILLAGE GENREATION: NEW (Nr. '..tostring( village_nr )..')'); -- TODO
else
-- get the saved data
bpos = village.to_add_data.bpos;
replacement_list = village.to_add_data.replacements;
new_village = false;
--print('VILLAGE GENREATION: USING ALREADY GENERATED VILLAGE: Nr. '..tostring( village.nr )); -- TODO
-- TODO local forget_bpos = generate_bpos( village, pr_village, vnoise)
if( village.to_add_data and village.to_add_data.bpos and village.to_add_data.replacements ) then
--print('VILLAGE GENREATION: USING ALREADY GENERATED VILLAGE: Nr. '..tostring( village.nr ));
return;
end
village.to_grow = {}; -- TODO this is a temporal solution to avoid flying tree thrunks
-- actually generate the village structure
local bpos = generate_bpos( village, pr_village, vnoise)
-- set fruits for all buildings in the village that need it - regardless weather they will be spawned
-- now or later; after the first call to this function here, the village data will be final
for _, pos in ipairs( bpos ) do
local binfo = buildings[pos.btype];
if( binfo.farming_plus and binfo.farming_plus == 1 and mg_villages.fruit_list and not pos.furit) then
pos.fruit = mg_villages.fruit_list[ pr_village:next( 1, #mg_villages.fruit_list )];
end
end
-- a changing replacement list would also be pretty confusing
local p = PseudoRandom(seed);
-- if the village is new, replacement_list is nil and a new replacement list will be created
local replacements = mg_villages.get_replacement_table( village.village_type, p, nil );
-- store the generated data in the village table
village.to_add_data = {};
village.to_add_data.bpos = bpos;
village.to_add_data.replacements = replacements.list;
--print('VILLAGE GENREATION: GENERATING NEW VILLAGE Nr. '..tostring( village.nr ));
end
-- actually place the buildings (at least those which came as .we files; .mts files are handled later on)
-- this code is also responsible for tree placement
mg_villages.place_buildings = function(village, minp, maxp, data, param2_data, a, vnoise)
local vx, vz, vs, vh = village.vx, village.vz, village.vs, village.vh
local village_type = village.village_type;
local seed = mg_villages.get_bseed({x=vx, z=vz})
local bpos = village.to_add_data.bpos;
village.to_grow = {}; -- TODO this is a temporal solution to avoid flying tree trunks
--generate_walls(bpos, data, a, minp, maxp, vh, vx, vz, vs, vnoise)
local pr = PseudoRandom(seed)
for _, g in ipairs(village.to_grow) do
@ -841,14 +856,7 @@ village.to_grow = {}; -- TODO this is a temporal solution to avoid flying tree t
end
end
-- a changing replacement list would also be pretty confusing
local p = PseudoRandom(seed);
-- if the village is new, replacement_list is nil and a new replacement list will be created
local replacements = mg_villages.get_replacement_table( village.village_type, p, replacement_list );
if( not( replacements.table )) then
replacements.table = {};
end
local replacements = mg_villages.get_replacement_table( village.village_type, p, village.to_add_data.replacements );
local extranodes = {}
for _, pos in ipairs(bpos) do