/*
Minetest
-Copyright (C) 2010-2018 celeron55, Perttu Ahola <celeron55@gmail.com>
-Copyright (C) 2010-2018 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
-Copyright (C) 2015-2018 paramat
+Copyright (C) 2010-2020 celeron55, Perttu Ahola <celeron55@gmail.com>
+Copyright (C) 2015-2020 paramat
+Copyright (C) 2010-2016 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
#include "mg_biome.h"
#include "cavegen.h"
+// TODO Remove this. Cave liquids are now defined and located using biome definitions
static NoiseParams nparams_caveliquids(0, 1, v3f(150.0, 150.0, 150.0), 776, 3, 0.6, 2.0);
void CavesNoiseIntersection::generateCaves(MMVManip *vm,
- v3s16 nmin, v3s16 nmax, u8 *biomemap)
+ v3s16 nmin, v3s16 nmax, biome_t *biomemap)
{
assert(vm);
assert(biomemap);
int water_level,
content_t water_source,
content_t lava_source,
- int lava_depth,
+ float large_cave_flooded,
BiomeGen *biomegen)
{
assert(ndef);
- this->ndef = ndef;
- this->gennotify = gennotify;
- this->seed = seed;
- this->water_level = water_level;
- this->np_caveliquids = &nparams_caveliquids;
- this->lava_depth = lava_depth;
- this->bmgn = biomegen;
+ this->ndef = ndef;
+ this->gennotify = gennotify;
+ this->seed = seed;
+ this->water_level = water_level;
+ this->np_caveliquids = &nparams_caveliquids;
+ this->large_cave_flooded = large_cave_flooded;
+ this->bmgn = biomegen;
c_water_source = water_source;
if (c_water_source == CONTENT_IGNORE)
this->ystride = nmax.X - nmin.X + 1;
+ flooded = ps->range(1, 1000) <= large_cave_flooded * 1000.0f;
+
+ // 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
int dswitchint = ps->range(1, 14);
- flooded = ps->range(1, 2) == 2;
if (large_cave) {
part_max_length_rs = ps->range(2, 4);
// Area starting point in nodes
of = node_min;
- // Allow a bit more
- //(this should be more than the maximum radius of the tunnel)
- const s16 insure = 10;
+ // Allow caves to extend up to 16 nodes beyond the mapchunk edge, to allow
+ // connecting with caves of neighbor mapchunks.
+ // 'insure' is needed to avoid many 'out of voxelmanip' cave nodes.
+ const s16 insure = 2;
s16 more = MYMAX(MAP_BLOCKSIZE - max_tunnel_diameter / 2 - insure, 1);
- ar += v3s16(1, 0, 1) * more * 2;
- of -= v3s16(1, 0, 1) * more;
+ ar += v3s16(1, 1, 1) * more * 2;
+ of -= v3s16(1, 1, 1) * more;
route_y_min = 0;
// Allow half a diameter + 7 over stone surface
fp.Z += 0.1f * ps->range(-10, 10);
v3s16 cp(fp.X, fp.Y, fp.Z);
- // Get biome at 'cp + of', the absolute centre point of this route
- v3s16 cpabs = cp + of;
+ // Choose cave liquid
MapNode liquidnode = CONTENT_IGNORE;
- if (bmgn) {
- Biome *biome = (Biome *)bmgn->calcBiomeAtPoint(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;
+ if (flooded) {
+ if (use_biome_liquid) {
+ liquidnode = c_biome_liquid;
+ } else {
+ // If cave liquid not defined by biome, fallback to old hardcoded behaviour.
+ // TODO 'np_caveliquids' is deprecated and should eventually be removed.
+ // Cave liquids are now defined and located using biome definitions.
+ float nval = NoisePerlin3D(np_caveliquids, startp.X,
+ startp.Y, startp.Z, seed);
+ liquidnode = (nval < 0.40f && node_max.Y < water_level - 256) ?
+ lavanode : waternode;
+ }
}
s16 d0 = -rs / 2;
else
vm->m_data[i] = airnode;
} else {
- if (c == CONTENT_IGNORE)
- continue;
-
vm->m_data[i] = airnode;
vm->m_flags[i] |= VMANIP_FLAG_CAVE;
}
vm->m_data[i] = airnode;
}
} else {
- if (c == CONTENT_IGNORE || c == CONTENT_AIR)
+ if (c == CONTENT_AIR)
continue;
vm->m_data[i] = airnode;