From 746ca41f58e356b0fbeeca1b43b7061ad1e1c02d Mon Sep 17 00:00:00 2001 From: Paramat Date: Sat, 7 Apr 2018 22:09:54 +0100 Subject: [PATCH] Biome API / dungeons: Add biome-defined dungeon nodes 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. --- doc/lua_api.txt | 11 +++++ src/mapgen/mapgen.cpp | 81 +++++++++++++++++--------------- src/mapgen/mapgen.h | 13 +---- src/mapgen/mapgen_carpathian.cpp | 7 +-- src/mapgen/mapgen_flat.cpp | 7 +-- src/mapgen/mapgen_fractal.cpp | 7 +-- src/mapgen/mapgen_v5.cpp | 7 +-- src/mapgen/mapgen_v7.cpp | 7 +-- src/mapgen/mapgen_valleys.cpp | 6 +-- src/mapgen/mg_biome.cpp | 24 ++++++---- src/mapgen/mg_biome.h | 3 ++ src/script/lua_api/l_mapgen.cpp | 21 +++++---- 12 files changed, 97 insertions(+), 97 deletions(-) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 620828824..0c7d44adf 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -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. diff --git a/src/mapgen/mapgen.cpp b/src/mapgen/mapgen.cpp index 67dbee3f5..9562482c8 100644 --- a/src/mapgen/mapgen.cpp +++ b/src/mapgen/mapgen.cpp @@ -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); diff --git a/src/mapgen/mapgen.h b/src/mapgen/mapgen.h index 2ebba68ea..51d23cd28 100644 --- a/src/mapgen/mapgen.h +++ b/src/mapgen/mapgen.h @@ -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: diff --git a/src/mapgen/mapgen_carpathian.cpp b/src/mapgen/mapgen_carpathian.cpp index 24f570b64..37c769693 100644 --- a/src/mapgen/mapgen_carpathian.cpp +++ b/src/mapgen/mapgen_carpathian.cpp @@ -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) diff --git a/src/mapgen/mapgen_flat.cpp b/src/mapgen/mapgen_flat.cpp index 57d358e86..60b30137b 100644 --- a/src/mapgen/mapgen_flat.cpp +++ b/src/mapgen/mapgen_flat.cpp @@ -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) diff --git a/src/mapgen/mapgen_fractal.cpp b/src/mapgen/mapgen_fractal.cpp index 45526b138..10397f7b8 100644 --- a/src/mapgen/mapgen_fractal.cpp +++ b/src/mapgen/mapgen_fractal.cpp @@ -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) diff --git a/src/mapgen/mapgen_v5.cpp b/src/mapgen/mapgen_v5.cpp index 2e788e8f1..aabc86c4d 100644 --- a/src/mapgen/mapgen_v5.cpp +++ b/src/mapgen/mapgen_v5.cpp @@ -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) diff --git a/src/mapgen/mapgen_v7.cpp b/src/mapgen/mapgen_v7.cpp index a99a50f29..c83a5105d 100644 --- a/src/mapgen/mapgen_v7.cpp +++ b/src/mapgen/mapgen_v7.cpp @@ -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) diff --git a/src/mapgen/mapgen_valleys.cpp b/src/mapgen/mapgen_valleys.cpp index f4c3c7b79..af8845615 100644 --- a/src/mapgen/mapgen_valleys.cpp +++ b/src/mapgen/mapgen_valleys.cpp @@ -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) diff --git a/src/mapgen/mg_biome.cpp b/src/mapgen/mg_biome.cpp index 584dea9c4..16e276b53 100644 --- a/src/mapgen/mg_biome.cpp +++ b/src/mapgen/mg_biome.cpp @@ -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); } diff --git a/src/mapgen/mg_biome.h b/src/mapgen/mg_biome.h index 27b6ebf95..1f60f7bac 100644 --- a/src/mapgen/mg_biome.h +++ b/src/mapgen/mg_biome.h @@ -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; diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp index 03a2b3eea..6fe0d322e 100644 --- a/src/script/lua_api/l_mapgen.cpp +++ b/src/script/lua_api/l_mapgen.cpp @@ -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 &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;