data of one-house-villages is now saved as well; mapchunk size got slightly more flexible; minor optimization; check for potential one-house-villages in neighbouring mapchunks as well; improved one-house-village generation
parent
270991df60
commit
7c25dbcc3e
45
mapgen.lua
45
mapgen.lua
|
@ -34,30 +34,16 @@ mg_villages.get_vn = function(x, z, noise, village)
|
|||
end
|
||||
|
||||
|
||||
mg_villages.villages_in_mapchunk = function( minp )
|
||||
mg_villages.villages_in_mapchunk = function( minp, mapchunk_size )
|
||||
local noise1raw = minetest.get_perlin(12345, 6, 0.5, 256)
|
||||
|
||||
local vcr = mg_villages.VILLAGE_CHECK_RADIUS
|
||||
local villages = {}
|
||||
for xi = -vcr, vcr do
|
||||
for zi = -vcr, vcr do
|
||||
for _, village in ipairs(mg_villages.villages_at_point({x = minp.x + xi * 80, z = minp.z + zi * 80}, noise1raw)) do
|
||||
village.to_grow = {}
|
||||
for _, village in ipairs(mg_villages.villages_at_point({x = minp.x + xi * mapchunk_size, z = minp.z + zi * mapchunk_size}, noise1raw)) do
|
||||
villages[#villages+1] = village
|
||||
end
|
||||
-- check if the village exists already
|
||||
local v_nr = 1;
|
||||
for v_nr, village in ipairs(villages) do
|
||||
local village_id = tostring( village.vx )..':'..tostring( village.vz );
|
||||
|
||||
if( not( village.name ) or village.name == '') then
|
||||
village.name = 'unknown';
|
||||
end
|
||||
|
||||
if( mg_villages.all_villages and mg_villages.all_villages[ village_id ]) then
|
||||
villages[ v_nr ] = mg_villages.all_villages[ village_id ];
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return villages;
|
||||
|
@ -384,8 +370,8 @@ mg_villages.village_area_mark_inside_village_area = function( village_area, vill
|
|||
if( not( village_area[ x ][ z ] )) then
|
||||
village_area[ x ][ z ] = { 0, 0 };
|
||||
|
||||
local n_rawnoise = village_noise:get2d({x = x, y = z}) -- create new blended terrain
|
||||
for village_nr, village in ipairs(villages) do
|
||||
local n_rawnoise = village_noise:get2d({x = x, y = z}) -- create new blended terrain
|
||||
local vn = mg_villages.get_vn(x, z, n_rawnoise, village);
|
||||
-- the village core; this is where the houses stand (but there's no house or road at this particular spot)
|
||||
if( vn <= 40 ) then
|
||||
|
@ -898,18 +884,31 @@ minetest.register_on_generated(function(minp, maxp, seed)
|
|||
local villages = {};
|
||||
-- create normal villages
|
||||
if( mg_villages.ENABLE_VILLAGES == true ) then
|
||||
villages = mg_villages.villages_in_mapchunk( minp );
|
||||
villages = mg_villages.villages_in_mapchunk( minp, maxp.x-minp.x+1 );
|
||||
end
|
||||
|
||||
-- if this mapchunk contains no part of a village, probably a lone building may be found in it
|
||||
if( #villages < 1 and mg_villages.INVERSE_HOUSE_DENSITY > 0 ) then
|
||||
villages = mg_villages.houses_in_mapchunk( minp );
|
||||
if( mg_villages.INVERSE_HOUSE_DENSITY > 0 ) then
|
||||
villages = mg_villages.houses_in_mapchunk( minp, maxp.x-minp.x+1, villages );
|
||||
end
|
||||
|
||||
-- check if the village exists already
|
||||
local v_nr = 1;
|
||||
for v_nr, village in ipairs(villages) do
|
||||
local village_id = tostring( village.vx )..':'..tostring( village.vz );
|
||||
|
||||
if( not( village.name ) or village.name == '') then
|
||||
village.name = 'unknown';
|
||||
end
|
||||
|
||||
if( mg_villages.all_villages and mg_villages.all_villages[ village_id ]) then
|
||||
villages[ v_nr ] = mg_villages.all_villages[ village_id ];
|
||||
end
|
||||
end
|
||||
|
||||
if( villages and #villages > 0 ) then
|
||||
mg_villages.place_villages_via_voxelmanip( villages, minp, maxp, nil, nil, nil, nil, nil );
|
||||
end
|
||||
|
||||
-- TODO: place individual buildings; villages will have to be empty in that case
|
||||
-- mg_villages.place_villages_via_voxelmanip( {}, minp, maxp, nil, nil, nil, nil, nil );
|
||||
end)
|
||||
|
||||
|
||||
|
|
51
villages.lua
51
villages.lua
|
@ -668,7 +668,7 @@ end
|
|||
-- creates individual buildings outside of villages;
|
||||
-- the data structure is like that of a village, except that bpos (=buildings to be placed) is already set;
|
||||
-- Note: one building per mapchunk is more than enough (else it would look too crowded);
|
||||
mg_villages.houses_in_mapchunk = function( minp )
|
||||
mg_villages.houses_in_one_mapchunk = function( minp, mapchunk_size, villages, vnoise )
|
||||
local village = {};
|
||||
local pr = PseudoRandom(mg_villages.get_bseed(minp))
|
||||
|
||||
|
@ -677,9 +677,8 @@ mg_villages.houses_in_mapchunk = function( minp )
|
|||
return {};
|
||||
end
|
||||
-- set random coordinates withhin chunk (but far enough away from the shell so that we don't have to bother about cavegen)
|
||||
-- TODO: the 79 depends on chunk size
|
||||
village.vx = pr:next(minp.x+16, minp.x + 79-32)
|
||||
village.vz = pr:next(minp.z+16, minp.z + 79-32)
|
||||
village.vx = pr:next(minp.x, minp.x + mapchunk_size - 1)
|
||||
village.vz = pr:next(minp.z, minp.z + mapchunk_size - 1)
|
||||
-- village height will be set to a value fitting the terrain later on
|
||||
village.vh = 10;
|
||||
-- this will force re-calculation of height
|
||||
|
@ -710,11 +709,51 @@ mg_villages.houses_in_mapchunk = function( minp )
|
|||
end
|
||||
|
||||
-- adjust the size of the flattened area to the building's size
|
||||
village.vs = pr:next( math.max( 2, math.floor(math.min( bsizex, bsizez )*0.3)), math.ceil( math.max( bsizex, bsizez )));
|
||||
village.vs = pr:next( math.max( 2, math.floor(math.min( bsizex, bsizez )*0.3)), math.min( math.ceil( math.max( bsizex, bsizez )), 25));
|
||||
|
||||
-- now check if this village can be placed here or if it intersects with another village in any critical manner;
|
||||
-- the village area may intersect (=unproblematic; may even look nice), but the actual building must not be inside another village
|
||||
for i,v in ipairs(villages) do
|
||||
-- abort if the new building can't be placed here
|
||||
if( mg_villages.inside_village_area(bx, bz, v, vnoise)
|
||||
or mg_villages.inside_village_area(bx+bsizex, bz, v, vnoise)
|
||||
or mg_villages.inside_village_area(bx, bz+bsizez, v, vnoise)
|
||||
or mg_villages.inside_village_area(bx+bsizex, bz+bsizez, v, vnoise)) then
|
||||
return;
|
||||
end
|
||||
end
|
||||
|
||||
local village_id = tostring( village.vx )..':'..tostring( village.vz );
|
||||
-- these values have to be determined once per village; afterwards, they need to be fixed
|
||||
if( mg_villages.all_villages and mg_villages.all_villages[ village_id ] and mg_villages.all_villages[ village_id ].optimal_height) then
|
||||
village.optimal_height = mg_villages.all_villages[ village_id ].optimal_height;
|
||||
village.vh = mg_villages.all_villages[ village_id ].optimal_height;
|
||||
village.artificial_snow = mg_villages.all_villages[ village_id ].artificial_snow;
|
||||
end
|
||||
|
||||
village.to_add_data = {};
|
||||
village.to_add_data.bpos = { {x=bx, y=village.vh, z=bz, btype=btype, bsizex=bsizex, bsizez=bsizez, brotate = rotation, road_nr = 0, side=1, o=orient1, mirror=mirror }}
|
||||
print('adding SINGLE HOUSE of type '..tostring( village.village_type )..' to map at '..tostring( village.vx )..':'..tostring( village.vz )..'.'); -- TODO
|
||||
return { village };
|
||||
|
||||
return village;
|
||||
end
|
||||
|
||||
|
||||
-- we need to determine where single houses will be placed in neighbouring mapchunks as well because
|
||||
-- they may be so close to the border that they will affect this mapchunk
|
||||
mg_villages.houses_in_mapchunk = function( minp, mapchunk_size, villages )
|
||||
local village_noise = minetest.get_perlin(7635, 3, 0.5, 16);
|
||||
for x=-1,1 do
|
||||
for z=-1,1 do
|
||||
local new_village = mg_villages.houses_in_one_mapchunk(
|
||||
{x=minp.x+(x*mapchunk_size), y=minp.y, z=minp.z+(z*mapchunk_size)},
|
||||
mapchunk_size,
|
||||
villages,
|
||||
village_noise );
|
||||
if( new_village and new_village.vs and new_village.vx and new_village.vz ) then
|
||||
table.insert( villages, new_village );
|
||||
end
|
||||
end
|
||||
end
|
||||
return villages;
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue