Skip to content

Commit b1b40fe

Browse files
authoredMay 18, 2019
Allow multiple cave liquids in a biome definition (#8481)
This allows games to specify biome cave liquids and avoid the old hardcoded behaviour, but preserves the ability to have multiple cave liquids in one biome, such as lava and water. When multiple cave liquids are defined by the biome definition, make each entire cave use a randomly chosen liquid, instead of every small cave segment using a randomly chosen liquid. Plus an optimisation: Don't place nodes if cave liquid is defined as 'air'
1 parent 6cb6aea commit b1b40fe

File tree

6 files changed

+52
-31
lines changed

6 files changed

+52
-31
lines changed
 

Diff for: ‎doc/lua_api.txt

+8-4
Original file line numberDiff line numberDiff line change
@@ -6510,10 +6510,14 @@ Used by `minetest.register_biome`.
65106510
depth_riverbed = 2,
65116511
-- Node placed under river water and thickness of this layer
65126512

6513-
node_cave_liquid = "default:water_source",
6514-
-- Nodes placed as a blob of liquid in 50% of large caves.
6515-
-- If absent, cave liquids fall back to classic behaviour of lava or
6516-
-- water distributed according to a hardcoded 3D noise.
6513+
node_cave_liquid = "default:lava_source",
6514+
node_cave_liquid = {"default:water_source", "default:lava_source"},
6515+
-- Nodes placed inside 50% of the medium size caves.
6516+
-- Multiple nodes can be specified, each cave will use a randomly
6517+
-- chosen node from the list.
6518+
-- If this field is left out or 'nil', cave liquids fall back to
6519+
-- classic behaviour of lava and water distributed using 3D noise.
6520+
-- For no cave liquid, specify "air".
65176521

65186522
node_dungeon = "default:cobble",
65196523
-- Node used for primary dungeon structure.

Diff for: ‎src/mapgen/cavegen.cpp

+29-24
Original file line numberDiff line numberDiff line change
@@ -321,9 +321,26 @@ void CavesRandomWalk::makeCave(MMVManip *vm, v3s16 nmin, v3s16 nmax,
321321

322322
this->ystride = nmax.X - nmin.X + 1;
323323

324+
flooded = ps->range(1, 2) == 2;
325+
326+
// If flooded:
327+
// Get biome at mapchunk midpoint. If cave liquid defined for biome, use it.
328+
// If defined liquid is "air", disable 'flooded' to avoid placing "air".
329+
use_biome_liquid = false;
330+
if (flooded && bmgn) {
331+
v3s16 midp = node_min + (node_max - node_min) / v3s16(2, 2, 2);
332+
Biome *biome = (Biome *)bmgn->getBiomeAtPoint(midp);
333+
if (biome->c_cave_liquid[0] != CONTENT_IGNORE) {
334+
use_biome_liquid = true;
335+
c_biome_liquid =
336+
biome->c_cave_liquid[ps->range(0, biome->c_cave_liquid.size() - 1)];
337+
if (c_biome_liquid == CONTENT_AIR)
338+
flooded = false;
339+
}
340+
}
341+
324342
// Set initial parameters from randomness
325343
int dswitchint = ps->range(1, 14);
326-
flooded = ps->range(1, 2) == 2;
327344

328345
if (large_cave) {
329346
part_max_length_rs = ps->range(2, 4);
@@ -502,31 +519,19 @@ void CavesRandomWalk::carveRoute(v3f vec, float f, bool randomize_xz)
502519
fp.Z += 0.1f * ps->range(-10, 10);
503520
v3s16 cp(fp.X, fp.Y, fp.Z);
504521

505-
// Get biome at 'cp + of', the absolute centre point of this route
506-
v3s16 cpabs = cp + of;
522+
// Choose cave liquid
507523
MapNode liquidnode = CONTENT_IGNORE;
508524

509-
if (bmgn) {
510-
Biome *biome = nullptr;
511-
if (cpabs.X < node_min.X || cpabs.X > node_max.X ||
512-
cpabs.Z < node_min.Z || cpabs.Z > node_max.Z)
513-
// Point is outside heat and humidity noise maps so use point noise
514-
// calculations.
515-
biome = (Biome *)bmgn->calcBiomeAtPoint(cpabs);
516-
else
517-
// Point is inside heat and humidity noise maps so use them
518-
biome = (Biome *)bmgn->getBiomeAtPoint(cpabs);
519-
520-
if (biome->c_cave_liquid != CONTENT_IGNORE)
521-
liquidnode = biome->c_cave_liquid;
522-
}
523-
524-
if (liquidnode == CONTENT_IGNORE) {
525-
// Fallback to classic behaviour using point 'startp'
526-
float nval = NoisePerlin3D(np_caveliquids, startp.X,
527-
startp.Y, startp.Z, seed);
528-
liquidnode = (nval < 0.40f && node_max.Y < lava_depth) ?
529-
lavanode : waternode;
525+
if (flooded) {
526+
if (use_biome_liquid) {
527+
liquidnode = c_biome_liquid;
528+
} else {
529+
// If cave liquid not defined by biome, fallback to old hardcoded behaviour
530+
float nval = NoisePerlin3D(np_caveliquids, startp.X,
531+
startp.Y, startp.Z, seed);
532+
liquidnode = (nval < 0.40f && node_max.Y < lava_depth) ?
533+
lavanode : waternode;
534+
}
530535
}
531536

532537
s16 d0 = -rs / 2;

Diff for: ‎src/mapgen/cavegen.h

+2
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ class CavesRandomWalk
133133
bool large_cave;
134134
bool large_cave_is_flat;
135135
bool flooded;
136+
bool use_biome_liquid;
136137

137138
v3s16 node_min;
138139
v3s16 node_max;
@@ -150,6 +151,7 @@ class CavesRandomWalk
150151

151152
content_t c_water_source;
152153
content_t c_lava_source;
154+
content_t c_biome_liquid;
153155

154156
// ndef is a mandatory parameter.
155157
// If gennotify is NULL, generation events are not logged.

Diff for: ‎src/mapgen/mg_biome.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ BiomeManager::BiomeManager(Server *server) :
6363
b->m_nodenames.emplace_back("mapgen_stone");
6464
b->m_nodenames.emplace_back("ignore");
6565
b->m_nodenames.emplace_back("ignore");
66+
b->m_nnlistsizes.push_back(1);
6667
b->m_nodenames.emplace_back("ignore");
6768
b->m_nodenames.emplace_back("ignore");
6869
b->m_nodenames.emplace_back("ignore");
@@ -330,7 +331,7 @@ void Biome::resolveNodeNames()
330331
getIdFromNrBacklog(&c_river_water, "mapgen_river_water_source", CONTENT_AIR, false);
331332
getIdFromNrBacklog(&c_riverbed, "mapgen_stone", CONTENT_AIR, false);
332333
getIdFromNrBacklog(&c_dust, "ignore", CONTENT_IGNORE, false);
333-
getIdFromNrBacklog(&c_cave_liquid, "ignore", CONTENT_IGNORE, false);
334+
getIdsFromNrBacklog(&c_cave_liquid);
334335
getIdFromNrBacklog(&c_dungeon, "ignore", CONTENT_IGNORE, false);
335336
getIdFromNrBacklog(&c_dungeon_alt, "ignore", CONTENT_IGNORE, false);
336337
getIdFromNrBacklog(&c_dungeon_stair, "ignore", CONTENT_IGNORE, false);

Diff for: ‎src/mapgen/mg_biome.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ class Biome : public ObjDef, public NodeResolver {
5252
content_t c_river_water;
5353
content_t c_riverbed;
5454
content_t c_dust;
55-
content_t c_cave_liquid;
55+
std::vector<content_t> c_cave_liquid;
5656
content_t c_dungeon;
5757
content_t c_dungeon_alt;
5858
content_t c_dungeon_stair;

Diff for: ‎src/script/lua_api/l_mapgen.cpp

+10-1
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,16 @@ Biome *read_biome_def(lua_State *L, int index, const NodeDefManager *ndef)
405405
nn.push_back(getstringfield_default(L, index, "node_river_water", ""));
406406
nn.push_back(getstringfield_default(L, index, "node_riverbed", ""));
407407
nn.push_back(getstringfield_default(L, index, "node_dust", ""));
408-
nn.push_back(getstringfield_default(L, index, "node_cave_liquid", ""));
408+
409+
size_t nnames = getstringlistfield(L, index, "node_cave_liquid", &nn);
410+
// If no cave liquids defined, set list to "ignore" to trigger old hardcoded
411+
// cave liquid behaviour.
412+
if (nnames == 0) {
413+
nn.push_back("ignore");
414+
nnames = 1;
415+
}
416+
b->m_nnlistsizes.push_back(nnames);
417+
409418
nn.push_back(getstringfield_default(L, index, "node_dungeon", ""));
410419
nn.push_back(getstringfield_default(L, index, "node_dungeon_alt", ""));
411420
nn.push_back(getstringfield_default(L, index, "node_dungeon_stair", ""));

0 commit comments

Comments
 (0)
Please sign in to comment.