summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkwolekr <kwolekr@minetest.net>2016-05-02 02:24:57 -0400
committerkwolekr <kwolekr@minetest.net>2016-05-27 23:23:58 -0400
commit87bc39dca733a2cc805bc1071794c4d5d7937115 (patch)
tree127a2f902e36cb10b399cfbe276fae3b452ebce1
parent76f485647983ebd7eb4c3abbca0869d13f76920b (diff)
downloadminetest-87bc39dca733a2cc805bc1071794c4d5d7937115.tar.gz
minetest-87bc39dca733a2cc805bc1071794c4d5d7937115.tar.bz2
minetest-87bc39dca733a2cc805bc1071794c4d5d7937115.zip
Mapgen: Combine generateBiomes, dustTopNodes, and generateCaves
This commit condenses the above methods into a single implementation used by V7, V5, Flat, Fractal, and Valleys mapgens and introduces MapgenBasic.
-rw-r--r--src/mapgen.cpp236
-rw-r--r--src/mapgen.h56
-rw-r--r--src/mapgen_flat.cpp221
-rw-r--r--src/mapgen_flat.h29
-rw-r--r--src/mapgen_fractal.cpp221
-rw-r--r--src/mapgen_fractal.h23
-rw-r--r--src/mapgen_v5.cpp221
-rw-r--r--src/mapgen_v5.h24
-rw-r--r--src/mapgen_v7.cpp230
-rw-r--r--src/mapgen_v7.h25
-rw-r--r--src/mapgen_valleys.cpp165
-rw-r--r--src/mapgen_valleys.h26
12 files changed, 316 insertions, 1161 deletions
diff --git a/src/mapgen.cpp b/src/mapgen.cpp
index e269bf454..f491ed9eb 100644
--- a/src/mapgen.cpp
+++ b/src/mapgen.cpp
@@ -39,6 +39,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "util/numeric.h"
#include "filesys.h"
#include "log.h"
+#include "cavegen.h"
FlagDesc flagdesc_mapgen[] = {
{"trees", MG_TREES},
@@ -370,6 +371,241 @@ void Mapgen::spreadLight(v3s16 nmin, v3s16 nmax)
////
+//// MapgenBasic
+////
+
+MapgenBasic::MapgenBasic(int mapgenid, MapgenParams *params, EmergeManager *emerge)
+ : Mapgen(mapgenid, params, emerge)
+{
+
+}
+
+MgStoneType MapgenBasic::generateBiomes()
+{
+ v3s16 em = vm->m_area.getExtent();
+ u32 index = 0;
+ MgStoneType stone_type = STONE;
+
+ for (s16 z = node_min.Z; z <= node_max.Z; z++)
+ for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
+ Biome *biome = NULL;
+ u16 depth_top = 0;
+ u16 base_filler = 0;
+ u16 depth_water_top = 0;
+ u32 vi = vm->m_area.index(x, node_max.Y, z);
+
+ // Check node at base of mapchunk above, either a node of a previously
+ // generated mapchunk or if not, a node of overgenerated base terrain.
+ content_t c_above = vm->m_data[vi + em.X].getContent();
+ bool air_above = c_above == CONTENT_AIR;
+ bool water_above = (c_above == c_water_source || c_above == c_river_water_source);
+
+ // If there is air or water above enable top/filler placement, otherwise force
+ // nplaced to stone level by setting a number exceeding any possible filler depth.
+ u16 nplaced = (air_above || water_above) ? 0 : U16_MAX;
+
+ 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:
+ // 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.
+ if ((c == c_stone && (air_above || water_above || !biome))
+ || ((c == c_water_source || c == c_river_water_source)
+ && (air_above || !biome))) {
+ biome = biomegen->getBiomeAtIndex(index, y);
+
+ depth_top = biome->depth_top;
+ base_filler = MYMAX(depth_top
+ + biome->depth_filler
+ + noise_filler_depth->result[index], 0.f);
+ depth_water_top = biome->depth_water_top;
+
+ // Detect stone type for dungeons during every biome calculation.
+ // This is more efficient than detecting per-node and will not
+ // miss any desert stone or sandstone biomes.
+ if (biome->c_stone == c_desert_stone)
+ stone_type = DESERT_STONE;
+ else if (biome->c_stone == c_sandstone)
+ stone_type = SANDSTONE;
+ }
+
+ if (c == c_stone) {
+ content_t c_below = vm->m_data[vi - em.X].getContent();
+
+ // If the node below isn't solid, make this node stone, so that
+ // any top/filler nodes above are structurally supported.
+ // This is done by aborting the cycle of top/filler placement
+ // immediately by forcing nplaced to stone level.
+ if (c_below == CONTENT_AIR
+ || c_below == c_water_source
+ || c_below == c_river_water_source)
+ nplaced = U16_MAX;
+
+ if (nplaced < depth_top) {
+ vm->m_data[vi] = MapNode(biome->c_top);
+ nplaced++;
+ } else if (nplaced < base_filler) {
+ vm->m_data[vi] = MapNode(biome->c_filler);
+ nplaced++;
+ } else {
+ vm->m_data[vi] = MapNode(biome->c_stone);
+ }
+
+ air_above = false;
+ water_above = false;
+ } else if (c == c_water_source) {
+ vm->m_data[vi] = MapNode((y > (s32)(water_level - depth_water_top))
+ ? biome->c_water_top : biome->c_water);
+ nplaced = 0; // Enable top/filler placement for next surface
+ air_above = false;
+ water_above = true;
+ } else if (c == c_river_water_source) {
+ vm->m_data[vi] = MapNode(biome->c_river_water);
+ nplaced = depth_top; // Enable filler placement for next surface
+ air_above = false;
+ water_above = true;
+ } else if (c == CONTENT_AIR) {
+ nplaced = 0; // Enable top/filler placement for next surface
+ air_above = true;
+ water_above = false;
+ } else { // Possible various nodes overgenerated from neighbouring mapchunks
+ nplaced = U16_MAX; // Disable top/filler placement
+ air_above = false;
+ water_above = false;
+ }
+
+ vm->m_area.add_y(em, vi, -1);
+ }
+ }
+
+ return stone_type;
+}
+
+
+void MapgenBasic::dustTopNodes()
+{
+ if (node_max.Y < water_level)
+ return;
+
+ v3s16 em = vm->m_area.getExtent();
+ u32 index = 0;
+
+ for (s16 z = node_min.Z; z <= node_max.Z; z++)
+ for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
+ Biome *biome = (Biome *)bmgr->getRaw(biomemap[index]);
+
+ if (biome->c_dust == CONTENT_IGNORE)
+ continue;
+
+ u32 vi = vm->m_area.index(x, full_node_max.Y, z);
+ content_t c_full_max = vm->m_data[vi].getContent();
+ s16 y_start;
+
+ if (c_full_max == CONTENT_AIR) {
+ y_start = full_node_max.Y - 1;
+ } else if (c_full_max == CONTENT_IGNORE) {
+ vi = vm->m_area.index(x, node_max.Y + 1, z);
+ content_t c_max = vm->m_data[vi].getContent();
+
+ if (c_max == CONTENT_AIR)
+ y_start = node_max.Y;
+ else
+ continue;
+ } else {
+ continue;
+ }
+
+ vi = vm->m_area.index(x, y_start, z);
+ for (s16 y = y_start; y >= node_min.Y - 1; y--) {
+ if (vm->m_data[vi].getContent() != CONTENT_AIR)
+ break;
+
+ vm->m_area.add_y(em, vi, -1);
+ }
+
+ content_t c = vm->m_data[vi].getContent();
+ if (!ndef->get(c).buildable_to && c != CONTENT_IGNORE && c != biome->c_dust) {
+ vm->m_area.add_y(em, vi, 1);
+ vm->m_data[vi] = MapNode(biome->c_dust);
+ }
+ }
+}
+
+
+void MapgenBasic::generateCaves(s16 max_stone_y, s16 large_cave_depth)
+{
+ if (max_stone_y < node_min.Y)
+ return;
+
+ noise_cave1->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
+ noise_cave2->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
+
+ v3s16 em = vm->m_area.getExtent();
+ u32 index2d = 0;
+
+ for (s16 z = node_min.Z; z <= node_max.Z; z++)
+ for (s16 x = node_min.X; x <= node_max.X; x++, index2d++) {
+ bool column_is_open = false; // Is column open to overground
+ bool is_tunnel = false; // Is tunnel or tunnel floor
+ u32 vi = vm->m_area.index(x, node_max.Y, z);
+ u32 index3d = (z - node_min.Z) * zstride_1d + csize.Y * ystride +
+ (x - node_min.X);
+ // Biome of column
+ Biome *biome = (Biome *)bmgr->getRaw(biomemap[index2d]);
+
+ // Don't excavate the overgenerated stone at node_max.Y + 1,
+ // this creates a 'roof' over the tunnel, preventing light in
+ // tunnels at mapchunk borders when generating mapchunks upwards.
+ // This 'roof' is removed when the mapchunk above is generated.
+ for (s16 y = node_max.Y; y >= node_min.Y - 1; y--,
+ index3d -= ystride,
+ vm->m_area.add_y(em, vi, -1)) {
+
+ content_t c = vm->m_data[vi].getContent();
+ if (c == CONTENT_AIR || c == biome->c_water_top ||
+ c == biome->c_water) {
+ column_is_open = true;
+ continue;
+ }
+ // Ground
+ float d1 = contour(noise_cave1->result[index3d]);
+ float d2 = contour(noise_cave2->result[index3d]);
+
+ if (d1 * d2 > cave_width && ndef->get(c).is_ground_content) {
+ // In tunnel and ground content, excavate
+ vm->m_data[vi] = MapNode(CONTENT_AIR);
+ is_tunnel = true;
+ } else {
+ // Not in tunnel or not ground content
+ if (is_tunnel && column_is_open &&
+ (c == biome->c_filler || c == biome->c_stone))
+ // Tunnel entrance floor
+ vm->m_data[vi] = MapNode(biome->c_top);
+
+ column_is_open = false;
+ is_tunnel = false;
+ }
+ }
+ }
+
+ if (node_max.Y > large_cave_depth)
+ return;
+
+ PseudoRandom ps(blockseed + 21343);
+ u32 bruises_count = ps.range(0, 2);
+ for (u32 i = 0; i < bruises_count; i++) {
+ CaveV5 cave(this, &ps); ////caves version varies ---- todo- fix this!
+ cave.makeCave(node_min, node_max, max_stone_y);
+ }
+}
+
+
+////
//// GenerateNotifier
////
diff --git a/src/mapgen.h b/src/mapgen.h
index 554ec6084..bee8e786a 100644
--- a/src/mapgen.h
+++ b/src/mapgen.h
@@ -46,6 +46,7 @@ extern FlagDesc flagdesc_gennotify[];
class Biome;
class BiomeGen;
struct BiomeParams;
+class BiomeManager;
class EmergeManager;
class MapBlock;
class VoxelManipulator;
@@ -137,6 +138,16 @@ struct MapgenParams {
void save(Settings &settings) const;
};
+
+/*
+ Generic interface for map generators. All mapgens must inherit this class.
+ If a feature exposed by a public member pointer is not supported by a
+ certain mapgen, it must be set to NULL.
+
+ Apart from makeChunk, getGroundLevelAtPoint, and getSpawnLevelAtPoint, all
+ methods can be used by constructing a Mapgen base class and setting the
+ appropriate public members (e.g. vm, ndef, and so on).
+*/
class Mapgen {
public:
int seed;
@@ -189,6 +200,51 @@ private:
DISABLE_CLASS_COPY(Mapgen);
};
+/*
+ MapgenBasic is a Mapgen implementation that handles basic functionality
+ the majority of conventional mapgens will probably want to use, but isn't
+ generic enough to be included as part of the base Mapgen class (such as
+ generating biome terrain over terrain node skeletons, generating caves,
+ dungeons, etc.)
+
+ Inherit MapgenBasic instead of Mapgen to add this basic functionality to
+ your mapgen without having to reimplement it. Feel free to override any of
+ these methods if you desire different or more advanced behavior.
+
+ Note that you must still create your own generateTerrain implementation when
+ inheriting MapgenBasic.
+*/
+class MapgenBasic : public Mapgen {
+public:
+ EmergeManager *m_emerge;
+ BiomeManager *bmgr;
+
+ Noise *noise_filler_depth;
+ Noise *noise_cave1;
+ Noise *noise_cave2;
+
+ v3s16 node_min;
+ v3s16 node_max;
+ v3s16 full_node_min;
+ v3s16 full_node_max;
+
+ content_t c_stone;
+ content_t c_water_source;
+ content_t c_river_water_source;
+ content_t c_desert_stone;
+ content_t c_sandstone;
+
+ int ystride;
+ int zstride_1d;
+ float cave_width;
+
+ MapgenBasic(int mapgenid, MapgenParams *params, EmergeManager *emerge);
+
+ virtual MgStoneType generateBiomes();
+ virtual void dustTopNodes();
+ virtual void generateCaves(s16 max_stone_y, s16 large_cave_depth);
+};
+
struct MapgenFactory {
virtual Mapgen *createMapgen(int mgid, MapgenParams *params,
EmergeManager *emerge) = 0;
diff --git a/src/mapgen_flat.cpp b/src/mapgen_flat.cpp
index cb9aa9a8b..97f1c4b2a 100644
--- a/src/mapgen_flat.cpp
+++ b/src/mapgen_flat.cpp
@@ -50,7 +50,7 @@ FlagDesc flagdesc_mapgen_flat[] = {
MapgenFlat::MapgenFlat(int mapgenid, MapgenParams *params, EmergeManager *emerge)
- : Mapgen(mapgenid, params, emerge)
+ : MapgenBasic(mapgenid, params, emerge)
{
this->m_emerge = emerge;
this->bmgr = emerge->biomemgr;
@@ -248,7 +248,7 @@ void MapgenFlat::makeChunk(BlockMakeData *data)
MgStoneType stone_type = generateBiomes();
if (flags & MG_CAVES)
- generateCaves(stone_surface_max_y);
+ generateCaves(stone_surface_max_y, large_cave_depth);
if ((flags & MG_DUNGEONS) && (stone_surface_max_y >= node_min.Y)) {
DungeonParams dp;
@@ -381,220 +381,3 @@ s16 MapgenFlat::generateTerrain()
return stone_surface_max_y;
}
-
-
-MgStoneType MapgenFlat::generateBiomes()
-{
- v3s16 em = vm->m_area.getExtent();
- u32 index = 0;
- MgStoneType stone_type = STONE;
-
- for (s16 z = node_min.Z; z <= node_max.Z; z++)
- for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
- Biome *biome = NULL;
- u16 depth_top = 0;
- u16 base_filler = 0;
- u16 depth_water_top = 0;
- u32 vi = vm->m_area.index(x, node_max.Y, z);
-
- // Check node at base of mapchunk above, either a node of a previously
- // generated mapchunk or if not, a node of overgenerated base terrain.
- content_t c_above = vm->m_data[vi + em.X].getContent();
- bool air_above = c_above == CONTENT_AIR;
- bool water_above = c_above == c_water_source;
-
- // If there is air or water above enable top/filler placement, otherwise force
- // nplaced to stone level by setting a number exceeding any possible filler depth.
- u16 nplaced = (air_above || water_above) ? 0 : U16_MAX;
-
-
- 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:
- // 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.
- if ((c == c_stone && (air_above || water_above || !biome)) ||
- (c == c_water_source && (air_above || !biome))) {
- biome = biomegen->getBiomeAtIndex(index, y);
-
- depth_top = biome->depth_top;
- base_filler = MYMAX(depth_top + biome->depth_filler
- + noise_filler_depth->result[index], 0);
- depth_water_top = biome->depth_water_top;
-
- // Detect stone type for dungeons during every biome calculation.
- // This is more efficient than detecting per-node and will not
- // miss any desert stone or sandstone biomes.
- if (biome->c_stone == c_desert_stone)
- stone_type = DESERT_STONE;
- else if (biome->c_stone == c_sandstone)
- stone_type = SANDSTONE;
- }
-
- if (c == c_stone) {
- content_t c_below = vm->m_data[vi - em.X].getContent();
-
- // If the node below isn't solid, make this node stone, so that
- // any top/filler nodes above are structurally supported.
- // This is done by aborting the cycle of top/filler placement
- // immediately by forcing nplaced to stone level.
- if (c_below == CONTENT_AIR || c_below == c_water_source)
- nplaced = U16_MAX;
-
- if (nplaced < depth_top) {
- vm->m_data[vi] = MapNode(biome->c_top);
- nplaced++;
- } else if (nplaced < base_filler) {
- vm->m_data[vi] = MapNode(biome->c_filler);
- nplaced++;
- } else {
- vm->m_data[vi] = MapNode(biome->c_stone);
- }
-
- air_above = false;
- water_above = false;
- } else if (c == c_water_source) {
- vm->m_data[vi] = MapNode((y > (s32)(water_level - depth_water_top)) ?
- biome->c_water_top : biome->c_water);
- nplaced = 0; // Enable top/filler placement for next surface
- air_above = false;
- water_above = true;
- } else if (c == CONTENT_AIR) {
- nplaced = 0; // Enable top/filler placement for next surface
- air_above = true;
- water_above = false;
- } else { // Possible various nodes overgenerated from neighbouring mapchunks
- nplaced = U16_MAX; // Disable top/filler placement
- air_above = false;
- water_above = false;
- }
-
- vm->m_area.add_y(em, vi, -1);
- }
- }
-
- return stone_type;
-}
-
-
-void MapgenFlat::dustTopNodes()
-{
- if (node_max.Y < water_level)
- return;
-
- v3s16 em = vm->m_area.getExtent();
- u32 index = 0;
-
- for (s16 z = node_min.Z; z <= node_max.Z; z++)
- for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
- Biome *biome = (Biome *)bmgr->getRaw(biomemap[index]);
-
- if (biome->c_dust == CONTENT_IGNORE)
- continue;
-
- u32 vi = vm->m_area.index(x, full_node_max.Y, z);
- content_t c_full_max = vm->m_data[vi].getContent();
- s16 y_start;
-
- if (c_full_max == CONTENT_AIR) {
- y_start = full_node_max.Y - 1;
- } else if (c_full_max == CONTENT_IGNORE) {
- vi = vm->m_area.index(x, node_max.Y + 1, z);
- content_t c_max = vm->m_data[vi].getContent();
-
- if (c_max == CONTENT_AIR)
- y_start = node_max.Y;
- else
- continue;
- } else {
- continue;
- }
-
- vi = vm->m_area.index(x, y_start, z);
- for (s16 y = y_start; y >= node_min.Y - 1; y--) {
- if (vm->m_data[vi].getContent() != CONTENT_AIR)
- break;
-
- vm->m_area.add_y(em, vi, -1);
- }
-
- content_t c = vm->m_data[vi].getContent();
- if (!ndef->get(c).buildable_to && c != CONTENT_IGNORE && c != biome->c_dust) {
- vm->m_area.add_y(em, vi, 1);
- vm->m_data[vi] = MapNode(biome->c_dust);
- }
- }
-}
-
-
-void MapgenFlat::generateCaves(s16 max_stone_y)
-{
- if (max_stone_y < node_min.Y)
- return;
-
- noise_cave1->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
- noise_cave2->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
-
- v3s16 em = vm->m_area.getExtent();
- u32 index2d = 0;
-
- for (s16 z = node_min.Z; z <= node_max.Z; z++)
- for (s16 x = node_min.X; x <= node_max.X; x++, index2d++) {
- bool column_is_open = false; // Is column open to overground
- bool is_tunnel = false; // Is tunnel or tunnel floor
- u32 vi = vm->m_area.index(x, node_max.Y, z);
- u32 index3d = (z - node_min.Z) * zstride_1d + csize.Y * ystride +
- (x - node_min.X);
- // Biome of column
- Biome *biome = (Biome *)bmgr->getRaw(biomemap[index2d]);
-
- // Don't excavate the overgenerated stone at node_max.Y + 1,
- // this creates a 'roof' over the tunnel, preventing light in
- // tunnels at mapchunk borders when generating mapchunks upwards.
- // This 'roof' is removed when the mapchunk above is generated.
- for (s16 y = node_max.Y; y >= node_min.Y - 1; y--,
- index3d -= ystride,
- vm->m_area.add_y(em, vi, -1)) {
-
- content_t c = vm->m_data[vi].getContent();
- if (c == CONTENT_AIR || c == biome->c_water_top ||
- c == biome->c_water) {
- column_is_open = true;
- continue;
- }
- // Ground
- float d1 = contour(noise_cave1->result[index3d]);
- float d2 = contour(noise_cave2->result[index3d]);
-
- if (d1 * d2 > cave_width && ndef->get(c).is_ground_content) {
- // In tunnel and ground content, excavate
- vm->m_data[vi] = MapNode(CONTENT_AIR);
- is_tunnel = true;
- } else {
- // Not in tunnel or not ground content
- if (is_tunnel && column_is_open &&
- (c == biome->c_filler || c == biome->c_stone))
- // Tunnel entrance floor
- vm->m_data[vi] = MapNode(biome->c_top);
-
- column_is_open = false;
- is_tunnel = false;
- }
- }
- }
-
- if (node_max.Y > large_cave_depth)
- return;
-
- PseudoRandom ps(blockseed + 21343);
- u32 bruises_count = ps.range(0, 2);
- for (u32 i = 0; i < bruises_count; i++) {
- CaveV5 cave(this, &ps);
- cave.makeCave(node_min, node_max, max_stone_y);
- }
-}
diff --git a/src/mapgen_flat.h b/src/mapgen_flat.h
index 53fd66a67..2b98c1f31 100644
--- a/src/mapgen_flat.h
+++ b/src/mapgen_flat.h
@@ -53,43 +53,19 @@ struct MapgenFlatParams : public MapgenSpecificParams {
void writeParams(Settings *settings) const;
};
-class MapgenFlat : public Mapgen {
+class MapgenFlat : public MapgenBasic {
public:
- EmergeManager *m_emerge;
- BiomeManager *bmgr;
-
- int ystride;
- int zstride_1d;
-
- v3s16 node_min;
- v3s16 node_max;
- v3s16 full_node_min;
- v3s16 full_node_max;
-
u32 spflags;
s16 ground_level;
s16 large_cave_depth;
- float cave_width;
float lake_threshold;
float lake_steepness;
float hill_threshold;
float hill_steepness;
Noise *noise_terrain;
- Noise *noise_filler_depth;
- Noise *noise_cave1;
- Noise *noise_cave2;
-
- Noise *noise_heat;
- Noise *noise_humidity;
- Noise *noise_heat_blend;
- Noise *noise_humidity_blend;
- content_t c_stone;
- content_t c_water_source;
content_t c_lava_source;
- content_t c_desert_stone;
content_t c_ice;
- content_t c_sandstone;
content_t c_cobble;
content_t c_stair_cobble;
@@ -104,9 +80,6 @@ public:
int getSpawnLevelAtPoint(v2s16 p);
void calculateNoise();
s16 generateTerrain();
- MgStoneType generateBiomes();
- void dustTopNodes();
- void generateCaves(s16 max_stone_y);
};
struct MapgenFactoryFlat : public MapgenFactory {
diff --git a/src/mapgen_fractal.cpp b/src/mapgen_fractal.cpp
index 9671a2143..81e162072 100644
--- a/src/mapgen_fractal.cpp
+++ b/src/mapgen_fractal.cpp
@@ -48,7 +48,7 @@ FlagDesc flagdesc_mapgen_fractal[] = {
MapgenFractal::MapgenFractal(int mapgenid, MapgenParams *params, EmergeManager *emerge)
- : Mapgen(mapgenid, params, emerge)
+ : MapgenBasic(mapgenid, params, emerge)
{
this->m_emerge = emerge;
this->bmgr = emerge->biomemgr;
@@ -264,7 +264,7 @@ void MapgenFractal::makeChunk(BlockMakeData *data)
MgStoneType stone_type = generateBiomes();
if (flags & MG_CAVES)
- generateCaves(stone_surface_max_y);
+ generateCaves(stone_surface_max_y, MGFRACTAL_LARGE_CAVE_DEPTH);
if ((flags & MG_DUNGEONS) && (stone_surface_max_y >= node_min.Y)) {
DungeonParams dp;
@@ -505,220 +505,3 @@ s16 MapgenFractal::generateTerrain()
return stone_surface_max_y;
}
-
-
-MgStoneType MapgenFractal::generateBiomes()
-{
- v3s16 em = vm->m_area.getExtent();
- u32 index = 0;
- MgStoneType stone_type = STONE;
-
- for (s16 z = node_min.Z; z <= node_max.Z; z++)
- for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
- Biome *biome = NULL;
- u16 depth_top = 0;
- u16 base_filler = 0;
- u16 depth_water_top = 0;
- u32 vi = vm->m_area.index(x, node_max.Y, z);
-
- // Check node at base of mapchunk above, either a node of a previously
- // generated mapchunk or if not, a node of overgenerated base terrain.
- content_t c_above = vm->m_data[vi + em.X].getContent();
- bool air_above = c_above == CONTENT_AIR;
- bool water_above = c_above == c_water_source;
-
- // If there is air or water above enable top/filler placement, otherwise force
- // nplaced to stone level by setting a number exceeding any possible filler depth.
- u16 nplaced = (air_above || water_above) ? 0 : U16_MAX;
-
-
- 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:
- // 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.
- if ((c == c_stone && (air_above || water_above || !biome)) ||
- (c == c_water_source && (air_above || !biome))) {
- biome = biomegen->getBiomeAtIndex(index, y);
-
- depth_top = biome->depth_top;
- base_filler = MYMAX(depth_top + biome->depth_filler
- + noise_filler_depth->result[index], 0);
- depth_water_top = biome->depth_water_top;
-
- // Detect stone type for dungeons during every biome calculation.
- // This is more efficient than detecting per-node and will not
- // miss any desert stone or sandstone biomes.
- if (biome->c_stone == c_desert_stone)
- stone_type = DESERT_STONE;
- else if (biome->c_stone == c_sandstone)
- stone_type = SANDSTONE;
- }
-
- if (c == c_stone) {
- content_t c_below = vm->m_data[vi - em.X].getContent();
-
- // If the node below isn't solid, make this node stone, so that
- // any top/filler nodes above are structurally supported.
- // This is done by aborting the cycle of top/filler placement
- // immediately by forcing nplaced to stone level.
- if (c_below == CONTENT_AIR || c_below == c_water_source)
- nplaced = U16_MAX;
-
- if (nplaced < depth_top) {
- vm->m_data[vi] = MapNode(biome->c_top);
- nplaced++;
- } else if (nplaced < base_filler) {
- vm->m_data[vi] = MapNode(biome->c_filler);
- nplaced++;
- } else {
- vm->m_data[vi] = MapNode(biome->c_stone);
- }
-
- air_above = false;
- water_above = false;
- } else if (c == c_water_source) {
- vm->m_data[vi] = MapNode((y > (s32)(water_level - depth_water_top)) ?
- biome->c_water_top : biome->c_water);
- nplaced = 0; // Enable top/filler placement for next surface
- air_above = false;
- water_above = true;
- } else if (c == CONTENT_AIR) {
- nplaced = 0; // Enable top/filler placement for next surface
- air_above = true;
- water_above = false;
- } else { // Possible various nodes overgenerated from neighbouring mapchunks
- nplaced = U16_MAX; // Disable top/filler placement
- air_above = false;
- water_above = false;
- }
-
- vm->m_area.add_y(em, vi, -1);
- }
- }
-
- return stone_type;
-}
-
-
-void MapgenFractal::dustTopNodes()
-{
- if (node_max.Y < water_level)
- return;
-
- v3s16 em = vm->m_area.getExtent();
- u32 index = 0;
-
- for (s16 z = node_min.Z; z <= node_max.Z; z++)
- for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
- Biome *biome = (Biome *)bmgr->getRaw(biomemap[index]);
-
- if (biome->c_dust == CONTENT_IGNORE)
- continue;
-
- u32 vi = vm->m_area.index(x, full_node_max.Y, z);
- content_t c_full_max = vm->m_data[vi].getContent();
- s16 y_start;
-
- if (c_full_max == CONTENT_AIR) {
- y_start = full_node_max.Y - 1;
- } else if (c_full_max == CONTENT_IGNORE) {
- vi = vm->m_area.index(x, node_max.Y + 1, z);
- content_t c_max = vm->m_data[vi].getContent();
-
- if (c_max == CONTENT_AIR)
- y_start = node_max.Y;
- else
- continue;
- } else {
- continue;
- }
-
- vi = vm->m_area.index(x, y_start, z);
- for (s16 y = y_start; y >= node_min.Y - 1; y--) {
- if (vm->m_data[vi].getContent() != CONTENT_AIR)
- break;
-
- vm->m_area.add_y(em, vi, -1);
- }
-
- content_t c = vm->m_data[vi].getContent();
- if (!ndef->get(c).buildable_to && c != CONTENT_IGNORE && c != biome->c_dust) {
- vm->m_area.add_y(em, vi, 1);
- vm->m_data[vi] = MapNode(biome->c_dust);
- }
- }
-}
-
-
-void MapgenFractal::generateCaves(s16 max_stone_y)
-{
- if (max_stone_y < node_min.Y)
- return;
-
- noise_cave1->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
- noise_cave2->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
-
- v3s16 em = vm->m_area.getExtent();
- u32 index2d = 0;
-
- for (s16 z = node_min.Z; z <= node_max.Z; z++)
- for (s16 x = node_min.X; x <= node_max.X; x++, index2d++) {
- bool column_is_open = false; // Is column open to overground
- bool is_tunnel = false; // Is tunnel or tunnel floor
- u32 vi = vm->m_area.index(x, node_max.Y, z);
- u32 index3d = (z - node_min.Z) * zstride_1d + csize.Y * ystride +
- (x - node_min.X);
- // Biome of column
- Biome *biome = (Biome *)bmgr->getRaw(biomemap[index2d]);
-
- // Don't excavate the overgenerated stone at node_max.Y + 1,
- // this creates a 'roof' over the tunnel, preventing light in
- // tunnels at mapchunk borders when generating mapchunks upwards.
- // This 'roof' is removed when the mapchunk above is generated.
- for (s16 y = node_max.Y; y >= node_min.Y - 1; y--,
- index3d -= ystride,
- vm->m_area.add_y(em, vi, -1)) {
-
- content_t c = vm->m_data[vi].getContent();
- if (c == CONTENT_AIR || c == biome->c_water_top ||
- c == biome->c_water) {
- column_is_open = true;
- continue;
- }
- // Ground
- float d1 = contour(noise_cave1->result[index3d]);
- float d2 = contour(noise_cave2->result[index3d]);
-
- if (d1 * d2 > cave_width && ndef->get(c).is_ground_content) {
- // In tunnel and ground content, excavate
- vm->m_data[vi] = MapNode(CONTENT_AIR);
- is_tunnel = true;
- } else {
- // Not in tunnel or not ground content
- if (is_tunnel && column_is_open &&
- (c == biome->c_filler || c == biome->c_stone))
- // Tunnel entrance floor
- vm->m_data[vi] = MapNode(biome->c_top);
-
- column_is_open = false;
- is_tunnel = false;
- }
- }
- }
-
- if (node_max.Y > MGFRACTAL_LARGE_CAVE_DEPTH)
- return;
-
- PseudoRandom ps(blockseed + 21343);
- u32 bruises_count = ps.range(0, 2);
- for (u32 i = 0; i < bruises_count; i++) {
- CaveV5 cave(this, &ps);
- cave.makeCave(node_min, node_max, max_stone_y);
- }
-}
diff --git a/src/mapgen_fractal.h b/src/mapgen_fractal.h
index a0e51b2c6..176885d46 100644
--- a/src/mapgen_fractal.h
+++ b/src/mapgen_fractal.h
@@ -57,23 +57,12 @@ struct MapgenFractalParams : public MapgenSpecificParams {
void writeParams(Settings *settings) const;
};
-class MapgenFractal : public Mapgen {
+class MapgenFractal : public MapgenBasic {
public:
- EmergeManager *m_emerge;
- BiomeManager *bmgr;
-
- int ystride;
- int zstride_1d;
u16 formula;
bool julia;
- v3s16 node_min;
- v3s16 node_max;
- v3s16 full_node_min;
- v3s16 full_node_max;
-
u32 spflags;
- float cave_width;
u16 fractal;
u16 iterations;
v3f scale;
@@ -84,16 +73,9 @@ public:
float julia_z;
float julia_w;
Noise *noise_seabed;
- Noise *noise_filler_depth;
- Noise *noise_cave1;
- Noise *noise_cave2;
- content_t c_stone;
- content_t c_water_source;
content_t c_lava_source;
- content_t c_desert_stone;
content_t c_ice;
- content_t c_sandstone;
content_t c_cobble;
content_t c_stair_cobble;
@@ -109,9 +91,6 @@ public:
void calculateNoise();
bool getFractalAtPoint(s16 x, s16 y, s16 z);
s16 generateTerrain();
- MgStoneType generateBiomes();
- void dustTopNodes();
- void generateCaves(s16 max_stone_y);
};
struct MapgenFactoryFractal : public MapgenFactory {
diff --git a/src/mapgen_v5.cpp b/src/mapgen_v5.cpp
index 829a1f432..7698af825 100644
--- a/src/mapgen_v5.cpp
+++ b/src/mapgen_v5.cpp
@@ -46,7 +46,7 @@ FlagDesc flagdesc_mapgen_v5[] = {
MapgenV5::MapgenV5(int mapgenid, MapgenParams *params, EmergeManager *emerge)
- : Mapgen(mapgenid, params, emerge)
+ : MapgenBasic(mapgenid, params, emerge)
{
this->m_emerge = emerge;
this->bmgr = emerge->biomemgr;
@@ -245,7 +245,7 @@ void MapgenV5::makeChunk(BlockMakeData *data)
// Generate caves
if ((flags & MG_CAVES) && (stone_surface_max_y >= node_min.Y))
- generateCaves(stone_surface_max_y);
+ generateCaves(stone_surface_max_y, MGV5_LARGE_CAVE_DEPTH);
// Generate dungeons and desert temples
if ((flags & MG_DUNGEONS) && (stone_surface_max_y >= node_min.Y)) {
@@ -391,220 +391,3 @@ int MapgenV5::generateBaseTerrain()
return stone_surface_max_y;
}
-
-
-MgStoneType MapgenV5::generateBiomes()
-{
- v3s16 em = vm->m_area.getExtent();
- u32 index = 0;
- MgStoneType stone_type = STONE;
-
- for (s16 z = node_min.Z; z <= node_max.Z; z++)
- for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
- Biome *biome = NULL;
- u16 depth_top = 0;
- u16 base_filler = 0;
- u16 depth_water_top = 0;
- u32 vi = vm->m_area.index(x, node_max.Y, z);
-
- // Check node at base of mapchunk above, either a node of a previously
- // generated mapchunk or if not, a node of overgenerated base terrain.
- content_t c_above = vm->m_data[vi + em.X].getContent();
- bool air_above = c_above == CONTENT_AIR;
- bool water_above = c_above == c_water_source;
-
- // If there is air or water above enable top/filler placement, otherwise force
- // nplaced to stone level by setting a number exceeding any possible filler depth.
- u16 nplaced = (air_above || water_above) ? 0 : U16_MAX;
-
- 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:
- // 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.
- if ((c == c_stone && (air_above || water_above || !biome)) ||
- (c == c_water_source && (air_above || !biome))) {
- biome = biomegen->getBiomeAtIndex(index, y);
-
- depth_top = biome->depth_top;
- base_filler = MYMAX(depth_top + biome->depth_filler
- + noise_filler_depth->result[index], 0);
- depth_water_top = biome->depth_water_top;
-
- // Detect stone type for dungeons during every biome calculation.
- // This is more efficient than detecting per-node and will not
- // miss any desert stone or sandstone biomes.
- if (biome->c_stone == c_desert_stone)
- stone_type = DESERT_STONE;
- else if (biome->c_stone == c_sandstone)
- stone_type = SANDSTONE;
- }
-
- if (c == c_stone) {
- content_t c_below = vm->m_data[vi - em.X].getContent();
-
- // If the node below isn't solid, make this node stone, so that
- // any top/filler nodes above are structurally supported.
- // This is done by aborting the cycle of top/filler placement
- // immediately by forcing nplaced to stone level.
- if (c_below == CONTENT_AIR || c_below == c_water_source)
- nplaced = U16_MAX;
-
- if (nplaced < depth_top) {
- vm->m_data[vi] = MapNode(biome->c_top);
- nplaced++;
- } else if (nplaced < base_filler) {
- vm->m_data[vi] = MapNode(biome->c_filler);
- nplaced++;
- } else {
- vm->m_data[vi] = MapNode(biome->c_stone);
- }
-
- air_above = false;
- water_above = false;
- } else if (c == c_water_source) {
- vm->m_data[vi] = MapNode((y > (s32)(water_level - depth_water_top)) ?
- biome->c_water_top : biome->c_water);
- nplaced = 0; // Enable top/filler placement for next surface
- air_above = false;
- water_above = true;
- } else if (c == CONTENT_AIR) {
- nplaced = 0; // Enable top/filler placement for next surface
- air_above = true;
- water_above = false;
- } else { // Possible various nodes overgenerated from neighbouring mapchunks
- nplaced = U16_MAX; // Disable top/filler placement
- air_above = false;
- water_above = false;
- }
-
- vm->m_area.add_y(em, vi, -1);
- }
- }
-
- return stone_type;
-}
-
-
-void MapgenV5::dustTopNodes()
-{
- if (node_max.Y < water_level)
- return;
-
- v3s16 em = vm->m_area.getExtent();
- u32 index = 0;
-
- for (s16 z = node_min.Z; z <= node_max.Z; z++)
- for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
- Biome *biome = (Biome *)bmgr->getRaw(biomemap[index]);
-
- if (biome->c_dust == CONTENT_IGNORE)
- continue;
-
- u32 vi = vm->m_area.index(x, full_node_max.Y, z);
- content_t c_full_max = vm->m_data[vi].getContent();
- s16 y_start;
-
- if (c_full_max == CONTENT_AIR) {
- y_start = full_node_max.Y - 1;
- } else if (c_full_max == CONTENT_IGNORE) {
- vi = vm->m_area.index(x, node_max.Y + 1, z);
- content_t c_max = vm->m_data[vi].getContent();
-
- if (c_max == CONTENT_AIR)
- y_start = node_max.Y;
- else
- continue;
- } else {
- continue;
- }
-
- vi = vm->m_area.index(x, y_start, z);
- for (s16 y = y_start; y >= node_min.Y - 1; y--) {
- if (vm->m_data[vi].getContent() != CONTENT_AIR)
- break;
-
- vm->m_area.add_y(em, vi, -1);
- }
-
- content_t c = vm->m_data[vi].getContent();
- if (!ndef->get(c).buildable_to && c != CONTENT_IGNORE && c != biome->c_dust) {
- vm->m_area.add_y(em, vi, 1);
- vm->m_data[vi] = MapNode(biome->c_dust);
- }
- }
-}
-
-
-void MapgenV5::generateCaves(int max_stone_y)
-{
- if (max_stone_y < node_min.Y)
- return;
-
- noise_cave1->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
- noise_cave2->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
-
- v3s16 em = vm->m_area.getExtent();
- u32 index2d = 0;
-
- for (s16 z = node_min.Z; z <= node_max.Z; z++)
- for (s16 x = node_min.X; x <= node_max.X; x++, index2d++) {
- bool column_is_open = false; // Is column open to overground
- bool is_tunnel = false; // Is tunnel or tunnel floor
- // Indexes at column top (node_max.Y)
- u32 vi = vm->m_area.index(x, node_max.Y, z);
- u32 index3d = (z - node_min.Z) * zstride_1d + csize.Y * ystride +
- (x - node_min.X);
- // Biome of column
- Biome *biome = (Biome *)bmgr->getRaw(biomemap[index2d]);
-
- // Don't excavate the overgenerated stone at node_max.Y + 1,
- // this creates a 'roof' over the tunnel, preventing light in
- // tunnels at mapchunk borders when generating mapchunks upwards.
- // This 'roof' is removed when the mapchunk above is generated.
- for (s16 y = node_max.Y; y >= node_min.Y - 1; y--,
- index3d -= ystride,
- vm->m_area.add_y(em, vi, -1)) {
-
- content_t c = vm->m_data[vi].getContent();
- if (c == CONTENT_AIR || c == biome->c_water_top ||
- c == biome->c_water) {
- column_is_open = true;
- continue;
- }
- // Ground
- float d1 = contour(noise_cave1->result[index3d]);
- float d2 = contour(noise_cave2->result[index3d]);
-
- if (d1 * d2 > cave_width && ndef->get(c).is_ground_content) {
- // In tunnel and ground content, excavate
- vm->m_data[vi] = MapNode(CONTENT_AIR);
- is_tunnel = true;
- } else {
- // Not in tunnel or not ground content
- if (is_tunnel && column_is_open &&
- (c == biome->c_filler || c == biome->c_stone))
- // Tunnel entrance floor
- vm->m_data[vi] = MapNode(biome->c_top);
-
- column_is_open = false;
- is_tunnel = false;
- }
- }
- }
-
- if (node_max.Y > MGV5_LARGE_CAVE_DEPTH)
- return;
-
- PseudoRandom ps(blockseed + 21343);
- u32 bruises_count = ps.range(0, 2);
- for (u32 i = 0; i < bruises_count; i++) {
- CaveV5 cave(this, &ps);
- cave.makeCave(node_min, node_max, max_stone_y);
- }
-}
diff --git a/src/mapgen_v5.h b/src/mapgen_v5.h
index eef3da617..99836b23e 100644
--- a/src/mapgen_v5.h
+++ b/src/mapgen_v5.h
@@ -48,34 +48,15 @@ struct MapgenV5Params : public MapgenSpecificParams {
};
-class MapgenV5 : public Mapgen {
+class MapgenV5 : public MapgenBasic {
public:
- EmergeManager *m_emerge;
- BiomeManager *bmgr;
-
- int ystride;
- int zstride_1d;
-
- v3s16 node_min;
- v3s16 node_max;
- v3s16 full_node_min;
- v3s16 full_node_max;
-
u32 spflags;
- float cave_width;
- Noise *noise_filler_depth;
Noise *noise_factor;
Noise *noise_height;
- Noise *noise_cave1;
- Noise *noise_cave2;
Noise *noise_ground;
- content_t c_stone;
- content_t c_water_source;
content_t c_lava_source;
- content_t c_desert_stone;
content_t c_ice;
- content_t c_sandstone;
content_t c_cobble;
content_t c_stair_cobble;
@@ -90,9 +71,6 @@ public:
int getSpawnLevelAtPoint(v2s16 p);
void calculateNoise();
int generateBaseTerrain();
- MgStoneType generateBiomes();
- void generateCaves(int max_stone_y);
- void dustTopNodes();
};
diff --git a/src/mapgen_v7.cpp b/src/mapgen_v7.cpp
index fddb34682..ee609bc95 100644
--- a/src/mapgen_v7.cpp
+++ b/src/mapgen_v7.cpp
@@ -51,7 +51,7 @@ FlagDesc flagdesc_mapgen_v7[] = {
MapgenV7::MapgenV7(int mapgenid, MapgenParams *params, EmergeManager *emerge)
- : Mapgen(mapgenid, params, emerge)
+ : MapgenBasic(mapgenid, params, emerge)
{
this->m_emerge = emerge;
this->bmgr = emerge->biomemgr;
@@ -276,7 +276,7 @@ void MapgenV7::makeChunk(BlockMakeData *data)
MgStoneType stone_type = generateBiomes();
if (flags & MG_CAVES)
- generateCaves(stone_surface_max_y);
+ generateCaves(stone_surface_max_y, water_level);
if ((flags & MG_DUNGEONS) && (stone_surface_max_y >= node_min.Y)) {
DungeonParams dp;
@@ -517,225 +517,13 @@ void MapgenV7::generateRidgeTerrain()
}
-MgStoneType MapgenV7::generateBiomes()
-{
- v3s16 em = vm->m_area.getExtent();
- u32 index = 0;
- MgStoneType stone_type = STONE;
-
- for (s16 z = node_min.Z; z <= node_max.Z; z++)
- for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
- Biome *biome = NULL;
- u16 depth_top = 0;
- u16 base_filler = 0;
- u16 depth_water_top = 0;
- u32 vi = vm->m_area.index(x, node_max.Y, z);
-
- // Check node at base of mapchunk above, either a node of a previously
- // generated mapchunk or if not, a node of overgenerated base terrain.
- content_t c_above = vm->m_data[vi + em.X].getContent();
- bool air_above = c_above == CONTENT_AIR;
- bool water_above = c_above == c_water_source;
-
- // If there is air or water above enable top/filler placement, otherwise force
- // nplaced to stone level by setting a number exceeding any possible filler depth.
- u16 nplaced = (air_above || water_above) ? 0 : U16_MAX;
-
- 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:
- // 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.
- if ((c == c_stone && (air_above || water_above || !biome)) ||
- (c == c_water_source && (air_above || !biome))) {
- biome = biomegen->getBiomeAtIndex(index, y);
-
- depth_top = biome->depth_top;
- base_filler = MYMAX(depth_top + biome->depth_filler
- + noise_filler_depth->result[index], 0);
- depth_water_top = biome->depth_water_top;
-
- // Detect stone type for dungeons during every biome calculation.
- // This is more efficient than detecting per-node and will not
- // miss any desert stone or sandstone biomes.
- if (biome->c_stone == c_desert_stone)
- stone_type = DESERT_STONE;
- else if (biome->c_stone == c_sandstone)
- stone_type = SANDSTONE;
- }
-
- if (c == c_stone) {
- content_t c_below = vm->m_data[vi - em.X].getContent();
-
- // If the node below isn't solid, make this node stone, so that
- // any top/filler nodes above are structurally supported.
- // This is done by aborting the cycle of top/filler placement
- // immediately by forcing nplaced to stone level.
- if (c_below == CONTENT_AIR || c_below == c_water_source)
- nplaced = U16_MAX;
-
- if (nplaced < depth_top) {
- vm->m_data[vi] = MapNode(biome->c_top);
- nplaced++;
- } else if (nplaced < base_filler) {
- vm->m_data[vi] = MapNode(biome->c_filler);
- nplaced++;
- } else {
- vm->m_data[vi] = MapNode(biome->c_stone);
- }
-
- air_above = false;
- water_above = false;
- } else if (c == c_water_source) {
- vm->m_data[vi] = MapNode((y > (s32)(water_level - depth_water_top)) ?
- biome->c_water_top : biome->c_water);
- nplaced = 0; // Enable top/filler placement for next surface
- air_above = false;
- water_above = true;
- } else if (c == CONTENT_AIR) {
- nplaced = 0; // Enable top/filler placement for next surface
- air_above = true;
- water_above = false;
- } else { // Possible various nodes overgenerated from neighbouring mapchunks
- nplaced = U16_MAX; // Disable top/filler placement
- air_above = false;
- water_above = false;
- }
-
- vm->m_area.add_y(em, vi, -1);
- }
- }
-
- return stone_type;
-}
-
-
-void MapgenV7::dustTopNodes()
-{
- if (node_max.Y < water_level)
- return;
-
- v3s16 em = vm->m_area.getExtent();
- u32 index = 0;
-
- for (s16 z = node_min.Z; z <= node_max.Z; z++)
- for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
- Biome *biome = (Biome *)bmgr->getRaw(biomemap[index]);
-
- if (biome->c_dust == CONTENT_IGNORE)
- continue;
-
- u32 vi = vm->m_area.index(x, full_node_max.Y, z);
- content_t c_full_max = vm->m_data[vi].getContent();
- s16 y_start;
-
- if (c_full_max == CONTENT_AIR) {
- y_start = full_node_max.Y - 1;
- } else if (c_full_max == CONTENT_IGNORE) {
- vi = vm->m_area.index(x, node_max.Y + 1, z);
- content_t c_max = vm->m_data[vi].getContent();
-
- if (c_max == CONTENT_AIR)
- y_start = node_max.Y;
- else
- continue;
- } else {
- continue;
- }
-
- vi = vm->m_area.index(x, y_start, z);
- for (s16 y = y_start; y >= node_min.Y - 1; y--) {
- if (vm->m_data[vi].getContent() != CONTENT_AIR)
- break;
-
- vm->m_area.add_y(em, vi, -1);
- }
-
- content_t c = vm->m_data[vi].getContent();
- if (!ndef->get(c).buildable_to && c != CONTENT_IGNORE && c != biome->c_dust) {
- vm->m_area.add_y(em, vi, 1);
- vm->m_data[vi] = MapNode(biome->c_dust);
- }
- }
-}
-
-
-void MapgenV7::generateCaves(s16 max_stone_y)
-{
- if (max_stone_y < node_min.Y)
- return;
-
- noise_cave1->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
- noise_cave2->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
-
- v3s16 em = vm->m_area.getExtent();
- u32 index2d = 0;
-
- for (s16 z = node_min.Z; z <= node_max.Z; z++)
- for (s16 x = node_min.X; x <= node_max.X; x++, index2d++) {
- bool column_is_open = false; // Is column open to overground
- bool is_tunnel = false; // Is tunnel or tunnel floor
- // Indexes at column top (node_max.Y)
- u32 vi = vm->m_area.index(x, node_max.Y, z);
- u32 index3d = (z - node_min.Z) * zstride_1d + csize.Y * ystride +
- (x - node_min.X);
- // Biome of column
- Biome *biome = (Biome *)bmgr->getRaw(biomemap[index2d]);
-
- // Don't excavate the overgenerated stone at node_max.Y + 1,
- // this creates a 'roof' over the tunnel, preventing light in
- // tunnels at mapchunk borders when generating mapchunks upwards.
- // This 'roof' is removed when the mapchunk above is generated.
- for (s16 y = node_max.Y; y >= node_min.Y - 1; y--,
- index3d -= ystride,
- vm->m_area.add_y(em, vi, -1)) {
-
- content_t c = vm->m_data[vi].getContent();
- if (c == CONTENT_AIR || c == biome->c_water_top ||
- c == biome->c_water) {
- column_is_open = true;
- continue;
- }
- // Ground
- float d1 = contour(noise_cave1->result[index3d]);
- float d2 = contour(noise_cave2->result[index3d]);
-
- if (d1 * d2 > cave_width && ndef->get(c).is_ground_content) {
- // In tunnel and ground content, excavate
- vm->m_data[vi] = MapNode(CONTENT_AIR);
- is_tunnel = true;
- } else {
- // Not in tunnel or not ground content
- if (is_tunnel && column_is_open &&
- (c == biome->c_filler || c == biome->c_stone))
- // Tunnel entrance floor
- vm->m_data[vi] = MapNode(biome->c_top);
-
- column_is_open = false;
- is_tunnel = false;
- }
- }
- }
-
- if (node_min.Y >= water_level)
- return;
-
- PseudoRandom ps(blockseed + 21343);
- u32 bruises_count = ps.range(0, 2);
- for (u32 i = 0; i < bruises_count; i++) {
- CaveV7 cave(this, &ps);
- cave.makeCave(node_min, node_max, max_stone_y);
- }
-}
-
-
-///////////////////////////////////////////////////////////////
-
+////////////////////////////////////////////////////////////////////////////////
+//// Code Boneyard
+////
+//// Much of the stuff here has potential to become useful again at some point
+//// in the future, but we don't want it to get lost or forgotten in version
+//// control.
+////
#if 0
int MapgenV7::generateMountainTerrain(s16 ymax)
diff --git a/src/mapgen_v7.h b/src/mapgen_v7.h
index a8dd9986d..21beab2b4 100644
--- a/src/mapgen_v7.h
+++ b/src/mapgen_v7.h
@@ -54,42 +54,24 @@ struct MapgenV7Params : public MapgenSpecificParams {
void writeParams(Settings *settings) const;
};
-class MapgenV7 : public Mapgen {
+class MapgenV7 : public MapgenBasic {
public:
- EmergeManager *m_emerge;
- BiomeManager *bmgr;
-
- int ystride;
int zstride_1u1d;
- int zstride_1d;
-
- v3s16 node_min;
- v3s16 node_max;
- v3s16 full_node_min;
- v3s16 full_node_max;
s16 *ridge_heightmap;
u32 spflags;
- float cave_width;
Noise *noise_terrain_base;
Noise *noise_terrain_alt;
Noise *noise_terrain_persist;
Noise *noise_height_select;
- Noise *noise_filler_depth;
Noise *noise_mount_height;
Noise *noise_ridge_uwater;
Noise *noise_mountain;
Noise *noise_ridge;
- Noise *noise_cave1;
- Noise *noise_cave2;
- content_t c_stone;
- content_t c_water_source;
content_t c_lava_source;
- content_t c_desert_stone;
content_t c_ice;
- content_t c_sandstone;
content_t c_cobble;
content_t c_stair_cobble;
@@ -112,11 +94,6 @@ public:
int generateTerrain();
void generateRidgeTerrain();
-
- MgStoneType generateBiomes();
- void dustTopNodes();
-
- void generateCaves(s16 max_stone_y);
};
struct MapgenFactoryV7 : public MapgenFactory {
diff --git a/src/mapgen_valleys.cpp b/src/mapgen_valleys.cpp
index 44083d9d3..fa790677a 100644
--- a/src/mapgen_valleys.cpp
+++ b/src/mapgen_valleys.cpp
@@ -65,7 +65,7 @@ static FlagDesc flagdesc_mapgen_valleys[] = {
MapgenValleys::MapgenValleys(int mapgenid, MapgenParams *params, EmergeManager *emerge)
- : Mapgen(mapgenid, params, emerge)
+ : MapgenBasic(mapgenid, params, emerge)
{
this->m_emerge = emerge;
this->bmgr = emerge->biomemgr;
@@ -302,7 +302,7 @@ void MapgenValleys::makeChunk(BlockMakeData *data)
// Cave creation.
if (flags & MG_CAVES)
- generateCaves(stone_surface_max_y);
+ generateCaves(stone_surface_max_y, large_cave_depth);
// Dungeon creation
if ((flags & MG_DUNGEONS) && node_max.Y < 50 && (stone_surface_max_y >= node_min.Y)) {
@@ -692,166 +692,7 @@ int MapgenValleys::generateTerrain()
return surface_max_y;
}
-
-MgStoneType MapgenValleys::generateBiomes()
-{
- v3s16 em = vm->m_area.getExtent();
- u32 index = 0;
- MgStoneType stone_type = STONE;
-
- for (s16 z = node_min.Z; z <= node_max.Z; z++)
- for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
- Biome *biome = NULL;
- u16 depth_top = 0;
- u16 base_filler = 0;
- u16 depth_water_top = 0;
- u32 vi = vm->m_area.index(x, node_max.Y, z);
-
- // Check node at base of mapchunk above, either a node of a previously
- // generated mapchunk or if not, a node of overgenerated base terrain.
- content_t c_above = vm->m_data[vi + em.X].getContent();
- bool air_above = c_above == CONTENT_AIR;
- bool water_above = (c_above == c_water_source || c_above == c_river_water_source);
-
- // If there is air or water above enable top/filler placement, otherwise force
- // nplaced to stone level by setting a number exceeding any possible filler depth.
- u16 nplaced = (air_above || water_above) ? 0 : U16_MAX;
-
- 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:
- // 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.
- if ((c == c_stone && (air_above || water_above || !biome))
- || ((c == c_water_source || c == c_river_water_source)
- && (air_above || !biome))) {
- // Both heat and humidity have already been adjusted for altitude.
- biome = biomegen->getBiomeAtIndex(index, y);
-
- depth_top = biome->depth_top;
- base_filler = MYMAX(depth_top
- + biome->depth_filler
- + noise_filler_depth->result[index], 0.f);
- depth_water_top = biome->depth_water_top;
-
- // Detect stone type for dungeons during every biome calculation.
- // This is more efficient than detecting per-node and will not
- // miss any desert stone or sandstone biomes.
- if (biome->c_stone == c_desert_stone)
- stone_type = DESERT_STONE;
- else if (biome->c_stone == c_sandstone)
- stone_type = SANDSTONE;
- }
-
- if (c == c_stone) {
- content_t c_below = vm->m_data[vi - em.X].getContent();
-
- // If the node below isn't solid, make this node stone, so that
- // any top/filler nodes above are structurally supported.
- // This is done by aborting the cycle of top/filler placement
- // immediately by forcing nplaced to stone level.
- if (c_below == CONTENT_AIR
- || c_below == c_water_source
- || c_below == c_river_water_source)
- nplaced = U16_MAX;
-
- if (nplaced < depth_top) {
- vm->m_data[vi] = MapNode(biome->c_top);
- nplaced++;
- } else if (nplaced < base_filler) {
- vm->m_data[vi] = MapNode(biome->c_filler);
- nplaced++;
- } else {
- vm->m_data[vi] = MapNode(biome->c_stone);
- }
-
- air_above = false;
- water_above = false;
- } else if (c == c_water_source) {
- vm->m_data[vi] = MapNode((y > (s32)(water_level - depth_water_top))
- ? biome->c_water_top : biome->c_water);
- nplaced = 0; // Enable top/filler placement for next surface
- air_above = false;
- water_above = true;
- } else if (c == c_river_water_source) {
- vm->m_data[vi] = MapNode(biome->c_river_water);
- nplaced = depth_top; // Enable filler placement for next surface
- air_above = false;
- water_above = true;
- } else if (c == CONTENT_AIR) {
- nplaced = 0; // Enable top/filler placement for next surface
- air_above = true;
- water_above = false;
- } else { // Possible various nodes overgenerated from neighbouring mapchunks
- nplaced = U16_MAX; // Disable top/filler placement
- air_above = false;
- water_above = false;
- }
-
- vm->m_area.add_y(em, vi, -1);
- }
- }
-
- return stone_type;
-}
-
-
-void MapgenValleys::dustTopNodes()
-{
- if (node_max.Y < water_level)
- return;
-
- v3s16 em = vm->m_area.getExtent();
- u32 index = 0;
-
- for (s16 z = node_min.Z; z <= node_max.Z; z++)
- for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
- Biome *biome = (Biome *)bmgr->getRaw(biomemap[index]);
-
- if (biome->c_dust == CONTENT_IGNORE)
- continue;
-
- u32 vi = vm->m_area.index(x, full_node_max.Y, z);
- content_t c_full_max = vm->m_data[vi].getContent();
- s16 y_start;
-
- if (c_full_max == CONTENT_AIR) {
- y_start = full_node_max.Y - 1;
- } else if (c_full_max == CONTENT_IGNORE) {
- vi = vm->m_area.index(x, node_max.Y + 1, z);
- content_t c_max = vm->m_data[vi].getContent();
-
- if (c_max == CONTENT_AIR)
- y_start = node_max.Y;
- else
- continue;
- } else {
- continue;
- }
-
- vi = vm->m_area.index(x, y_start, z);
- for (s16 y = y_start; y >= node_min.Y - 1; y--) {
- if (vm->m_data[vi].getContent() != CONTENT_AIR)
- break;
-
- vm->m_area.add_y(em, vi, -1);
- }
-
- content_t c = vm->m_data[vi].getContent();
- if (!ndef->get(c).buildable_to && c != CONTENT_IGNORE && c != biome->c_dust) {
- vm->m_area.add_y(em, vi, 1);
- vm->m_data[vi] = MapNode(biome->c_dust);
- }
- }
-}
-
-
-void MapgenValleys::generateCaves(s16 max_stone_y)
+void MapgenValleys::generateCaves(s16 max_stone_y, s16 large_cave_depth)
{
if (max_stone_y < node_min.Y)
return;
diff --git a/src/mapgen_valleys.h b/src/mapgen_valleys.h
index 0e268c1cf..2ab253430 100644
--- a/src/mapgen_valleys.h
+++ b/src/mapgen_valleys.h
@@ -85,7 +85,7 @@ struct TerrainNoise {
float inter_valley_fill;
};
-class MapgenValleys : public Mapgen {
+class MapgenValleys : public MapgenBasic {
public:
MapgenValleys(int mapgenid, MapgenParams *params, EmergeManager *emerge);
@@ -97,13 +97,9 @@ public:
s16 large_cave_depth;
private:
- EmergeManager *m_emerge;
- BiomeManager *bmgr;
BiomeGenOriginal *m_bgen;
- int ystride;
int zstride;
- int zstride_1d;
float map_gen_limit;
@@ -113,11 +109,6 @@ private:
s16 cave_water_max_height;
s16 lava_max_height;
- v3s16 node_min;
- v3s16 node_max;
- v3s16 full_node_min;
- v3s16 full_node_max;
-
u32 spflags;
float altitude_chill;
s16 lava_features_lim;
@@ -126,10 +117,6 @@ private:
float river_size_factor;
float *tcave_cache;
s16 water_features_lim;
- float cave_width;
- Noise *noise_filler_depth;
- Noise *noise_cave1;
- Noise *noise_cave2;
Noise *noise_inter_valley_fill;
Noise *noise_inter_valley_slope;
Noise *noise_rivers;
@@ -139,19 +126,13 @@ private:
Noise *noise_valley_profile;
content_t c_cobble;
- content_t c_desert_stone;
content_t c_dirt;
- content_t c_ice;
content_t c_lava_source;
content_t c_mossycobble;
- content_t c_river_water_source;
content_t c_sand;
- content_t c_sandstone;
content_t c_sandstonebrick;
content_t c_stair_cobble;
content_t c_stair_sandstonebrick;
- content_t c_stone;
- content_t c_water_source;
float terrainLevelAtPoint(s16 x, s16 z);
@@ -161,10 +142,7 @@ private:
float terrainLevelFromNoise(TerrainNoise *tn);
float adjustedTerrainLevelFromNoise(TerrainNoise *tn);
- MgStoneType generateBiomes();
- void dustTopNodes();
-
- void generateCaves(s16 max_stone_y);
+ virtual void generateCaves(s16 max_stone_y, s16 large_cave_depth);
};
struct MapgenFactoryValleys : public MapgenFactory {