/*
Minetest Valleys C
-Copyright (C) 2010-2015 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
-Copyright (C) 2010-2015 paramat, Matt Gregory
-Copyright (C) 2016 Duane Robertson <duane@duanerobertson.com>
+Copyright (C) 2016-2017 Duane Robertson <duane@duanerobertson.com>
+Copyright (C) 2016-2017 paramat
Based on Valleys Mapgen by Gael de Sailly
(https://forum.minetest.net/viewtopic.php?f=9&t=11430)
#include "settings.h" // For g_settings
#include "emerge.h"
#include "dungeongen.h"
-#include "treegen.h"
#include "mg_biome.h"
#include "mg_ore.h"
#include "mg_decoration.h"
///////////////////////////////////////////////////////////////////////////////
-MapgenValleys::MapgenValleys(int mapgenid, MapgenParams *params, EmergeManager *emerge)
+MapgenValleys::MapgenValleys(int mapgenid, MapgenValleysParams *params, EmergeManager *emerge)
: MapgenBasic(mapgenid, params, emerge)
{
// NOTE: MapgenValleys has a hard dependency on BiomeGenOriginal
- this->m_bgen = (BiomeGenOriginal *)biomegen;
+ m_bgen = (BiomeGenOriginal *)biomegen;
- this->map_gen_limit = MYMIN(MAX_MAP_GENERATION_LIMIT,
- g_settings->getU16("map_generation_limit"));
-
- MapgenValleysParams *sp = (MapgenValleysParams *)params->sparams;
BiomeParamsOriginal *bp = (BiomeParamsOriginal *)params->bparams;
- this->spflags = sp->spflags;
- this->altitude_chill = sp->altitude_chill;
- this->large_cave_depth = sp->large_cave_depth;
- this->lava_features_lim = rangelim(sp->lava_features, 0, 10);
- this->massive_cave_depth = sp->massive_cave_depth;
- this->river_depth_bed = sp->river_depth + 1.f;
- this->river_size_factor = sp->river_size / 100.f;
- this->water_features_lim = rangelim(sp->water_features, 0, 10);
- this->cave_width = sp->cave_width;
+ spflags = params->spflags;
+ altitude_chill = params->altitude_chill;
+ large_cave_depth = params->large_cave_depth;
+ lava_features_lim = rangelim(params->lava_features, 0, 10);
+ massive_cave_depth = params->massive_cave_depth;
+ river_depth_bed = params->river_depth + 1.f;
+ river_size_factor = params->river_size / 100.f;
+ water_features_lim = rangelim(params->water_features, 0, 10);
+ cave_width = params->cave_width;
//// 2D Terrain noise
- noise_filler_depth = new Noise(&sp->np_filler_depth, seed, csize.X, csize.Z);
- noise_inter_valley_slope = new Noise(&sp->np_inter_valley_slope, seed, csize.X, csize.Z);
- noise_rivers = new Noise(&sp->np_rivers, seed, csize.X, csize.Z);
- noise_terrain_height = new Noise(&sp->np_terrain_height, seed, csize.X, csize.Z);
- noise_valley_depth = new Noise(&sp->np_valley_depth, seed, csize.X, csize.Z);
- noise_valley_profile = new Noise(&sp->np_valley_profile, seed, csize.X, csize.Z);
+ noise_filler_depth = new Noise(¶ms->np_filler_depth, seed, csize.X, csize.Z);
+ noise_inter_valley_slope = new Noise(¶ms->np_inter_valley_slope, seed, csize.X, csize.Z);
+ noise_rivers = new Noise(¶ms->np_rivers, seed, csize.X, csize.Z);
+ noise_terrain_height = new Noise(¶ms->np_terrain_height, seed, csize.X, csize.Z);
+ noise_valley_depth = new Noise(¶ms->np_valley_depth, seed, csize.X, csize.Z);
+ noise_valley_profile = new Noise(¶ms->np_valley_profile, seed, csize.X, csize.Z);
//// 3D Terrain noise
// 1-up 1-down overgeneration
- noise_inter_valley_fill = new Noise(&sp->np_inter_valley_fill, seed, csize.X, csize.Y + 2, csize.Z);
+ noise_inter_valley_fill = new Noise(¶ms->np_inter_valley_fill, seed, csize.X, csize.Y + 2, csize.Z);
// 1-down overgeneraion
- noise_cave1 = new Noise(&sp->np_cave1, seed, csize.X, csize.Y + 1, csize.Z);
- noise_cave2 = new Noise(&sp->np_cave2, seed, csize.X, csize.Y + 1, csize.Z);
- noise_massive_caves = new Noise(&sp->np_massive_caves, seed, csize.X, csize.Y + 1, csize.Z);
+ noise_cave1 = new Noise(¶ms->np_cave1, seed, csize.X, csize.Y + 1, csize.Z);
+ noise_cave2 = new Noise(¶ms->np_cave2, seed, csize.X, csize.Y + 1, csize.Z);
+ noise_massive_caves = new Noise(¶ms->np_massive_caves, seed, csize.X, csize.Y + 1, csize.Z);
- this->humid_rivers = (spflags & MGVALLEYS_HUMID_RIVERS);
- this->use_altitude_chill = (spflags & MGVALLEYS_ALT_CHILL);
- this->humidity_adjust = bp->np_humidity.offset - 50.f;
+ humid_rivers = (spflags & MGVALLEYS_HUMID_RIVERS);
+ use_altitude_chill = (spflags & MGVALLEYS_ALT_CHILL);
+ humidity_adjust = bp->np_humidity.offset - 50.f;
// a small chance of overflows if the settings are very high
- this->cave_water_max_height = water_level + MYMAX(0, water_features_lim - 4) * 50;
- this->lava_max_height = water_level + MYMAX(0, lava_features_lim - 4) * 50;
+ cave_water_max_height = water_level + MYMAX(0, water_features_lim - 4) * 50;
+ lava_max_height = water_level + MYMAX(0, lava_features_lim - 4) * 50;
tcave_cache = new float[csize.Y + 2];
-
- // Resolve content to be used
- c_lava_source = ndef->getId("mapgen_lava_source");
}
MapgenValleysParams::MapgenValleysParams()
{
- spflags = MGVALLEYS_HUMID_RIVERS | MGVALLEYS_ALT_CHILL;
- altitude_chill = 90; // The altitude at which temperature drops by 20C.
- large_cave_depth = -33;
- lava_features = 0; // How often water will occur in caves.
- massive_cave_depth = -256; // highest altitude of massive caves
- river_depth = 4; // How deep to carve river channels.
- river_size = 5; // How wide to make rivers.
- water_features = 0; // How often water will occur in caves.
- cave_width = 0.3;
-
- np_cave1 = NoiseParams(0, 12, v3f(96, 96, 96), 52534, 4, 0.5, 2.0);
- np_cave2 = NoiseParams(0, 12, v3f(96, 96, 96), 10325, 4, 0.5, 2.0);
+ np_cave1 = NoiseParams(0, 12, v3f(61, 61, 61), 52534, 3, 0.5, 2.0);
+ np_cave2 = NoiseParams(0, 12, v3f(67, 67, 67), 10325, 3, 0.5, 2.0);
np_filler_depth = NoiseParams(0.f, 1.2f, v3f(256, 256, 256), 1605, 3, 0.5f, 2.f);
np_inter_valley_fill = NoiseParams(0.f, 1.f, v3f(256, 512, 256), 1993, 6, 0.8f, 2.f);
np_inter_valley_slope = NoiseParams(0.5f, 0.5f, v3f(128, 128, 128), 746, 1, 1.f, 2.f);
blockseed = getBlockSeed2(full_node_min, seed);
- // Generate noise maps and base terrain height.
- calculateNoise();
-
// Generate biome noises. Note this must be executed strictly before
// generateTerrain, because generateTerrain depends on intermediate
// biome-related noises.
m_bgen->calcBiomeNoise(node_min);
+ // Generate noise maps and base terrain height.
+ // Modify heat and humidity maps.
+ calculateNoise();
+
// Generate base terrain with initial heightmaps
s16 stone_surface_max_y = generateTerrain();
- // Build biomemap
- m_bgen->getBiomes(heightmap);
+ // Recalculate heightmap
+ updateHeightmap(node_min, node_max);
- // Place biome-specific nodes
- MgStoneType stone_type = generateBiomes();
+ // Place biome-specific nodes and build biomemap
+ MgStoneType mgstone_type;
+ content_t biome_stone;
+ generateBiomes(&mgstone_type, &biome_stone, water_level - 1);
// Cave creation.
if (flags & MG_CAVES)
// Dungeon creation
if ((flags & MG_DUNGEONS) && node_max.Y < 50)
- generateDungeons(stone_surface_max_y, stone_type);
+ generateDungeons(stone_surface_max_y, mgstone_type, biome_stone);
// Generate the registered decorations
if (flags & MG_DECORATIONS)
- m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
+ m_emerge->decomgr->placeAllDecos(this, blockseed,
+ node_min, node_max, water_level - 1);
// Generate the registered ores
- m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
+ m_emerge->oremgr->placeAllOres(this, blockseed,
+ node_min, node_max, water_level - 1);
// Sprinkle some dust on top after everything else was generated
dustTopNodes();
MapNode n_stone(c_stone);
MapNode n_water(c_water_source);
- v3s16 em = vm->m_area.getExtent();
+ const v3s16 &em = vm->m_area.getExtent();
s16 surface_max_y = -MAX_MAP_GENERATION_LIMIT;
u32 index_2d = 0;
index_3d += ystride;
}
- // This happens if we're generating a chunk that doesn't
- // contain the terrain surface, in which case, we need
- // to set heightmap to a value outside of the chunk,
- // to avoid confusing lua mods that use heightmap.
if (heightmap[index_2d] == -MAX_MAP_GENERATION_LIMIT) {
s16 surface_y_int = myround(surface_y);
if (surface_y_int > node_max.Y + 1 || surface_y_int < node_min.Y - 1) {
MapNode n_lava(c_lava_source);
MapNode n_water(c_river_water_source);
- v3s16 em = vm->m_area.getExtent();
+ const v3s16 &em = vm->m_area.getExtent();
// Cave blend distance near YMIN, YMAX
const float massive_cave_blend = 128.f;
const float massive_cave_threshold = 0.6f;
// mct: 1 = small rare caves, 0.5 1/3rd ground volume, 0 = 1/2 ground volume.
- float yblmin = -map_gen_limit + massive_cave_blend * 1.5f;
+ float yblmin = -mapgen_limit + massive_cave_blend * 1.5f;
float yblmax = massive_cave_depth - massive_cave_blend * 1.5f;
bool made_a_big_one = false;
// lava_depth varies between one and ten as you approach
// the bottom of the world.
- s16 lava_depth = ceil((lava_max_height - node_min.Y + 1) * 10.f / map_gen_limit);
+ s16 lava_depth = ceil((lava_max_height - node_min.Y + 1) * 10.f / mapgen_limit);
// This allows random lava spawns to be less common at the surface.
s16 lava_chance = MYCUBE(lava_features_lim) * lava_depth;
// water_depth varies between ten and one on the way down.
- s16 water_depth = ceil((map_gen_limit - abs(node_min.Y) + 1) * 10.f / map_gen_limit);
+ s16 water_depth = ceil((mapgen_limit - abs(node_min.Y) + 1) * 10.f / mapgen_limit);
// This allows random water spawns to be more common at the surface.
s16 water_chance = MYCUBE(water_features_lim) * water_depth;
for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) {
Biome *biome = (Biome *)m_bmgr->getRaw(biomemap[index_2d]);
bool tunnel_air_above = false;
+ bool is_under_river = false;
bool underground = false;
u32 index_data = vm->m_area.index(x, node_max.Y, z);
u32 index_3d = (z - node_min.Z) * zstride_1d + csize.Y * ystride + (x - node_min.X);
}
content_t c = vm->m_data[index_data].getContent();
+ // Detect river water to place riverbed nodes in tunnels
+ if (c == biome->c_river_water)
+ is_under_river = true;
+
float d1 = contour(noise_cave1->result[index_3d]);
float d2 = contour(noise_cave2->result[index_3d]);
- // River water is not set as ground content
- // in the default game. This can produce strange results
- // when a tunnel undercuts a river. However, that's not for
- // the mapgen to correct. Fix it in lua.
-
if (d1 * d2 > cave_width && ndef->get(c).is_ground_content) {
// in a tunnel
vm->m_data[index_data] = n_air;
vm->m_area.add_y(em, j, 1);
if (sr > terrain - y) {
- // Put dirt in tunnels near the surface.
- if (underground)
+ // Put biome nodes in tunnels near the surface
+ if (is_under_river)
+ vm->m_data[index_data] = MapNode(biome->c_riverbed);
+ else if (underground)
vm->m_data[index_data] = MapNode(biome->c_filler);
else
vm->m_data[index_data] = MapNode(biome->c_top);
u32 bruises_count = ps.range(0, 2);
for (u32 i = 0; i < bruises_count; i++) {
CavesRandomWalk cave(ndef, &gennotify, seed, water_level,
- c_water_source, c_lava_source);
+ c_water_source, c_lava_source, lava_max_height);
cave.makeCave(vm, node_min, node_max, &ps, true, max_stone_y, heightmap);
}