Biome API / dungeons: Add biome-defined dungeon nodes
authorParamat <paramat@users.noreply.github.com>
Sat, 7 Apr 2018 21:09:54 +0000 (22:09 +0100)
committerGitHub <noreply@github.com>
Sat, 7 Apr 2018 21:09:54 +0000 (22:09 +0100)
Add new biome fields 'node_dungeon', 'node_dungeon_alt', 'node_dungeon_stair'.
If 'node_dungeon' is not defined dungeons fall back to classic behaviour.

Remove messy and imprecise dungeon material code from 'generateBiomes()'.
Code deciding dungeon materials is now in 'generateDungeons()' and uses the
biome at mapchunk centre for more precision.

Remove hardcoded 'MG_STONE' types as long intended.

12 files changed:
doc/lua_api.txt
src/mapgen/mapgen.cpp
src/mapgen/mapgen.h
src/mapgen/mapgen_carpathian.cpp
src/mapgen/mapgen_flat.cpp
src/mapgen/mapgen_fractal.cpp
src/mapgen/mapgen_v5.cpp
src/mapgen/mapgen_v7.cpp
src/mapgen/mapgen_valleys.cpp
src/mapgen/mg_biome.cpp
src/mapgen/mg_biome.h
src/script/lua_api/l_mapgen.cpp

index 620828824032a75b95b55759868c3c39068a713a..0c7d44adf15c1df21591379e304dbe722b176574 100644 (file)
@@ -5676,6 +5676,17 @@ Definition tables
     --  ^ Nodes placed as a blob of liquid in 50% of large caves.
     --  ^ If absent, cave liquids fall back to classic behaviour of lava or
     --  ^ water distributed according to a hardcoded 3D noise.
+        node_dungeon = "default:cobble",
+    --  ^ Node used for primary dungeon structure.
+    --  ^ If absent, dungeon materials fall back to classic behaviour.
+    --  ^ If present, the following two nodes are also used.
+        node_dungeon_alt = "default:mossycobble",
+    --  ^ Node used for randomly-distributed alternative structure nodes.
+    --  ^ If alternative structure nodes are not wanted leave this absent for
+    --  ^ performance reasons.
+        node_dungeon_stair = "stairs:stair_cobble",
+    --  ^ Node used for dungeon stairs.
+    --  ^ If absent, stairs fall back to 'node_dungeon'.
         y_max = 31000,
         y_min = 1,
     --  ^ Upper and lower limits for biome.
index 67dbee3f5414d9c03c0dccf41426f6be7be1a851..9562482c804d70afe006e58cc30a4a1253deed28 100644 (file)
@@ -640,8 +640,7 @@ MapgenBasic::~MapgenBasic()
 }
 
 
-void MapgenBasic::generateBiomes(MgStoneType *mgstone_type,
-       content_t *biome_stone)
+void MapgenBasic::generateBiomes()
 {
        // can't generate biomes without a biome generator!
        assert(biomegen);
@@ -649,8 +648,6 @@ void MapgenBasic::generateBiomes(MgStoneType *mgstone_type,
 
        const v3s16 &em = vm->m_area.getExtent();
        u32 index = 0;
-       MgStoneType stone_type = MGSTONE_OTHER;
-       content_t c_biome_stone = c_stone;
 
        noise_filler_depth->perlinMap2D(node_min.X, node_min.Z);
 
@@ -705,17 +702,6 @@ void MapgenBasic::generateBiomes(MgStoneType *mgstone_type,
                                depth_water_top = biome->depth_water_top;
                                depth_riverbed = biome->depth_riverbed;
                                biome_y_min = biome->min_pos.Y;
-
-                               // Detect stone type for dungeons during every biome calculation.
-                               // If none detected the last selected biome stone is chosen.
-                               if (biome->c_stone == c_stone)
-                                       stone_type = MGSTONE_STONE;
-                               else if (biome->c_stone == c_desert_stone)
-                                       stone_type = MGSTONE_DESERT_STONE;
-                               else if (biome->c_stone == c_sandstone)
-                                       stone_type = MGSTONE_SANDSTONE;
-
-                               c_biome_stone = biome->c_stone;
                        }
 
                        if (c == c_stone) {
@@ -776,9 +762,6 @@ void MapgenBasic::generateBiomes(MgStoneType *mgstone_type,
                        VoxelArea::add_y(em, vi, -1);
                }
        }
-
-       *mgstone_type = stone_type;
-       *biome_stone = c_biome_stone;
 }
 
 
@@ -878,16 +861,18 @@ bool MapgenBasic::generateCaverns(s16 max_stone_y)
 }
 
 
-void MapgenBasic::generateDungeons(s16 max_stone_y,
-       MgStoneType stone_type, content_t biome_stone)
+void MapgenBasic::generateDungeons(s16 max_stone_y)
 {
        if (max_stone_y < node_min.Y)
                return;
 
+       // Get biome at mapchunk midpoint
+       v3s16 chunk_mid = node_min + (node_max - node_min) / v3s16(2, 2, 2);
+       Biome *biome = (Biome *)biomegen->calcBiomeAtPoint(chunk_mid);
+
        DungeonParams dp;
 
        dp.seed             = seed;
-
        dp.only_in_ground   = true;
        dp.corridor_len_min = 1;
        dp.corridor_len_max = 13;
@@ -899,9 +884,27 @@ void MapgenBasic::generateDungeons(s16 max_stone_y,
        dp.np_density       = nparams_dungeon_density;
        dp.np_alt_wall      = nparams_dungeon_alt_wall;
 
-       switch (stone_type) {
-       default:
-       case MGSTONE_STONE:
+       // Biome-defined dungeon nodes
+       if (biome->c_dungeon != CONTENT_IGNORE) {
+               dp.c_wall              = biome->c_dungeon;
+               // If 'node_dungeon_alt' is not defined by biome, it and dp.c_alt_wall
+               // become CONTENT_IGNORE which skips the alt wall node placement loop in
+               // dungeongen.cpp.
+               dp.c_alt_wall          = biome->c_dungeon_alt;
+               // Stairs fall back to 'c_dungeon' if not defined by biome
+               dp.c_stair = (biome->c_dungeon_stair != CONTENT_IGNORE) ?
+                       biome->c_dungeon_stair : biome->c_dungeon;
+
+               dp.diagonal_dirs       = false;
+               dp.holesize            = v3s16(2, 2, 2);
+               dp.room_size_min       = v3s16(6, 4, 6);
+               dp.room_size_max       = v3s16(10, 6, 10);
+               dp.room_size_large_min = v3s16(10, 8, 10);
+               dp.room_size_large_max = v3s16(18, 16, 18);
+               dp.notifytype          = GENNOTIFY_DUNGEON;
+
+       // Otherwise classic behaviour
+       } else if (biome->c_stone == c_stone) {
                dp.c_wall              = c_cobble;
                dp.c_alt_wall          = c_mossycobble;
                dp.c_stair             = c_stair_cobble;
@@ -913,8 +916,8 @@ void MapgenBasic::generateDungeons(s16 max_stone_y,
                dp.room_size_large_min = v3s16(8, 8, 8);
                dp.room_size_large_max = v3s16(16, 16, 16);
                dp.notifytype          = GENNOTIFY_DUNGEON;
-               break;
-       case MGSTONE_DESERT_STONE:
+
+       } else if (biome->c_stone == c_desert_stone) {
                dp.c_wall              = c_desert_stone;
                dp.c_alt_wall          = CONTENT_IGNORE;
                dp.c_stair             = c_stair_desert_stone;
@@ -926,8 +929,8 @@ void MapgenBasic::generateDungeons(s16 max_stone_y,
                dp.room_size_large_min = v3s16(10, 13, 10);
                dp.room_size_large_max = v3s16(18, 21, 18);
                dp.notifytype          = GENNOTIFY_TEMPLE;
-               break;
-       case MGSTONE_SANDSTONE:
+
+       } else if (biome->c_stone == c_sandstone) {
                dp.c_wall              = c_sandstonebrick;
                dp.c_alt_wall          = CONTENT_IGNORE;
                dp.c_stair             = c_stair_sandstone_block;
@@ -939,20 +942,20 @@ void MapgenBasic::generateDungeons(s16 max_stone_y,
                dp.room_size_large_min = v3s16(10, 8, 10);
                dp.room_size_large_max = v3s16(18, 16, 18);
                dp.notifytype          = GENNOTIFY_DUNGEON;
-               break;
-       case MGSTONE_OTHER:
-               dp.c_wall              = biome_stone;
-               dp.c_alt_wall          = biome_stone;
-               dp.c_stair             = biome_stone;
+
+       // Fallback to using biome 'node_stone'
+       } else {
+               dp.c_wall              = biome->c_stone;
+               dp.c_alt_wall          = CONTENT_IGNORE;
+               dp.c_stair             = biome->c_stone;
 
                dp.diagonal_dirs       = false;
-               dp.holesize            = v3s16(1, 2, 1);
-               dp.room_size_min       = v3s16(4, 4, 4);
-               dp.room_size_max       = v3s16(8, 6, 8);
-               dp.room_size_large_min = v3s16(8, 8, 8);
-               dp.room_size_large_max = v3s16(16, 16, 16);
+               dp.holesize            = v3s16(2, 2, 2);
+               dp.room_size_min       = v3s16(6, 4, 6);
+               dp.room_size_max       = v3s16(10, 6, 10);
+               dp.room_size_large_min = v3s16(10, 8, 10);
+               dp.room_size_large_max = v3s16(18, 16, 18);
                dp.notifytype          = GENNOTIFY_DUNGEON;
-               break;
        }
 
        DungeonGen dgen(ndef, &gennotify, &dp);
index 2ebba68eab311d5f317f3c2f0732791c2fa7f5d4..51d23cd28a8cde12c714547f31b08afb8e6ffb1c 100644 (file)
@@ -77,13 +77,6 @@ enum GenNotifyType {
        NUM_GENNOTIFY_TYPES
 };
 
-enum MgStoneType {
-       MGSTONE_STONE,
-       MGSTONE_DESERT_STONE,
-       MGSTONE_SANDSTONE,
-       MGSTONE_OTHER,
-};
-
 struct GenNotifyEvent {
        GenNotifyType type;
        v3s16 pos;
@@ -247,10 +240,8 @@ public:
 
        virtual void generateCaves(s16 max_stone_y, s16 large_cave_depth);
        virtual bool generateCaverns(s16 max_stone_y);
-       virtual void generateDungeons(s16 max_stone_y,
-               MgStoneType stone_type, content_t biome_stone);
-       virtual void generateBiomes(MgStoneType *mgstone_type,
-               content_t *biome_stone);
+       virtual void generateDungeons(s16 max_stone_y);
+       virtual void generateBiomes();
        virtual void dustTopNodes();
 
 protected:
index 24f570b6497d06c3d2c94346d0146948c6f335c1..37c769693ba3f341cdd83e1b479714207736db75 100644 (file)
@@ -248,10 +248,7 @@ void MapgenCarpathian::makeChunk(BlockMakeData *data)
 
        // Init biome generator, place biome-specific nodes, and build biomemap
        biomegen->calcBiomeNoise(node_min);
-
-       MgStoneType mgstone_type;
-       content_t biome_stone;
-       generateBiomes(&mgstone_type, &biome_stone);
+       generateBiomes();
 
        // Generate caverns, tunnels and classic caves
        if (flags & MG_CAVES) {
@@ -272,7 +269,7 @@ void MapgenCarpathian::makeChunk(BlockMakeData *data)
        // Generate dungeons
        if ((flags & MG_DUNGEONS) && full_node_min.Y >= dungeon_ymin &&
                        full_node_max.Y <= dungeon_ymax)
-               generateDungeons(stone_surface_max_y, mgstone_type, biome_stone);
+               generateDungeons(stone_surface_max_y);
 
        // Generate the registered decorations
        if (flags & MG_DECORATIONS)
index 57d358e86bf7ee7038cbf64e5eac8a877a86e160..60b30137b9763acce55238c4b23cc16f6fdb6ee6 100644 (file)
@@ -196,17 +196,14 @@ void MapgenFlat::makeChunk(BlockMakeData *data)
 
        // Init biome generator, place biome-specific nodes, and build biomemap
        biomegen->calcBiomeNoise(node_min);
-
-       MgStoneType mgstone_type;
-       content_t biome_stone;
-       generateBiomes(&mgstone_type, &biome_stone);
+       generateBiomes();
 
        if (flags & MG_CAVES)
                generateCaves(stone_surface_max_y, large_cave_depth);
 
        if ((flags & MG_DUNGEONS) && full_node_min.Y >= dungeon_ymin &&
                        full_node_max.Y <= dungeon_ymax)
-               generateDungeons(stone_surface_max_y, mgstone_type, biome_stone);
+               generateDungeons(stone_surface_max_y);
 
        // Generate the registered decorations
        if (flags & MG_DECORATIONS)
index 45526b13875390f14dbf037785b11ff32784bc5d..10397f7b824f1da5b4cbe33541cc5e2c68a016f0 100644 (file)
@@ -207,17 +207,14 @@ void MapgenFractal::makeChunk(BlockMakeData *data)
 
        // Init biome generator, place biome-specific nodes, and build biomemap
        biomegen->calcBiomeNoise(node_min);
-
-       MgStoneType mgstone_type;
-       content_t biome_stone;
-       generateBiomes(&mgstone_type, &biome_stone);
+       generateBiomes();
 
        if (flags & MG_CAVES)
                generateCaves(stone_surface_max_y, large_cave_depth);
 
        if ((flags & MG_DUNGEONS) && full_node_min.Y >= dungeon_ymin &&
                        full_node_max.Y <= dungeon_ymax)
-               generateDungeons(stone_surface_max_y, mgstone_type, biome_stone);
+               generateDungeons(stone_surface_max_y);
 
        // Generate the registered decorations
        if (flags & MG_DECORATIONS)
index 2e788e8f1e79166acbefdb9fecce43bf465ec55c..aabc86c4d7c6b89d48aae452ab9e1cb0101888d8 100644 (file)
@@ -207,10 +207,7 @@ void MapgenV5::makeChunk(BlockMakeData *data)
 
        // Init biome generator, place biome-specific nodes, and build biomemap
        biomegen->calcBiomeNoise(node_min);
-
-       MgStoneType mgstone_type;
-       content_t biome_stone;
-       generateBiomes(&mgstone_type, &biome_stone);
+       generateBiomes();
 
        // Generate caverns, tunnels and classic caves
        if (flags & MG_CAVES) {
@@ -231,7 +228,7 @@ void MapgenV5::makeChunk(BlockMakeData *data)
        // Generate dungeons and desert temples
        if ((flags & MG_DUNGEONS) && full_node_min.Y >= dungeon_ymin &&
                        full_node_max.Y <= dungeon_ymax)
-               generateDungeons(stone_surface_max_y, mgstone_type, biome_stone);
+               generateDungeons(stone_surface_max_y);
 
        // Generate the registered decorations
        if (flags & MG_DECORATIONS)
index a99a50f297d4d2514d46590affa904e5e66234f6..c83a5105dcd42ed20d7298f8cec5ec6d93656360 100644 (file)
@@ -311,10 +311,7 @@ void MapgenV7::makeChunk(BlockMakeData *data)
 
        // Init biome generator, place biome-specific nodes, and build biomemap
        biomegen->calcBiomeNoise(node_min);
-
-       MgStoneType mgstone_type;
-       content_t biome_stone;
-       generateBiomes(&mgstone_type, &biome_stone);
+       generateBiomes();
 
        // Generate caverns, tunnels and classic caves
        if (flags & MG_CAVES) {
@@ -335,7 +332,7 @@ void MapgenV7::makeChunk(BlockMakeData *data)
        // Generate dungeons
        if ((flags & MG_DUNGEONS) && full_node_min.Y >= dungeon_ymin &&
                        full_node_max.Y <= dungeon_ymax)
-               generateDungeons(stone_surface_max_y, mgstone_type, biome_stone);
+               generateDungeons(stone_surface_max_y);
 
        // Generate the registered decorations
        if (flags & MG_DECORATIONS)
index f4c3c7b79a0513173f5b9c56dff6ceee1098bc91..af88456153a0d33b9c4a18b51f6f9dd9045fa4dc 100644 (file)
@@ -242,9 +242,7 @@ void MapgenValleys::makeChunk(BlockMakeData *data)
        updateHeightmap(node_min, node_max);
 
        // Place biome-specific nodes and build biomemap
-       MgStoneType mgstone_type;
-       content_t biome_stone;
-       generateBiomes(&mgstone_type, &biome_stone);
+       generateBiomes();
 
        // Cave creation.
        if (flags & MG_CAVES)
@@ -253,7 +251,7 @@ void MapgenValleys::makeChunk(BlockMakeData *data)
        // Dungeon creation
        if ((flags & MG_DUNGEONS) && full_node_min.Y >= dungeon_ymin &&
                        full_node_max.Y <= dungeon_ymax)
-               generateDungeons(stone_surface_max_y, mgstone_type, biome_stone);
+               generateDungeons(stone_surface_max_y);
 
        // Generate the registered decorations
        if (flags & MG_DECORATIONS)
index 584dea9c4580fa1402bfb55adaa899d1a90306a8..16e276b53b846035e43d4f5f86cbc48f8b8e2b7c 100644 (file)
@@ -63,6 +63,9 @@ BiomeManager::BiomeManager(Server *server) :
        b->m_nodenames.emplace_back("mapgen_stone");
        b->m_nodenames.emplace_back("ignore");
        b->m_nodenames.emplace_back("ignore");
+       b->m_nodenames.emplace_back("ignore");
+       b->m_nodenames.emplace_back("ignore");
+       b->m_nodenames.emplace_back("ignore");
        m_ndef->pendNodeResolve(b);
 
        add(b);
@@ -314,13 +317,16 @@ Biome *BiomeGenOriginal::calcBiomeFromNoise(float heat, float humidity, v3s16 po
 
 void Biome::resolveNodeNames()
 {
-       getIdFromNrBacklog(&c_top,         "mapgen_stone",              CONTENT_AIR);
-       getIdFromNrBacklog(&c_filler,      "mapgen_stone",              CONTENT_AIR);
-       getIdFromNrBacklog(&c_stone,       "mapgen_stone",              CONTENT_AIR);
-       getIdFromNrBacklog(&c_water_top,   "mapgen_water_source",       CONTENT_AIR);
-       getIdFromNrBacklog(&c_water,       "mapgen_water_source",       CONTENT_AIR);
-       getIdFromNrBacklog(&c_river_water, "mapgen_river_water_source", CONTENT_AIR);
-       getIdFromNrBacklog(&c_riverbed,    "mapgen_stone",              CONTENT_AIR);
-       getIdFromNrBacklog(&c_dust,        "ignore",                    CONTENT_IGNORE);
-       getIdFromNrBacklog(&c_cave_liquid, "ignore",                    CONTENT_IGNORE);
+       getIdFromNrBacklog(&c_top,           "mapgen_stone",              CONTENT_AIR);
+       getIdFromNrBacklog(&c_filler,        "mapgen_stone",              CONTENT_AIR);
+       getIdFromNrBacklog(&c_stone,         "mapgen_stone",              CONTENT_AIR);
+       getIdFromNrBacklog(&c_water_top,     "mapgen_water_source",       CONTENT_AIR);
+       getIdFromNrBacklog(&c_water,         "mapgen_water_source",       CONTENT_AIR);
+       getIdFromNrBacklog(&c_river_water,   "mapgen_river_water_source", CONTENT_AIR);
+       getIdFromNrBacklog(&c_riverbed,      "mapgen_stone",              CONTENT_AIR);
+       getIdFromNrBacklog(&c_dust,          "ignore",                    CONTENT_IGNORE);
+       getIdFromNrBacklog(&c_cave_liquid,   "ignore",                    CONTENT_IGNORE);
+       getIdFromNrBacklog(&c_dungeon,       "ignore",                    CONTENT_IGNORE);
+       getIdFromNrBacklog(&c_dungeon_alt,   "ignore",                    CONTENT_IGNORE);
+       getIdFromNrBacklog(&c_dungeon_stair, "ignore",                    CONTENT_IGNORE);
 }
index 27b6ebf95678cc1fd283d8748cd561713ff8ddce..1f60f7baca431919591ff1df96743d03f3cd5f1c 100644 (file)
@@ -53,6 +53,9 @@ public:
        content_t c_riverbed;
        content_t c_dust;
        content_t c_cave_liquid;
+       content_t c_dungeon;
+       content_t c_dungeon_alt;
+       content_t c_dungeon_stair;
 
        s16 depth_top;
        s16 depth_filler;
index 03a2b3eea8a3445220b7c71f5276512d146e68b8..6fe0d322e8cc27c5755d826adc86e3b888beb558 100644 (file)
@@ -397,15 +397,18 @@ Biome *read_biome_def(lua_State *L, int index, const NodeDefManager *ndef)
        getintfield(L, index, "y_max", b->max_pos.Y);
 
        std::vector<std::string> &nn = b->m_nodenames;
-       nn.push_back(getstringfield_default(L, index, "node_top",         ""));
-       nn.push_back(getstringfield_default(L, index, "node_filler",      ""));
-       nn.push_back(getstringfield_default(L, index, "node_stone",       ""));
-       nn.push_back(getstringfield_default(L, index, "node_water_top",   ""));
-       nn.push_back(getstringfield_default(L, index, "node_water",       ""));
-       nn.push_back(getstringfield_default(L, index, "node_river_water", ""));
-       nn.push_back(getstringfield_default(L, index, "node_riverbed",    ""));
-       nn.push_back(getstringfield_default(L, index, "node_dust",        ""));
-       nn.push_back(getstringfield_default(L, index, "node_cave_liquid", ""));
+       nn.push_back(getstringfield_default(L, index, "node_top",           ""));
+       nn.push_back(getstringfield_default(L, index, "node_filler",        ""));
+       nn.push_back(getstringfield_default(L, index, "node_stone",         ""));
+       nn.push_back(getstringfield_default(L, index, "node_water_top",     ""));
+       nn.push_back(getstringfield_default(L, index, "node_water",         ""));
+       nn.push_back(getstringfield_default(L, index, "node_river_water",   ""));
+       nn.push_back(getstringfield_default(L, index, "node_riverbed",      ""));
+       nn.push_back(getstringfield_default(L, index, "node_dust",          ""));
+       nn.push_back(getstringfield_default(L, index, "node_cave_liquid",   ""));
+       nn.push_back(getstringfield_default(L, index, "node_dungeon",       ""));
+       nn.push_back(getstringfield_default(L, index, "node_dungeon_alt",   ""));
+       nn.push_back(getstringfield_default(L, index, "node_dungeon_stair", ""));
        ndef->pendNodeResolve(b);
 
        return b;