forked from Mirrorlandia_minetest/minetest
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'
This commit is contained in:
parent
6cb6aea969
commit
b1b40fef16
@ -6510,10 +6510,14 @@ Used by `minetest.register_biome`.
|
|||||||
depth_riverbed = 2,
|
depth_riverbed = 2,
|
||||||
-- Node placed under river water and thickness of this layer
|
-- Node placed under river water and thickness of this layer
|
||||||
|
|
||||||
node_cave_liquid = "default:water_source",
|
node_cave_liquid = "default:lava_source",
|
||||||
-- Nodes placed as a blob of liquid in 50% of large caves.
|
node_cave_liquid = {"default:water_source", "default:lava_source"},
|
||||||
-- If absent, cave liquids fall back to classic behaviour of lava or
|
-- Nodes placed inside 50% of the medium size caves.
|
||||||
-- water distributed according to a hardcoded 3D noise.
|
-- Multiple nodes can be specified, each cave will use a randomly
|
||||||
|
-- chosen node from the list.
|
||||||
|
-- If this field is left out or 'nil', cave liquids fall back to
|
||||||
|
-- classic behaviour of lava and water distributed using 3D noise.
|
||||||
|
-- For no cave liquid, specify "air".
|
||||||
|
|
||||||
node_dungeon = "default:cobble",
|
node_dungeon = "default:cobble",
|
||||||
-- Node used for primary dungeon structure.
|
-- Node used for primary dungeon structure.
|
||||||
|
@ -321,9 +321,26 @@ void CavesRandomWalk::makeCave(MMVManip *vm, v3s16 nmin, v3s16 nmax,
|
|||||||
|
|
||||||
this->ystride = nmax.X - nmin.X + 1;
|
this->ystride = nmax.X - nmin.X + 1;
|
||||||
|
|
||||||
|
flooded = ps->range(1, 2) == 2;
|
||||||
|
|
||||||
|
// If flooded:
|
||||||
|
// Get biome at mapchunk midpoint. If cave liquid defined for biome, use it.
|
||||||
|
// If defined liquid is "air", disable 'flooded' to avoid placing "air".
|
||||||
|
use_biome_liquid = false;
|
||||||
|
if (flooded && bmgn) {
|
||||||
|
v3s16 midp = node_min + (node_max - node_min) / v3s16(2, 2, 2);
|
||||||
|
Biome *biome = (Biome *)bmgn->getBiomeAtPoint(midp);
|
||||||
|
if (biome->c_cave_liquid[0] != CONTENT_IGNORE) {
|
||||||
|
use_biome_liquid = true;
|
||||||
|
c_biome_liquid =
|
||||||
|
biome->c_cave_liquid[ps->range(0, biome->c_cave_liquid.size() - 1)];
|
||||||
|
if (c_biome_liquid == CONTENT_AIR)
|
||||||
|
flooded = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Set initial parameters from randomness
|
// Set initial parameters from randomness
|
||||||
int dswitchint = ps->range(1, 14);
|
int dswitchint = ps->range(1, 14);
|
||||||
flooded = ps->range(1, 2) == 2;
|
|
||||||
|
|
||||||
if (large_cave) {
|
if (large_cave) {
|
||||||
part_max_length_rs = ps->range(2, 4);
|
part_max_length_rs = ps->range(2, 4);
|
||||||
@ -502,31 +519,19 @@ void CavesRandomWalk::carveRoute(v3f vec, float f, bool randomize_xz)
|
|||||||
fp.Z += 0.1f * ps->range(-10, 10);
|
fp.Z += 0.1f * ps->range(-10, 10);
|
||||||
v3s16 cp(fp.X, fp.Y, fp.Z);
|
v3s16 cp(fp.X, fp.Y, fp.Z);
|
||||||
|
|
||||||
// Get biome at 'cp + of', the absolute centre point of this route
|
// Choose cave liquid
|
||||||
v3s16 cpabs = cp + of;
|
|
||||||
MapNode liquidnode = CONTENT_IGNORE;
|
MapNode liquidnode = CONTENT_IGNORE;
|
||||||
|
|
||||||
if (bmgn) {
|
if (flooded) {
|
||||||
Biome *biome = nullptr;
|
if (use_biome_liquid) {
|
||||||
if (cpabs.X < node_min.X || cpabs.X > node_max.X ||
|
liquidnode = c_biome_liquid;
|
||||||
cpabs.Z < node_min.Z || cpabs.Z > node_max.Z)
|
} else {
|
||||||
// Point is outside heat and humidity noise maps so use point noise
|
// If cave liquid not defined by biome, fallback to old hardcoded behaviour
|
||||||
// calculations.
|
float nval = NoisePerlin3D(np_caveliquids, startp.X,
|
||||||
biome = (Biome *)bmgn->calcBiomeAtPoint(cpabs);
|
startp.Y, startp.Z, seed);
|
||||||
else
|
liquidnode = (nval < 0.40f && node_max.Y < lava_depth) ?
|
||||||
// Point is inside heat and humidity noise maps so use them
|
lavanode : waternode;
|
||||||
biome = (Biome *)bmgn->getBiomeAtPoint(cpabs);
|
}
|
||||||
|
|
||||||
if (biome->c_cave_liquid != CONTENT_IGNORE)
|
|
||||||
liquidnode = biome->c_cave_liquid;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (liquidnode == CONTENT_IGNORE) {
|
|
||||||
// Fallback to classic behaviour using point 'startp'
|
|
||||||
float nval = NoisePerlin3D(np_caveliquids, startp.X,
|
|
||||||
startp.Y, startp.Z, seed);
|
|
||||||
liquidnode = (nval < 0.40f && node_max.Y < lava_depth) ?
|
|
||||||
lavanode : waternode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s16 d0 = -rs / 2;
|
s16 d0 = -rs / 2;
|
||||||
|
@ -133,6 +133,7 @@ public:
|
|||||||
bool large_cave;
|
bool large_cave;
|
||||||
bool large_cave_is_flat;
|
bool large_cave_is_flat;
|
||||||
bool flooded;
|
bool flooded;
|
||||||
|
bool use_biome_liquid;
|
||||||
|
|
||||||
v3s16 node_min;
|
v3s16 node_min;
|
||||||
v3s16 node_max;
|
v3s16 node_max;
|
||||||
@ -150,6 +151,7 @@ public:
|
|||||||
|
|
||||||
content_t c_water_source;
|
content_t c_water_source;
|
||||||
content_t c_lava_source;
|
content_t c_lava_source;
|
||||||
|
content_t c_biome_liquid;
|
||||||
|
|
||||||
// ndef is a mandatory parameter.
|
// ndef is a mandatory parameter.
|
||||||
// If gennotify is NULL, generation events are not logged.
|
// If gennotify is NULL, generation events are not logged.
|
||||||
|
@ -63,6 +63,7 @@ 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_nnlistsizes.push_back(1);
|
||||||
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");
|
||||||
@ -330,7 +331,7 @@ void Biome::resolveNodeNames()
|
|||||||
getIdFromNrBacklog(&c_river_water, "mapgen_river_water_source", CONTENT_AIR, false);
|
getIdFromNrBacklog(&c_river_water, "mapgen_river_water_source", CONTENT_AIR, false);
|
||||||
getIdFromNrBacklog(&c_riverbed, "mapgen_stone", CONTENT_AIR, false);
|
getIdFromNrBacklog(&c_riverbed, "mapgen_stone", CONTENT_AIR, false);
|
||||||
getIdFromNrBacklog(&c_dust, "ignore", CONTENT_IGNORE, false);
|
getIdFromNrBacklog(&c_dust, "ignore", CONTENT_IGNORE, false);
|
||||||
getIdFromNrBacklog(&c_cave_liquid, "ignore", CONTENT_IGNORE, false);
|
getIdsFromNrBacklog(&c_cave_liquid);
|
||||||
getIdFromNrBacklog(&c_dungeon, "ignore", CONTENT_IGNORE, false);
|
getIdFromNrBacklog(&c_dungeon, "ignore", CONTENT_IGNORE, false);
|
||||||
getIdFromNrBacklog(&c_dungeon_alt, "ignore", CONTENT_IGNORE, false);
|
getIdFromNrBacklog(&c_dungeon_alt, "ignore", CONTENT_IGNORE, false);
|
||||||
getIdFromNrBacklog(&c_dungeon_stair, "ignore", CONTENT_IGNORE, false);
|
getIdFromNrBacklog(&c_dungeon_stair, "ignore", CONTENT_IGNORE, false);
|
||||||
|
@ -52,7 +52,7 @@ public:
|
|||||||
content_t c_river_water;
|
content_t c_river_water;
|
||||||
content_t c_riverbed;
|
content_t c_riverbed;
|
||||||
content_t c_dust;
|
content_t c_dust;
|
||||||
content_t c_cave_liquid;
|
std::vector<content_t> c_cave_liquid;
|
||||||
content_t c_dungeon;
|
content_t c_dungeon;
|
||||||
content_t c_dungeon_alt;
|
content_t c_dungeon_alt;
|
||||||
content_t c_dungeon_stair;
|
content_t c_dungeon_stair;
|
||||||
|
@ -405,7 +405,16 @@ Biome *read_biome_def(lua_State *L, int index, const NodeDefManager *ndef)
|
|||||||
nn.push_back(getstringfield_default(L, index, "node_river_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_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", ""));
|
|
||||||
|
size_t nnames = getstringlistfield(L, index, "node_cave_liquid", &nn);
|
||||||
|
// If no cave liquids defined, set list to "ignore" to trigger old hardcoded
|
||||||
|
// cave liquid behaviour.
|
||||||
|
if (nnames == 0) {
|
||||||
|
nn.push_back("ignore");
|
||||||
|
nnames = 1;
|
||||||
|
}
|
||||||
|
b->m_nnlistsizes.push_back(nnames);
|
||||||
|
|
||||||
nn.push_back(getstringfield_default(L, index, "node_dungeon", ""));
|
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_alt", ""));
|
||||||
nn.push_back(getstringfield_default(L, index, "node_dungeon_stair", ""));
|
nn.push_back(getstringfield_default(L, index, "node_dungeon_stair", ""));
|
||||||
|
Loading…
Reference in New Issue
Block a user