diff --git a/doc/lua_api.txt b/doc/lua_api.txt index de3927a74..231456bbb 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -4630,9 +4630,6 @@ Definition tables ### Biome definition (`register_biome`) -**Note** -The Biome API is still in an experimental phase and subject to change. - { name = "tundra", node_dust = "default:snow", @@ -4659,13 +4656,6 @@ The Biome API is still in an experimental phase and subject to change. y_max = 31000, -- ^ Lower and upper limits for biome. -- ^ Limits are relative to y = water_level - 1. - -- ^ Because biome is not recalculated for every node in a node column - -- ^ some biome materials can exceed their limits, especially stone. - -- ^ For each node column in a mapchunk, biome is only recalculated at column - -- ^ top and at each of these surfaces: - -- ^ Ground below air, water below air, ground below water. - -- ^ The selected biome then stays in effect for all nodes below until - -- ^ column base or the next biome recalculation. heat_point = 0, humidity_point = 50, -- ^ Characteristic average temperature and humidity for the biome. diff --git a/src/mapgen.cpp b/src/mapgen.cpp index fe7f74cfa..1d72ec037 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -633,6 +633,7 @@ void MapgenBasic::generateBiomes(MgStoneType *mgstone_type, u16 base_filler = 0; u16 depth_water_top = 0; u16 depth_riverbed = 0; + s16 biome_y_min = -MAX_MAP_GENERATION_LIMIT; u32 vi = vm->m_area.index(x, node_max.Y, z); // Check node at base of mapchunk above, either a node of a previously @@ -650,22 +651,20 @@ void MapgenBasic::generateBiomes(MgStoneType *mgstone_type, for (s16 y = node_max.Y; y >= node_min.Y; y--) { content_t c = vm->m_data[vi].getContent(); - - // Biome is recalculated each time an upper surface is detected while - // working down a column. The selected biome then remains in effect for - // all nodes below until the next surface and biome recalculation. - // Biome is recalculated: + // Biome is (re)calculated: // 1. At the surface of stone below air or water. // 2. At the surface of water below air. // 3. When stone or water is detected but biome has not yet been calculated. + // 4. When stone or water is detected just below a biome's lower limit. bool is_stone_surface = (c == c_stone) && - (air_above || water_above || !biome); + (air_above || water_above || !biome || y < biome_y_min); // 1, 3, 4 bool is_water_surface = (c == c_water_source || c == c_river_water_source) && - (air_above || !biome); + (air_above || !biome || y < biome_y_min); // 2, 3, 4 if (is_stone_surface || is_water_surface) { + // (Re)calculate biome // Limit to +-MAX MAP GENERATION LIMIT to work with biome y_min / y_max. s32 relative_y = rangelim(y - biome_zero_level, -MAX_MAP_GENERATION_LIMIT, MAX_MAP_GENERATION_LIMIT); @@ -677,9 +676,11 @@ void MapgenBasic::generateBiomes(MgStoneType *mgstone_type, depth_top = biome->depth_top; base_filler = MYMAX(depth_top + biome->depth_filler + - noise_filler_depth->result[index], 0.f); + noise_filler_depth->result[index], 0.0f); depth_water_top = biome->depth_water_top; depth_riverbed = biome->depth_riverbed; + biome_y_min = rangelim(biome->y_min + biome_zero_level, + -MAX_MAP_GENERATION_LIMIT, MAX_MAP_GENERATION_LIMIT); // Detect stone type for dungeons during every biome calculation. // If none detected the last selected biome stone is chosen.