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.
master
Paramat 2018-04-07 22:09:54 +01:00 committed by GitHub
parent 460b375cad
commit 746ca41f58
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 97 additions and 97 deletions

View File

@ -5676,6 +5676,17 @@ Definition tables
-- ^ Nodes placed as a blob of liquid in 50% of large caves. -- ^ Nodes placed as a blob of liquid in 50% of large caves.
-- ^ If absent, cave liquids fall back to classic behaviour of lava or -- ^ If absent, cave liquids fall back to classic behaviour of lava or
-- ^ water distributed according to a hardcoded 3D noise. -- ^ 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_max = 31000,
y_min = 1, y_min = 1,
-- ^ Upper and lower limits for biome. -- ^ Upper and lower limits for biome.

View File

@ -640,8 +640,7 @@ MapgenBasic::~MapgenBasic()
} }
void MapgenBasic::generateBiomes(MgStoneType *mgstone_type, void MapgenBasic::generateBiomes()
content_t *biome_stone)
{ {
// can't generate biomes without a biome generator! // can't generate biomes without a biome generator!
assert(biomegen); assert(biomegen);
@ -649,8 +648,6 @@ void MapgenBasic::generateBiomes(MgStoneType *mgstone_type,
const v3s16 &em = vm->m_area.getExtent(); const v3s16 &em = vm->m_area.getExtent();
u32 index = 0; 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); 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_water_top = biome->depth_water_top;
depth_riverbed = biome->depth_riverbed; depth_riverbed = biome->depth_riverbed;
biome_y_min = biome->min_pos.Y; 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) { if (c == c_stone) {
@ -776,9 +762,6 @@ void MapgenBasic::generateBiomes(MgStoneType *mgstone_type,
VoxelArea::add_y(em, vi, -1); 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, void MapgenBasic::generateDungeons(s16 max_stone_y)
MgStoneType stone_type, content_t biome_stone)
{ {
if (max_stone_y < node_min.Y) if (max_stone_y < node_min.Y)
return; 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; DungeonParams dp;
dp.seed = seed; dp.seed = seed;
dp.only_in_ground = true; dp.only_in_ground = true;
dp.corridor_len_min = 1; dp.corridor_len_min = 1;
dp.corridor_len_max = 13; dp.corridor_len_max = 13;
@ -899,9 +884,27 @@ void MapgenBasic::generateDungeons(s16 max_stone_y,
dp.np_density = nparams_dungeon_density; dp.np_density = nparams_dungeon_density;
dp.np_alt_wall = nparams_dungeon_alt_wall; dp.np_alt_wall = nparams_dungeon_alt_wall;
switch (stone_type) { // Biome-defined dungeon nodes
default: if (biome->c_dungeon != CONTENT_IGNORE) {
case MGSTONE_STONE: 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_wall = c_cobble;
dp.c_alt_wall = c_mossycobble; dp.c_alt_wall = c_mossycobble;
dp.c_stair = c_stair_cobble; 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_min = v3s16(8, 8, 8);
dp.room_size_large_max = v3s16(16, 16, 16); dp.room_size_large_max = v3s16(16, 16, 16);
dp.notifytype = GENNOTIFY_DUNGEON; 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_wall = c_desert_stone;
dp.c_alt_wall = CONTENT_IGNORE; dp.c_alt_wall = CONTENT_IGNORE;
dp.c_stair = c_stair_desert_stone; 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_min = v3s16(10, 13, 10);
dp.room_size_large_max = v3s16(18, 21, 18); dp.room_size_large_max = v3s16(18, 21, 18);
dp.notifytype = GENNOTIFY_TEMPLE; dp.notifytype = GENNOTIFY_TEMPLE;
break;
case MGSTONE_SANDSTONE: } else if (biome->c_stone == c_sandstone) {
dp.c_wall = c_sandstonebrick; dp.c_wall = c_sandstonebrick;
dp.c_alt_wall = CONTENT_IGNORE; dp.c_alt_wall = CONTENT_IGNORE;
dp.c_stair = c_stair_sandstone_block; 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_min = v3s16(10, 8, 10);
dp.room_size_large_max = v3s16(18, 16, 18); dp.room_size_large_max = v3s16(18, 16, 18);
dp.notifytype = GENNOTIFY_DUNGEON; dp.notifytype = GENNOTIFY_DUNGEON;
break;
case MGSTONE_OTHER: // Fallback to using biome 'node_stone'
dp.c_wall = biome_stone; } else {
dp.c_alt_wall = biome_stone; dp.c_wall = biome->c_stone;
dp.c_stair = biome_stone; dp.c_alt_wall = CONTENT_IGNORE;
dp.c_stair = biome->c_stone;
dp.diagonal_dirs = false; dp.diagonal_dirs = false;
dp.holesize = v3s16(1, 2, 1); dp.holesize = v3s16(2, 2, 2);
dp.room_size_min = v3s16(4, 4, 4); dp.room_size_min = v3s16(6, 4, 6);
dp.room_size_max = v3s16(8, 6, 8); dp.room_size_max = v3s16(10, 6, 10);
dp.room_size_large_min = v3s16(8, 8, 8); dp.room_size_large_min = v3s16(10, 8, 10);
dp.room_size_large_max = v3s16(16, 16, 16); dp.room_size_large_max = v3s16(18, 16, 18);
dp.notifytype = GENNOTIFY_DUNGEON; dp.notifytype = GENNOTIFY_DUNGEON;
break;
} }
DungeonGen dgen(ndef, &gennotify, &dp); DungeonGen dgen(ndef, &gennotify, &dp);

View File

@ -77,13 +77,6 @@ enum GenNotifyType {
NUM_GENNOTIFY_TYPES NUM_GENNOTIFY_TYPES
}; };
enum MgStoneType {
MGSTONE_STONE,
MGSTONE_DESERT_STONE,
MGSTONE_SANDSTONE,
MGSTONE_OTHER,
};
struct GenNotifyEvent { struct GenNotifyEvent {
GenNotifyType type; GenNotifyType type;
v3s16 pos; v3s16 pos;
@ -247,10 +240,8 @@ public:
virtual void generateCaves(s16 max_stone_y, s16 large_cave_depth); virtual void generateCaves(s16 max_stone_y, s16 large_cave_depth);
virtual bool generateCaverns(s16 max_stone_y); virtual bool generateCaverns(s16 max_stone_y);
virtual void generateDungeons(s16 max_stone_y, virtual void generateDungeons(s16 max_stone_y);
MgStoneType stone_type, content_t biome_stone); virtual void generateBiomes();
virtual void generateBiomes(MgStoneType *mgstone_type,
content_t *biome_stone);
virtual void dustTopNodes(); virtual void dustTopNodes();
protected: protected:

View File

@ -248,10 +248,7 @@ void MapgenCarpathian::makeChunk(BlockMakeData *data)
// Init biome generator, place biome-specific nodes, and build biomemap // Init biome generator, place biome-specific nodes, and build biomemap
biomegen->calcBiomeNoise(node_min); biomegen->calcBiomeNoise(node_min);
generateBiomes();
MgStoneType mgstone_type;
content_t biome_stone;
generateBiomes(&mgstone_type, &biome_stone);
// Generate caverns, tunnels and classic caves // Generate caverns, tunnels and classic caves
if (flags & MG_CAVES) { if (flags & MG_CAVES) {
@ -272,7 +269,7 @@ void MapgenCarpathian::makeChunk(BlockMakeData *data)
// Generate dungeons // Generate dungeons
if ((flags & MG_DUNGEONS) && full_node_min.Y >= dungeon_ymin && if ((flags & MG_DUNGEONS) && full_node_min.Y >= dungeon_ymin &&
full_node_max.Y <= dungeon_ymax) full_node_max.Y <= dungeon_ymax)
generateDungeons(stone_surface_max_y, mgstone_type, biome_stone); generateDungeons(stone_surface_max_y);
// Generate the registered decorations // Generate the registered decorations
if (flags & MG_DECORATIONS) if (flags & MG_DECORATIONS)

View File

@ -196,17 +196,14 @@ void MapgenFlat::makeChunk(BlockMakeData *data)
// Init biome generator, place biome-specific nodes, and build biomemap // Init biome generator, place biome-specific nodes, and build biomemap
biomegen->calcBiomeNoise(node_min); biomegen->calcBiomeNoise(node_min);
generateBiomes();
MgStoneType mgstone_type;
content_t biome_stone;
generateBiomes(&mgstone_type, &biome_stone);
if (flags & MG_CAVES) if (flags & MG_CAVES)
generateCaves(stone_surface_max_y, large_cave_depth); generateCaves(stone_surface_max_y, large_cave_depth);
if ((flags & MG_DUNGEONS) && full_node_min.Y >= dungeon_ymin && if ((flags & MG_DUNGEONS) && full_node_min.Y >= dungeon_ymin &&
full_node_max.Y <= dungeon_ymax) full_node_max.Y <= dungeon_ymax)
generateDungeons(stone_surface_max_y, mgstone_type, biome_stone); generateDungeons(stone_surface_max_y);
// Generate the registered decorations // Generate the registered decorations
if (flags & MG_DECORATIONS) if (flags & MG_DECORATIONS)

View File

@ -207,17 +207,14 @@ void MapgenFractal::makeChunk(BlockMakeData *data)
// Init biome generator, place biome-specific nodes, and build biomemap // Init biome generator, place biome-specific nodes, and build biomemap
biomegen->calcBiomeNoise(node_min); biomegen->calcBiomeNoise(node_min);
generateBiomes();
MgStoneType mgstone_type;
content_t biome_stone;
generateBiomes(&mgstone_type, &biome_stone);
if (flags & MG_CAVES) if (flags & MG_CAVES)
generateCaves(stone_surface_max_y, large_cave_depth); generateCaves(stone_surface_max_y, large_cave_depth);
if ((flags & MG_DUNGEONS) && full_node_min.Y >= dungeon_ymin && if ((flags & MG_DUNGEONS) && full_node_min.Y >= dungeon_ymin &&
full_node_max.Y <= dungeon_ymax) full_node_max.Y <= dungeon_ymax)
generateDungeons(stone_surface_max_y, mgstone_type, biome_stone); generateDungeons(stone_surface_max_y);
// Generate the registered decorations // Generate the registered decorations
if (flags & MG_DECORATIONS) if (flags & MG_DECORATIONS)

View File

@ -207,10 +207,7 @@ void MapgenV5::makeChunk(BlockMakeData *data)
// Init biome generator, place biome-specific nodes, and build biomemap // Init biome generator, place biome-specific nodes, and build biomemap
biomegen->calcBiomeNoise(node_min); biomegen->calcBiomeNoise(node_min);
generateBiomes();
MgStoneType mgstone_type;
content_t biome_stone;
generateBiomes(&mgstone_type, &biome_stone);
// Generate caverns, tunnels and classic caves // Generate caverns, tunnels and classic caves
if (flags & MG_CAVES) { if (flags & MG_CAVES) {
@ -231,7 +228,7 @@ void MapgenV5::makeChunk(BlockMakeData *data)
// Generate dungeons and desert temples // Generate dungeons and desert temples
if ((flags & MG_DUNGEONS) && full_node_min.Y >= dungeon_ymin && if ((flags & MG_DUNGEONS) && full_node_min.Y >= dungeon_ymin &&
full_node_max.Y <= dungeon_ymax) full_node_max.Y <= dungeon_ymax)
generateDungeons(stone_surface_max_y, mgstone_type, biome_stone); generateDungeons(stone_surface_max_y);
// Generate the registered decorations // Generate the registered decorations
if (flags & MG_DECORATIONS) if (flags & MG_DECORATIONS)

View File

@ -311,10 +311,7 @@ void MapgenV7::makeChunk(BlockMakeData *data)
// Init biome generator, place biome-specific nodes, and build biomemap // Init biome generator, place biome-specific nodes, and build biomemap
biomegen->calcBiomeNoise(node_min); biomegen->calcBiomeNoise(node_min);
generateBiomes();
MgStoneType mgstone_type;
content_t biome_stone;
generateBiomes(&mgstone_type, &biome_stone);
// Generate caverns, tunnels and classic caves // Generate caverns, tunnels and classic caves
if (flags & MG_CAVES) { if (flags & MG_CAVES) {
@ -335,7 +332,7 @@ void MapgenV7::makeChunk(BlockMakeData *data)
// Generate dungeons // Generate dungeons
if ((flags & MG_DUNGEONS) && full_node_min.Y >= dungeon_ymin && if ((flags & MG_DUNGEONS) && full_node_min.Y >= dungeon_ymin &&
full_node_max.Y <= dungeon_ymax) full_node_max.Y <= dungeon_ymax)
generateDungeons(stone_surface_max_y, mgstone_type, biome_stone); generateDungeons(stone_surface_max_y);
// Generate the registered decorations // Generate the registered decorations
if (flags & MG_DECORATIONS) if (flags & MG_DECORATIONS)

View File

@ -242,9 +242,7 @@ void MapgenValleys::makeChunk(BlockMakeData *data)
updateHeightmap(node_min, node_max); updateHeightmap(node_min, node_max);
// Place biome-specific nodes and build biomemap // Place biome-specific nodes and build biomemap
MgStoneType mgstone_type; generateBiomes();
content_t biome_stone;
generateBiomes(&mgstone_type, &biome_stone);
// Cave creation. // Cave creation.
if (flags & MG_CAVES) if (flags & MG_CAVES)
@ -253,7 +251,7 @@ void MapgenValleys::makeChunk(BlockMakeData *data)
// Dungeon creation // Dungeon creation
if ((flags & MG_DUNGEONS) && full_node_min.Y >= dungeon_ymin && if ((flags & MG_DUNGEONS) && full_node_min.Y >= dungeon_ymin &&
full_node_max.Y <= dungeon_ymax) full_node_max.Y <= dungeon_ymax)
generateDungeons(stone_surface_max_y, mgstone_type, biome_stone); generateDungeons(stone_surface_max_y);
// Generate the registered decorations // Generate the registered decorations
if (flags & MG_DECORATIONS) if (flags & MG_DECORATIONS)

View File

@ -63,6 +63,9 @@ BiomeManager::BiomeManager(Server *server) :
b->m_nodenames.emplace_back("mapgen_stone"); 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");
b->m_nodenames.emplace_back("ignore");
b->m_nodenames.emplace_back("ignore");
m_ndef->pendNodeResolve(b); m_ndef->pendNodeResolve(b);
add(b); add(b);
@ -323,4 +326,7 @@ void Biome::resolveNodeNames()
getIdFromNrBacklog(&c_riverbed, "mapgen_stone", CONTENT_AIR); getIdFromNrBacklog(&c_riverbed, "mapgen_stone", CONTENT_AIR);
getIdFromNrBacklog(&c_dust, "ignore", CONTENT_IGNORE); getIdFromNrBacklog(&c_dust, "ignore", CONTENT_IGNORE);
getIdFromNrBacklog(&c_cave_liquid, "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);
} }

View File

@ -53,6 +53,9 @@ public:
content_t c_riverbed; content_t c_riverbed;
content_t c_dust; content_t c_dust;
content_t c_cave_liquid; content_t c_cave_liquid;
content_t c_dungeon;
content_t c_dungeon_alt;
content_t c_dungeon_stair;
s16 depth_top; s16 depth_top;
s16 depth_filler; s16 depth_filler;

View File

@ -406,6 +406,9 @@ Biome *read_biome_def(lua_State *L, int index, const NodeDefManager *ndef)
nn.push_back(getstringfield_default(L, index, "node_riverbed", "")); 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_dust", ""));
nn.push_back(getstringfield_default(L, index, "node_cave_liquid", "")); 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); ndef->pendNodeResolve(b);
return b; return b;