diff options
Diffstat (limited to 'src/mapgen')
-rw-r--r-- | src/mapgen/cavegen.cpp | 56 | ||||
-rw-r--r-- | src/mapgen/cavegen.h | 4 | ||||
-rw-r--r-- | src/mapgen/dungeongen.cpp | 89 | ||||
-rw-r--r-- | src/mapgen/dungeongen.h | 43 | ||||
-rw-r--r-- | src/mapgen/mapgen.cpp | 232 | ||||
-rw-r--r-- | src/mapgen/mapgen.h | 31 | ||||
-rw-r--r-- | src/mapgen/mapgen_carpathian.cpp | 228 | ||||
-rw-r--r-- | src/mapgen/mapgen_carpathian.h | 28 | ||||
-rw-r--r-- | src/mapgen/mapgen_flat.cpp | 51 | ||||
-rw-r--r-- | src/mapgen/mapgen_flat.h | 3 | ||||
-rw-r--r-- | src/mapgen/mapgen_fractal.cpp | 115 | ||||
-rw-r--r-- | src/mapgen/mapgen_fractal.h | 16 | ||||
-rw-r--r-- | src/mapgen/mapgen_singlenode.cpp | 5 | ||||
-rw-r--r-- | src/mapgen/mapgen_singlenode.h | 2 | ||||
-rw-r--r-- | src/mapgen/mapgen_v5.cpp | 28 | ||||
-rw-r--r-- | src/mapgen/mapgen_v5.h | 3 | ||||
-rw-r--r-- | src/mapgen/mapgen_v6.cpp | 278 | ||||
-rw-r--r-- | src/mapgen/mapgen_v6.h | 4 | ||||
-rw-r--r-- | src/mapgen/mapgen_v7.cpp | 16 | ||||
-rw-r--r-- | src/mapgen/mapgen_v7.h | 3 | ||||
-rw-r--r-- | src/mapgen/mapgen_valleys.cpp | 385 | ||||
-rw-r--r-- | src/mapgen/mapgen_valleys.h | 30 | ||||
-rw-r--r-- | src/mapgen/mg_biome.cpp | 3 | ||||
-rw-r--r-- | src/mapgen/mg_biome.h | 2 | ||||
-rw-r--r-- | src/mapgen/mg_schematic.cpp | 2 | ||||
-rw-r--r-- | src/mapgen/treegen.cpp | 2 |
26 files changed, 822 insertions, 837 deletions
diff --git a/src/mapgen/cavegen.cpp b/src/mapgen/cavegen.cpp index e54d76e08..fa34b7273 100644 --- a/src/mapgen/cavegen.cpp +++ b/src/mapgen/cavegen.cpp @@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #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); @@ -321,9 +322,26 @@ void CavesRandomWalk::makeCave(MMVManip *vm, v3s16 nmin, v3s16 nmax, 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 int dswitchint = ps->range(1, 14); - flooded = ps->range(1, 2) == 2; if (large_cave) { part_max_length_rs = ps->range(2, 4); @@ -502,31 +520,21 @@ void CavesRandomWalk::carveRoute(v3f vec, float f, bool randomize_xz) 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 = nullptr; - if (cpabs.X < node_min.X || cpabs.X > node_max.X || - cpabs.Z < node_min.Z || cpabs.Z > node_max.Z) - // Point is outside heat and humidity noise maps so use point noise - // calculations. - biome = (Biome *)bmgn->calcBiomeAtPoint(cpabs); - else - // Point is inside heat and humidity noise maps so use them - 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; + if (flooded) { + if (use_biome_liquid) { + liquidnode = c_biome_liquid; + } else { + // TODO remove this. Cave liquids are now defined and located using biome + // definitions. + // If cave liquid not defined by biome, fallback to old hardcoded behaviour. + 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; diff --git a/src/mapgen/cavegen.h b/src/mapgen/cavegen.h index 7b7be6219..3f1730ddb 100644 --- a/src/mapgen/cavegen.h +++ b/src/mapgen/cavegen.h @@ -119,6 +119,8 @@ public: // configurable parameters s32 seed; int water_level; + // TODO 'lava_depth' and 'np_caveliquids' are deprecated and should be removed. + // Cave liquids are now defined and located using biome definitions. int lava_depth; NoiseParams *np_caveliquids; @@ -133,6 +135,7 @@ public: bool large_cave; bool large_cave_is_flat; bool flooded; + bool use_biome_liquid; v3s16 node_min; v3s16 node_max; @@ -150,6 +153,7 @@ public: content_t c_water_source; content_t c_lava_source; + content_t c_biome_liquid; // ndef is a mandatory parameter. // If gennotify is NULL, generation events are not logged. diff --git a/src/mapgen/dungeongen.cpp b/src/mapgen/dungeongen.cpp index 77ac05770..acdb1a0f0 100644 --- a/src/mapgen/dungeongen.cpp +++ b/src/mapgen/dungeongen.cpp @@ -31,9 +31,6 @@ with this program; if not, write to the Free Software Foundation, Inc., //#define DGEN_USE_TORCHES -NoiseParams nparams_dungeon_density(0.9, 0.5, v3f(500.0, 500.0, 500.0), 0, 2, 0.8, 2.0); -NoiseParams nparams_dungeon_alt_wall(-0.4, 1.0, v3f(40.0, 40.0, 40.0), 32474, 6, 1.1, 2.0); - /////////////////////////////////////////////////////////////////////////////// @@ -69,28 +66,26 @@ DungeonGen::DungeonGen(const NodeDefManager *ndef, 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.rooms_min = 2; - dp.rooms_max = 16; + dp.large_room_chance = 1; + dp.num_rooms = 8; + dp.num_dungeons = 1; dp.notifytype = GENNOTIFY_DUNGEON; - dp.np_density = nparams_dungeon_density; - dp.np_alt_wall = nparams_dungeon_alt_wall; + dp.np_alt_wall = + NoiseParams(-0.4, 1.0, v3f(40.0, 40.0, 40.0), 32474, 6, 1.1, 2.0); } } void DungeonGen::generate(MMVManip *vm, u32 bseed, v3s16 nmin, v3s16 nmax) { + if (dp.num_dungeons == 0) + return; + assert(vm); //TimeTaker t("gen dungeons"); - float nval_density = NoisePerlin3D(&dp.np_density, nmin.X, nmin.Y, nmin.Z, dp.seed); - if (nval_density < 1.0f) - return; - - static const bool preserve_ignore = !g_settings->getBool("projecting_dungeons"); - this->vm = vm; this->blockseed = bseed; random.seed(bseed + 2); @@ -99,9 +94,13 @@ void DungeonGen::generate(MMVManip *vm, u32 bseed, v3s16 nmin, v3s16 nmax) vm->clearFlag(VMANIP_FLAG_DUNGEON_INSIDE | VMANIP_FLAG_DUNGEON_PRESERVE); if (dp.only_in_ground) { - // Set all air and liquid drawtypes to be untouchable to make dungeons - // open to air and liquids. Optionally set ignore to be untouchable to - // prevent projecting dungeons. + // Set all air and liquid drawtypes to be untouchable to make dungeons generate + // in ground only. + // Set 'ignore' to be untouchable to prevent generation in ungenerated neighbor + // mapchunks, to avoid dungeon rooms generating outside ground. + // Like randomwalk caves, preserve nodes that have 'is_ground_content = false', + // to avoid dungeons that generate out beyond the edge of a mapchunk destroying + // nodes added by mods in 'register_on_generated()'. for (s16 z = nmin.Z; z <= nmax.Z; z++) { for (s16 y = nmin.Y; y <= nmax.Y; y++) { u32 i = vm->m_area.index(nmin.X, y, z); @@ -109,7 +108,7 @@ void DungeonGen::generate(MMVManip *vm, u32 bseed, v3s16 nmin, v3s16 nmax) content_t c = vm->m_data[i].getContent(); NodeDrawType dtype = ndef->get(c).drawtype; if (dtype == NDT_AIRLIKE || dtype == NDT_LIQUID || - (preserve_ignore && c == CONTENT_IGNORE)) + c == CONTENT_IGNORE || !ndef->get(c).is_ground_content) vm->m_flags[i] |= VMANIP_FLAG_DUNGEON_PRESERVE; i++; } @@ -118,7 +117,7 @@ void DungeonGen::generate(MMVManip *vm, u32 bseed, v3s16 nmin, v3s16 nmax) } // Add them - for (u32 i = 0; i < std::floor(nval_density); i++) + for (u32 i = 0; i < dp.num_dungeons; i++) makeDungeon(v3s16(1, 1, 1) * MAP_BLOCKSIZE); // Optionally convert some structure to alternative structure @@ -149,19 +148,13 @@ void DungeonGen::makeDungeon(v3s16 start_padding) /* Find place for first room. - There is a 1 in 4 chance of the first room being 'large', - all other rooms are not 'large'. */ bool fits = false; for (u32 i = 0; i < 100 && !fits; i++) { - bool is_large_room = ((random.next() & 3) == 1); - if (is_large_room) { - roomsize.Z = random.range( - dp.room_size_large_min.Z, dp.room_size_large_max.Z); - roomsize.Y = random.range( - dp.room_size_large_min.Y, dp.room_size_large_max.Y); - roomsize.X = random.range( - dp.room_size_large_min.X, dp.room_size_large_max.X); + if (dp.large_room_chance >= 1) { + roomsize.Z = random.range(dp.room_size_large_min.Z, dp.room_size_large_max.Z); + roomsize.Y = random.range(dp.room_size_large_min.Y, dp.room_size_large_max.Y); + roomsize.X = random.range(dp.room_size_large_min.X, dp.room_size_large_max.X); } else { roomsize.Z = random.range(dp.room_size_min.Z, dp.room_size_max.Z); roomsize.Y = random.range(dp.room_size_min.Y, dp.room_size_max.Y); @@ -203,8 +196,7 @@ void DungeonGen::makeDungeon(v3s16 start_padding) */ v3s16 last_room_center = roomplace + v3s16(roomsize.X / 2, 1, roomsize.Z / 2); - u32 room_count = random.range(dp.rooms_min, dp.rooms_max); - for (u32 i = 0; i < room_count; i++) { + for (u32 i = 0; i < dp.num_rooms; i++) { // Make a room to the determined place makeRoom(roomsize, roomplace); @@ -218,7 +210,7 @@ void DungeonGen::makeDungeon(v3s16 start_padding) #endif // Quit if last room - if (i == room_count - 1) + if (i + 1 == dp.num_rooms) break; // Determine walker start position @@ -256,9 +248,16 @@ void DungeonGen::makeDungeon(v3s16 start_padding) makeCorridor(doorplace, doordir, corridor_end, corridor_end_dir); // Find a place for a random sized room - roomsize.Z = random.range(dp.room_size_min.Z, dp.room_size_max.Z); - roomsize.Y = random.range(dp.room_size_min.Y, dp.room_size_max.Y); - roomsize.X = random.range(dp.room_size_min.X, dp.room_size_max.X); + if (dp.large_room_chance > 1 && random.range(1, dp.large_room_chance) == 1) { + // Large room + roomsize.Z = random.range(dp.room_size_large_min.Z, dp.room_size_large_max.Z); + roomsize.Y = random.range(dp.room_size_large_min.Y, dp.room_size_large_max.Y); + roomsize.X = random.range(dp.room_size_large_min.X, dp.room_size_large_max.X); + } else { + roomsize.Z = random.range(dp.room_size_min.Z, dp.room_size_max.Z); + roomsize.Y = random.range(dp.room_size_min.Y, dp.room_size_max.Y); + roomsize.X = random.range(dp.room_size_min.X, dp.room_size_max.X); + } m_pos = corridor_end; m_dir = corridor_end_dir; @@ -271,7 +270,6 @@ void DungeonGen::makeDungeon(v3s16 start_padding) else // Don't actually make a door roomplace -= doordir; - } } @@ -490,7 +488,7 @@ void DungeonGen::makeCorridor(v3s16 doorplace, v3s16 doordir, if (partcount >= partlength) { partcount = 0; - dir = random_turn(random, dir); + random_turn(random, dir); partlength = random.range(1, length); @@ -651,20 +649,19 @@ v3s16 turn_xz(v3s16 olddir, int t) } -v3s16 random_turn(PseudoRandom &random, v3s16 olddir) +void random_turn(PseudoRandom &random, v3s16 &dir) { int turn = random.range(0, 2); - v3s16 dir; - if (turn == 0) - // Go straight - dir = olddir; - else if (turn == 1) + if (turn == 0) { + // Go straight: nothing to do + return; + } else if (turn == 1) { // Turn right - dir = turn_xz(olddir, 0); - else + dir = turn_xz(dir, 0); + } else { // Turn left - dir = turn_xz(olddir, 1); - return dir; + dir = turn_xz(dir, 1); + } } diff --git a/src/mapgen/dungeongen.h b/src/mapgen/dungeongen.h index 2748524c5..35e6beef5 100644 --- a/src/mapgen/dungeongen.h +++ b/src/mapgen/dungeongen.h @@ -34,7 +34,7 @@ class NodeDefManager; v3s16 rand_ortho_dir(PseudoRandom &random, bool diagonal_dirs); v3s16 turn_xz(v3s16 olddir, int t); -v3s16 random_turn(PseudoRandom &random, v3s16 olddir); +void random_turn(PseudoRandom &random, v3s16 &dir); int dir_to_facedir(v3s16 d); @@ -42,24 +42,44 @@ struct DungeonParams { s32 seed; content_t c_wall; + // Randomly scattered alternative wall nodes content_t c_alt_wall; content_t c_stair; - bool diagonal_dirs; + // 3D noise that determines which c_wall nodes are converted to c_alt_wall + NoiseParams np_alt_wall; + + // Number of dungeons generated in mapchunk. All will use the same set of + // dungeonparams. + u16 num_dungeons; + // Dungeons only generate in ground bool only_in_ground; - v3s16 holesize; - u16 corridor_len_min; - u16 corridor_len_max; + // Number of rooms + u16 num_rooms; + // Room size random range. Includes walls / floor / ceilng v3s16 room_size_min; v3s16 room_size_max; + // Large room size random range. Includes walls / floor / ceilng v3s16 room_size_large_min; v3s16 room_size_large_max; - u16 rooms_min; - u16 rooms_max; + // Value 0 disables large rooms. + // Value 1 results in 1 large room, the first generated room. + // Value > 1 makes the first generated room large, all other rooms have a + // '1 in value' chance of being large. + u16 large_room_chance; + // Dimensions of 3D 'brush' that creates corridors. + // Dimensions are of the empty space, not including walls / floor / ceilng. + // Diagonal corridors must have hole width >=2 to be passable. + // Currently, hole width >= 3 causes stair corridor bugs. + v3s16 holesize; + // Corridor length random range + u16 corridor_len_min; + u16 corridor_len_max; + // Diagonal corridors are possible, 1 in 4 corridors will be diagonal + bool diagonal_dirs; + // Usually 'GENNOTIFY_DUNGEON', but mapgen v6 uses 'GENNOTIFY_TEMPLE' for + // desert dungeons. GenNotifyType notifytype; - - NoiseParams np_density; - NoiseParams np_alt_wall; }; class DungeonGen { @@ -82,8 +102,7 @@ public: DungeonGen(const NodeDefManager *ndef, GenerateNotifier *gennotify, DungeonParams *dparams); - void generate(MMVManip *vm, u32 bseed, - v3s16 full_node_min, v3s16 full_node_max); + void generate(MMVManip *vm, u32 bseed, v3s16 full_node_min, v3s16 full_node_max); void makeDungeon(v3s16 start_padding); void makeRoom(v3s16 roomsize, v3s16 roomplace); diff --git a/src/mapgen/mapgen.cpp b/src/mapgen/mapgen.cpp index 7de367a27..6d5e721ce 100644 --- a/src/mapgen/mapgen.cpp +++ b/src/mapgen/mapgen.cpp @@ -19,6 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include <cmath> #include "mapgen.h" #include "voxel.h" #include "noise.h" @@ -38,6 +39,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "serialization.h" #include "util/serialize.h" #include "util/numeric.h" +#include "util/directiontables.h" #include "filesys.h" #include "log.h" #include "mapgen_carpathian.h" @@ -80,15 +82,21 @@ struct MapgenDesc { //// Built-in mapgens //// +// Order used here defines the order of appearence in mainmenu. +// v6 always last to discourage selection. +// Special mapgens flat, fractal, singlenode, next to last. Of these, singlenode +// last to discourage selection. +// Of the remaining, v5 last due to age, v7 first due to being the default. +// The order of 'enum MapgenType' in mapgen.h must match this order. static MapgenDesc g_reg_mapgens[] = { - {"v5", true}, - {"v6", true}, {"v7", true}, + {"valleys", true}, + {"carpathian", true}, + {"v5", true}, {"flat", true}, {"fractal", true}, - {"valleys", true}, {"singlenode", true}, - {"carpathian", true}, + {"v6", true}, }; STATIC_ASSERT( @@ -148,28 +156,28 @@ const char *Mapgen::getMapgenName(MapgenType mgtype) } -Mapgen *Mapgen::createMapgen(MapgenType mgtype, int mgid, - MapgenParams *params, EmergeManager *emerge) +Mapgen *Mapgen::createMapgen(MapgenType mgtype, MapgenParams *params, + EmergeManager *emerge) { switch (mgtype) { case MAPGEN_CARPATHIAN: - return new MapgenCarpathian(mgid, (MapgenCarpathianParams *)params, emerge); + return new MapgenCarpathian((MapgenCarpathianParams *)params, emerge); case MAPGEN_FLAT: - return new MapgenFlat(mgid, (MapgenFlatParams *)params, emerge); + return new MapgenFlat((MapgenFlatParams *)params, emerge); case MAPGEN_FRACTAL: - return new MapgenFractal(mgid, (MapgenFractalParams *)params, emerge); + return new MapgenFractal((MapgenFractalParams *)params, emerge); case MAPGEN_SINGLENODE: - return new MapgenSinglenode(mgid, (MapgenSinglenodeParams *)params, emerge); + return new MapgenSinglenode((MapgenSinglenodeParams *)params, emerge); case MAPGEN_V5: - return new MapgenV5(mgid, (MapgenV5Params *)params, emerge); + return new MapgenV5((MapgenV5Params *)params, emerge); case MAPGEN_V6: - return new MapgenV6(mgid, (MapgenV6Params *)params, emerge); + return new MapgenV6((MapgenV6Params *)params, emerge); case MAPGEN_V7: - return new MapgenV7(mgid, (MapgenV7Params *)params, emerge); + return new MapgenV7((MapgenV7Params *)params, emerge); case MAPGEN_VALLEYS: - return new MapgenValleys(mgid, (MapgenValleysParams *)params, emerge); + return new MapgenValleys((MapgenValleysParams *)params, emerge); default: - return NULL; + return nullptr; } } @@ -194,7 +202,7 @@ MapgenParams *Mapgen::createMapgenParams(MapgenType mgtype) case MAPGEN_VALLEYS: return new MapgenValleysParams; default: - return NULL; + return nullptr; } } @@ -415,7 +423,7 @@ void Mapgen::updateLiquid(UniqueQueue<v3s16> *trans_liquid, v3s16 nmin, v3s16 nm void Mapgen::setLighting(u8 light, v3s16 nmin, v3s16 nmax) { - ScopeProfiler sp(g_profiler, "EmergeThread: mapgen lighting update", SPT_AVG); + ScopeProfiler sp(g_profiler, "EmergeThread: update lighting", SPT_AVG); VoxelArea a(nmin, nmax); for (int z = a.MinEdge.Z; z <= a.MaxEdge.Z; z++) { @@ -428,7 +436,8 @@ void Mapgen::setLighting(u8 light, v3s16 nmin, v3s16 nmax) } -void Mapgen::lightSpread(VoxelArea &a, v3s16 p, u8 light) +void Mapgen::lightSpread(VoxelArea &a, std::queue<std::pair<v3s16, u8>> &queue, + const v3s16 &p, u8 light) { if (light <= 1 || !a.contains(p)) return; @@ -448,8 +457,8 @@ void Mapgen::lightSpread(VoxelArea &a, v3s16 p, u8 light) // Bail out only if we have no more light from either bank to propogate, or // we hit a solid block that light cannot pass through. if ((light_day <= (n.param1 & 0x0F) && - light_night <= (n.param1 & 0xF0)) || - !ndef->get(n).light_propagates) + light_night <= (n.param1 & 0xF0)) || + !ndef->get(n).light_propagates) return; // Since this recursive function only terminates when there is no light from @@ -460,19 +469,15 @@ void Mapgen::lightSpread(VoxelArea &a, v3s16 p, u8 light) n.param1 = light; - lightSpread(a, p + v3s16(0, 0, 1), light); - lightSpread(a, p + v3s16(0, 1, 0), light); - lightSpread(a, p + v3s16(1, 0, 0), light); - lightSpread(a, p - v3s16(0, 0, 1), light); - lightSpread(a, p - v3s16(0, 1, 0), light); - lightSpread(a, p - v3s16(1, 0, 0), light); + // add to queue + queue.emplace(p, light); } void Mapgen::calcLighting(v3s16 nmin, v3s16 nmax, v3s16 full_nmin, v3s16 full_nmax, bool propagate_shadow) { - ScopeProfiler sp(g_profiler, "EmergeThread: mapgen lighting update", SPT_AVG); + ScopeProfiler sp(g_profiler, "EmergeThread: update lighting", SPT_AVG); //TimeTaker t("updateLighting"); propagateSunlight(nmin, nmax, propagate_shadow); @@ -518,9 +523,10 @@ void Mapgen::propagateSunlight(v3s16 nmin, v3s16 nmax, bool propagate_shadow) } -void Mapgen::spreadLight(v3s16 nmin, v3s16 nmax) +void Mapgen::spreadLight(const v3s16 &nmin, const v3s16 &nmax) { //TimeTaker t("spreadLight"); + std::queue<std::pair<v3s16, u8>> queue; VoxelArea a(nmin, nmax); for (int z = a.MinEdge.Z; z <= a.MaxEdge.Z; z++) { @@ -544,18 +550,24 @@ void Mapgen::spreadLight(v3s16 nmin, v3s16 nmax) u8 light = n.param1; if (light) { - lightSpread(a, v3s16(x, y, z + 1), light); - lightSpread(a, v3s16(x, y + 1, z ), light); - lightSpread(a, v3s16(x + 1, y, z ), light); - lightSpread(a, v3s16(x, y, z - 1), light); - lightSpread(a, v3s16(x, y - 1, z ), light); - lightSpread(a, v3s16(x - 1, y, z ), light); + const v3s16 p(x, y, z); + // spread to all 6 neighbor nodes + for (const auto &dir : g_6dirs) + lightSpread(a, queue, p + dir, light); } } } } - //printf("spreadLight: %dms\n", t.stop()); + while (!queue.empty()) { + const auto &i = queue.front(); + // spread to all 6 neighbor nodes + for (const auto &dir : g_6dirs) + lightSpread(a, queue, i.first + dir, i.second); + queue.pop(); + } + + //printf("spreadLight: %lums\n", t.stop()); } @@ -592,45 +604,20 @@ MapgenBasic::MapgenBasic(int mapgenid, MapgenParams *params, EmergeManager *emer this->heightmap = new s16[csize.X * csize.Z]; //// Initialize biome generator - // TODO(hmmmm): should we have a way to disable biomemanager biomes? biomegen = m_bmgr->createBiomeGen(BIOMEGEN_ORIGINAL, params->bparams, csize); biomemap = biomegen->biomemap; //// Look up some commonly used content c_stone = ndef->getId("mapgen_stone"); - c_desert_stone = ndef->getId("mapgen_desert_stone"); - c_sandstone = ndef->getId("mapgen_sandstone"); c_water_source = ndef->getId("mapgen_water_source"); c_river_water_source = ndef->getId("mapgen_river_water_source"); c_lava_source = ndef->getId("mapgen_lava_source"); + c_cobble = ndef->getId("mapgen_cobble"); - // Fall back to more basic content if not defined - // river_water_source cannot fallback to water_source because river water - // needs to be non-renewable and have a short flow range. - if (c_desert_stone == CONTENT_IGNORE) - c_desert_stone = c_stone; - if (c_sandstone == CONTENT_IGNORE) - c_sandstone = c_stone; - - //// Content used for dungeon generation - c_cobble = ndef->getId("mapgen_cobble"); - c_mossycobble = ndef->getId("mapgen_mossycobble"); - c_stair_cobble = ndef->getId("mapgen_stair_cobble"); - c_stair_desert_stone = ndef->getId("mapgen_stair_desert_stone"); - c_sandstonebrick = ndef->getId("mapgen_sandstonebrick"); - c_stair_sandstone_block = ndef->getId("mapgen_stair_sandstone_block"); - - // Fall back to more basic content if not defined - if (c_mossycobble == CONTENT_IGNORE) - c_mossycobble = c_cobble; - if (c_stair_cobble == CONTENT_IGNORE) - c_stair_cobble = c_cobble; - if (c_stair_desert_stone == CONTENT_IGNORE) - c_stair_desert_stone = c_desert_stone; - if (c_sandstonebrick == CONTENT_IGNORE) - c_sandstonebrick = c_sandstone; - if (c_stair_sandstone_block == CONTENT_IGNORE) - c_stair_sandstone_block = c_sandstonebrick; + // Fall back to more basic content if not defined. + // Lava falls back to water as both are suitable as cave liquids. + if (c_lava_source == CONTENT_IGNORE) + c_lava_source = c_water_source; } @@ -889,94 +876,59 @@ 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->getBiomeAtPoint(chunk_mid); + u16 num_dungeons = std::fmax(std::floor( + NoisePerlin3D(&np_dungeons, node_min.X, node_min.Y, node_min.Z, seed)), 0.0f); + if (num_dungeons == 0) + return; + + PseudoRandom ps(blockseed + 70033); DungeonParams dp; - dp.seed = seed; - dp.only_in_ground = true; - dp.corridor_len_min = 1; - dp.corridor_len_max = 13; - dp.rooms_min = 2; - dp.rooms_max = 16; + dp.np_alt_wall = + NoiseParams(-0.4, 1.0, v3f(40.0, 40.0, 40.0), 32474, 6, 1.1, 2.0); + + dp.seed = seed; + dp.only_in_ground = true; + dp.num_dungeons = num_dungeons; + dp.notifytype = GENNOTIFY_DUNGEON; + dp.num_rooms = ps.range(2, 16); + dp.room_size_min = v3s16(5, 5, 5); + dp.room_size_max = v3s16(12, 6, 12); + dp.room_size_large_min = v3s16(12, 6, 12); + dp.room_size_large_max = v3s16(16, 16, 16); + dp.large_room_chance = (ps.range(1, 4) == 1) ? 8 : 0; + dp.diagonal_dirs = ps.range(1, 8) == 1; + // Diagonal corridors must have 'hole' width >=2 to be passable + u8 holewidth = (dp.diagonal_dirs) ? 2 : ps.range(1, 2); + dp.holesize = v3s16(holewidth, 3, holewidth); + dp.corridor_len_min = 1; + dp.corridor_len_max = 13; - dp.np_density = nparams_dungeon_density; - dp.np_alt_wall = nparams_dungeon_alt_wall; + // Get biome at mapchunk midpoint + v3s16 chunk_mid = node_min + (node_max - node_min) / v3s16(2, 2, 2); + Biome *biome = (Biome *)biomegen->getBiomeAtPoint(chunk_mid); - // Biome-defined dungeon nodes + // Use biome-defined dungeon nodes if defined if (biome->c_dungeon != CONTENT_IGNORE) { - dp.c_wall = biome->c_dungeon; + 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; + 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; - - 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.notifytype = GENNOTIFY_DUNGEON; - - } 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; - - dp.diagonal_dirs = true; - dp.holesize = v3s16(2, 3, 2); - dp.room_size_min = v3s16(6, 9, 6); - dp.room_size_max = v3s16(10, 11, 10); - dp.room_size_large_min = v3s16(10, 13, 10); - dp.room_size_large_max = v3s16(18, 21, 18); - dp.notifytype = GENNOTIFY_TEMPLE; - - } 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; - - 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; - - // Fallback to using biome 'node_stone' + // Fallback to using cobble mapgen alias if defined + } else if (c_cobble != CONTENT_IGNORE) { + dp.c_wall = c_cobble; + dp.c_alt_wall = CONTENT_IGNORE; + dp.c_stair = c_cobble; + // Fallback to using biome-defined 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(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; + dp.c_wall = biome->c_stone; + dp.c_alt_wall = CONTENT_IGNORE; + dp.c_stair = biome->c_stone; } DungeonGen dgen(ndef, &gennotify, &dp); diff --git a/src/mapgen/mapgen.h b/src/mapgen/mapgen.h index b60aea57e..0ac26d538 100644 --- a/src/mapgen/mapgen.h +++ b/src/mapgen/mapgen.h @@ -102,15 +102,16 @@ private: std::list<GenNotifyEvent> m_notify_events; }; +// Order must match the order of 'static MapgenDesc g_reg_mapgens[]' in mapgen.cpp enum MapgenType { - MAPGEN_V5, - MAPGEN_V6, MAPGEN_V7, + MAPGEN_VALLEYS, + MAPGEN_CARPATHIAN, + MAPGEN_V5, MAPGEN_FLAT, MAPGEN_FRACTAL, - MAPGEN_VALLEYS, MAPGEN_SINGLENODE, - MAPGEN_CARPATHIAN, + MAPGEN_V6, MAPGEN_INVALID, }; @@ -189,11 +190,12 @@ public: void updateLiquid(UniqueQueue<v3s16> *trans_liquid, v3s16 nmin, v3s16 nmax); void setLighting(u8 light, v3s16 nmin, v3s16 nmax); - void lightSpread(VoxelArea &a, v3s16 p, u8 light); + void lightSpread(VoxelArea &a, std::queue<std::pair<v3s16, u8>> &queue, + const v3s16 &p, u8 light); void calcLighting(v3s16 nmin, v3s16 nmax, v3s16 full_nmin, v3s16 full_nmax, bool propagate_shadow = true); void propagateSunlight(v3s16 nmin, v3s16 nmax, bool propagate_shadow); - void spreadLight(v3s16 nmin, v3s16 nmax); + void spreadLight(const v3s16 &nmin, const v3s16 &nmax); virtual void makeChunk(BlockMakeData *data) {} virtual int getGroundLevelAtPoint(v2s16 p) { return 0; } @@ -208,8 +210,8 @@ public: // Mapgen management functions static MapgenType getMapgenType(const std::string &mgname); static const char *getMapgenName(MapgenType mgtype); - static Mapgen *createMapgen(MapgenType mgtype, int mgid, - MapgenParams *params, EmergeManager *emerge); + static Mapgen *createMapgen(MapgenType mgtype, MapgenParams *params, + EmergeManager *emerge); static MapgenParams *createMapgenParams(MapgenType mgtype); static void getMapgenNames(std::vector<const char *> *mgnames, bool include_hidden); @@ -257,21 +259,11 @@ protected: v3s16 full_node_min; v3s16 full_node_max; - // Content required for generateBiomes content_t c_stone; - content_t c_desert_stone; - content_t c_sandstone; content_t c_water_source; content_t c_river_water_source; content_t c_lava_source; - - // Content required for generateDungeons content_t c_cobble; - content_t c_stair_cobble; - content_t c_mossycobble; - content_t c_stair_desert_stone; - content_t c_sandstonebrick; - content_t c_stair_sandstone_block; int ystride; int zstride; @@ -283,9 +275,12 @@ protected: NoiseParams np_cave1; NoiseParams np_cave2; NoiseParams np_cavern; + NoiseParams np_dungeons; float cave_width; float cavern_limit; float cavern_taper; float cavern_threshold; + // TODO 'lava_depth' is deprecated and should be removed. Cave liquids are + // now defined and located using biome definitions. int lava_depth; }; diff --git a/src/mapgen/mapgen_carpathian.cpp b/src/mapgen/mapgen_carpathian.cpp index f7daef708..12ce07da4 100644 --- a/src/mapgen/mapgen_carpathian.cpp +++ b/src/mapgen/mapgen_carpathian.cpp @@ -1,8 +1,7 @@ /* Minetest -Copyright (C) 2017-2018 vlapsley, Vaughan Lapsley <vlapsley@gmail.com> -Copyright (C) 2010-2018 paramat -Copyright (C) 2010-2018 kwolekr, Ryan Kwolek <kwolekr@minetest.net> +Copyright (C) 2017-2019 vlapsley, Vaughan Lapsley <vlapsley@gmail.com> +Copyright (C) 2017-2019 paramat 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 @@ -43,6 +42,7 @@ with this program; if not, write to the Free Software Foundation, Inc., FlagDesc flagdesc_mapgen_carpathian[] = { {"caverns", MGCARPATHIAN_CAVERNS}, + {"rivers", MGCARPATHIAN_RIVERS}, {NULL, 0} }; @@ -50,11 +50,13 @@ FlagDesc flagdesc_mapgen_carpathian[] = { /////////////////////////////////////////////////////////////////////////////// -MapgenCarpathian::MapgenCarpathian( - int mapgenid, MapgenCarpathianParams *params, EmergeManager *emerge) - : MapgenBasic(mapgenid, params, emerge) +MapgenCarpathian::MapgenCarpathian(MapgenCarpathianParams *params, EmergeManager *emerge) + : MapgenBasic(MAPGEN_CARPATHIAN, params, emerge) { base_level = params->base_level; + river_width = params->river_width; + river_depth = params->river_depth; + valley_width = params->valley_width; spflags = params->spflags; cave_width = params->cave_width; @@ -80,6 +82,8 @@ MapgenCarpathian::MapgenCarpathian( noise_hills = new Noise(¶ms->np_hills, seed, csize.X, csize.Z); noise_ridge_mnt = new Noise(¶ms->np_ridge_mnt, seed, csize.X, csize.Z); noise_step_mnt = new Noise(¶ms->np_step_mnt, seed, csize.X, csize.Z); + if (spflags & MGCARPATHIAN_RIVERS) + noise_rivers = new Noise(¶ms->np_rivers, seed, csize.X, csize.Z); //// 3D terrain noise // 1 up 1 down overgeneration @@ -89,6 +93,7 @@ MapgenCarpathian::MapgenCarpathian( MapgenBasic::np_cave1 = params->np_cave1; MapgenBasic::np_cave2 = params->np_cave2; MapgenBasic::np_cavern = params->np_cavern; + MapgenBasic::np_dungeons = params->np_dungeons; } @@ -105,26 +110,31 @@ MapgenCarpathian::~MapgenCarpathian() delete noise_hills; delete noise_ridge_mnt; delete noise_step_mnt; + if (spflags & MGCARPATHIAN_RIVERS) + delete noise_rivers; + delete noise_mnt_var; } MapgenCarpathianParams::MapgenCarpathianParams(): - np_filler_depth (0, 1, v3f(128, 128, 128), 261, 3, 0.7, 2.0), - np_height1 (0, 5, v3f(251, 251, 251), 9613, 5, 0.5, 2.0), - np_height2 (0, 5, v3f(383, 383, 383), 1949, 5, 0.5, 2.0), - np_height3 (0, 5, v3f(509, 509, 509), 3211, 5, 0.5, 2.0), - np_height4 (0, 5, v3f(631, 631, 631), 1583, 5, 0.5, 2.0), - np_hills_terrain (1, 1, v3f(1301, 1301, 1301), 1692, 5, 0.5, 2.0), - np_ridge_terrain (1, 1, v3f(1889, 1889, 1889), 3568, 5, 0.5, 2.0), - np_step_terrain (1, 1, v3f(1889, 1889, 1889), 4157, 5, 0.5, 2.0), - np_hills (0, 3, v3f(257, 257, 257), 6604, 6, 0.5, 2.0), - np_ridge_mnt (0, 12, v3f(743, 743, 743), 5520, 6, 0.7, 2.0), - np_step_mnt (0, 8, v3f(509, 509, 509), 2590, 6, 0.6, 2.0), - np_mnt_var (0, 1, v3f(499, 499, 499), 2490, 5, 0.55, 2.0), - np_cave1 (0, 12, v3f(61, 61, 61), 52534, 3, 0.5, 2.0), - np_cave2 (0, 12, v3f(67, 67, 67), 10325, 3, 0.5, 2.0), - np_cavern (0, 1, v3f(384, 128, 384), 723, 5, 0.63, 2.0) + np_filler_depth (0, 1, v3f(128, 128, 128), 261, 3, 0.7, 2.0), + np_height1 (0, 5, v3f(251, 251, 251), 9613, 5, 0.5, 2.0), + np_height2 (0, 5, v3f(383, 383, 383), 1949, 5, 0.5, 2.0), + np_height3 (0, 5, v3f(509, 509, 509), 3211, 5, 0.5, 2.0), + np_height4 (0, 5, v3f(631, 631, 631), 1583, 5, 0.5, 2.0), + np_hills_terrain (1, 1, v3f(1301, 1301, 1301), 1692, 5, 0.5, 2.0), + np_ridge_terrain (1, 1, v3f(1889, 1889, 1889), 3568, 5, 0.5, 2.0), + np_step_terrain (1, 1, v3f(1889, 1889, 1889), 4157, 5, 0.5, 2.0), + np_hills (0, 3, v3f(257, 257, 257), 6604, 6, 0.5, 2.0), + np_ridge_mnt (0, 12, v3f(743, 743, 743), 5520, 6, 0.7, 2.0), + np_step_mnt (0, 8, v3f(509, 509, 509), 2590, 6, 0.6, 2.0), + np_rivers (0, 1, v3f(1000, 1000, 1000), 85039, 5, 0.6, 2.0), + np_mnt_var (0, 1, v3f(499, 499, 499), 2490, 5, 0.55, 2.0), + np_cave1 (0, 12, v3f(61, 61, 61), 52534, 3, 0.5, 2.0), + np_cave2 (0, 12, v3f(67, 67, 67), 10325, 3, 0.5, 2.0), + np_cavern (0, 1, v3f(384, 128, 384), 723, 5, 0.63, 2.0), + np_dungeons (0.9, 0.5, v3f(500, 500, 500), 0, 2, 0.8, 2.0) { } @@ -132,7 +142,12 @@ MapgenCarpathianParams::MapgenCarpathianParams(): void MapgenCarpathianParams::readParams(const Settings *settings) { settings->getFlagStrNoEx("mgcarpathian_spflags", spflags, flagdesc_mapgen_carpathian); - settings->getFloatNoEx("mgcarpathian_base_level", base_level); + + settings->getFloatNoEx("mgcarpathian_base_level", base_level); + settings->getFloatNoEx("mgcarpathian_river_width", river_width); + settings->getFloatNoEx("mgcarpathian_river_depth", river_depth); + settings->getFloatNoEx("mgcarpathian_valley_width", valley_width); + settings->getFloatNoEx("mgcarpathian_cave_width", cave_width); settings->getS16NoEx("mgcarpathian_large_cave_depth", large_cave_depth); settings->getS16NoEx("mgcarpathian_lava_depth", lava_depth); @@ -153,17 +168,24 @@ void MapgenCarpathianParams::readParams(const Settings *settings) settings->getNoiseParams("mgcarpathian_np_hills", np_hills); settings->getNoiseParams("mgcarpathian_np_ridge_mnt", np_ridge_mnt); settings->getNoiseParams("mgcarpathian_np_step_mnt", np_step_mnt); + settings->getNoiseParams("mgcarpathian_np_rivers", np_rivers); settings->getNoiseParams("mgcarpathian_np_mnt_var", np_mnt_var); settings->getNoiseParams("mgcarpathian_np_cave1", np_cave1); settings->getNoiseParams("mgcarpathian_np_cave2", np_cave2); settings->getNoiseParams("mgcarpathian_np_cavern", np_cavern); + settings->getNoiseParams("mgcarpathian_np_dungeons", np_dungeons); } void MapgenCarpathianParams::writeParams(Settings *settings) const { settings->setFlagStr("mgcarpathian_spflags", spflags, flagdesc_mapgen_carpathian, U32_MAX); - settings->setFloat("mgcarpathian_base_level", base_level); + + settings->setFloat("mgcarpathian_base_level", base_level); + settings->setFloat("mgcarpathian_river_width", river_width); + settings->setFloat("mgcarpathian_river_depth", river_depth); + settings->setFloat("mgcarpathian_valley_width", valley_width); + settings->setFloat("mgcarpathian_cave_width", cave_width); settings->setS16("mgcarpathian_large_cave_depth", large_cave_depth); settings->setS16("mgcarpathian_lava_depth", lava_depth); @@ -184,10 +206,12 @@ void MapgenCarpathianParams::writeParams(Settings *settings) const settings->setNoiseParams("mgcarpathian_np_hills", np_hills); settings->setNoiseParams("mgcarpathian_np_ridge_mnt", np_ridge_mnt); settings->setNoiseParams("mgcarpathian_np_step_mnt", np_step_mnt); + settings->setNoiseParams("mgcarpathian_np_rivers", np_rivers); settings->setNoiseParams("mgcarpathian_np_mnt_var", np_mnt_var); settings->setNoiseParams("mgcarpathian_np_cave1", np_cave1); settings->setNoiseParams("mgcarpathian_np_cave2", np_cave2); settings->setNoiseParams("mgcarpathian_np_cavern", np_cavern); + settings->setNoiseParams("mgcarpathian_np_dungeons", np_dungeons); } @@ -307,64 +331,95 @@ void MapgenCarpathian::makeChunk(BlockMakeData *data) int MapgenCarpathian::getSpawnLevelAtPoint(v2s16 p) { - s16 level_at_point = terrainLevelAtPoint(p.X, p.Y); - if (level_at_point <= water_level || level_at_point > water_level + 32) - return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point - - return level_at_point; -} - - -float MapgenCarpathian::terrainLevelAtPoint(s16 x, s16 z) -{ - float height1 = NoisePerlin2D(&noise_height1->np, x, z, seed); - float height2 = NoisePerlin2D(&noise_height2->np, x, z, seed); - float height3 = NoisePerlin2D(&noise_height3->np, x, z, seed); - float height4 = NoisePerlin2D(&noise_height4->np, x, z, seed); - float hter = NoisePerlin2D(&noise_hills_terrain->np, x, z, seed); - float rter = NoisePerlin2D(&noise_ridge_terrain->np, x, z, seed); - float ster = NoisePerlin2D(&noise_step_terrain->np, x, z, seed); - float n_hills = NoisePerlin2D(&noise_hills->np, x, z, seed); - float n_ridge_mnt = NoisePerlin2D(&noise_ridge_mnt->np, x, z, seed); - float n_step_mnt = NoisePerlin2D(&noise_step_mnt->np, x, z, seed); - - int height = -MAX_MAP_GENERATION_LIMIT; + // If rivers are enabled, first check if in a river channel + if (spflags & MGCARPATHIAN_RIVERS) { + float river = std::fabs(NoisePerlin2D(&noise_rivers->np, p.X, p.Y, seed)) - + river_width; + if (river < 0.0f) + return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point + } - for (s16 y = 1; y <= 30; y++) { - float mnt_var = NoisePerlin3D(&noise_mnt_var->np, x, y, z, seed); + float height1 = NoisePerlin2D(&noise_height1->np, p.X, p.Y, seed); + float height2 = NoisePerlin2D(&noise_height2->np, p.X, p.Y, seed); + float height3 = NoisePerlin2D(&noise_height3->np, p.X, p.Y, seed); + float height4 = NoisePerlin2D(&noise_height4->np, p.X, p.Y, seed); + + float hterabs = std::fabs(NoisePerlin2D(&noise_hills_terrain->np, p.X, p.Y, seed)); + float n_hills = NoisePerlin2D(&noise_hills->np, p.X, p.Y, seed); + float hill_mnt = hterabs * hterabs * hterabs * n_hills * n_hills; + + float rterabs = std::fabs(NoisePerlin2D(&noise_ridge_terrain->np, p.X, p.Y, seed)); + float n_ridge_mnt = NoisePerlin2D(&noise_ridge_mnt->np, p.X, p.Y, seed); + float ridge_mnt = rterabs * rterabs * rterabs * (1.0f - std::fabs(n_ridge_mnt)); + + float sterabs = std::fabs(NoisePerlin2D(&noise_step_terrain->np, p.X, p.Y, seed)); + float n_step_mnt = NoisePerlin2D(&noise_step_mnt->np, p.X, p.Y, seed); + float step_mnt = sterabs * sterabs * sterabs * getSteps(n_step_mnt); + + float valley = 1.0f; + float river = 0.0f; + + if ((spflags & MGCARPATHIAN_RIVERS) && node_max.Y >= water_level - 16) { + river = std::fabs(NoisePerlin2D(&noise_rivers->np, p.X, p.Y, seed)) - river_width; + if (river <= valley_width) { + // Within river valley + if (river < 0.0f) { + // River channel + valley = river; + } else { + // Valley slopes. + // 0 at river edge, 1 at valley edge. + float riversc = river / valley_width; + // Smoothstep + valley = riversc * riversc * (3.0f - 2.0f * riversc); + } + } + } - // Gradient & shallow seabed - s32 grad = (y < water_level) ? grad_wl + (water_level - y) * 3 : 1 - y; + bool solid_below = false; + u8 cons_non_solid = 0; // consecutive non-solid nodes - // Hill/Mountain height (hilliness) + for (s16 y = water_level; y <= water_level + 32; y++) { + float mnt_var = NoisePerlin3D(&noise_mnt_var->np, p.X, y, p.Y, seed); float hill1 = getLerp(height1, height2, mnt_var); float hill2 = getLerp(height3, height4, mnt_var); float hill3 = getLerp(height3, height2, mnt_var); float hill4 = getLerp(height1, height4, mnt_var); - float hilliness = - std::fmax(std::fmin(hill1, hill2), std::fmin(hill3, hill4)); - - // Rolling hills - float hill_mnt = hilliness * std::pow(n_hills, 2.f); - float hills = std::pow(std::fabs(hter), 3.f) * hill_mnt; - // Ridged mountains - float ridge_mnt = hilliness * (1.f - std::fabs(n_ridge_mnt)); - float ridged_mountains = std::pow(std::fabs(rter), 3.f) * ridge_mnt; + float hilliness = std::fmax(std::fmin(hill1, hill2), std::fmin(hill3, hill4)); + float hills = hill_mnt * hilliness; + float ridged_mountains = ridge_mnt * hilliness; + float step_mountains = step_mnt * hilliness; - // Step (terraced) mountains - float step_mnt = hilliness * getSteps(n_step_mnt); - float step_mountains = std::pow(std::fabs(ster), 3.f) * step_mnt; + s32 grad = 1 - y; - // Final terrain level float mountains = hills + ridged_mountains + step_mountains; float surface_level = base_level + mountains + grad; - if (y > surface_level && height < 0) - height = y; + if ((spflags & MGCARPATHIAN_RIVERS) && river <= valley_width) { + if (valley < 0.0f) { + // River channel + surface_level = std::fmin(surface_level, + water_level - std::sqrt(-valley) * river_depth); + } else if (surface_level > water_level) { + // Valley slopes + surface_level = water_level + (surface_level - water_level) * valley; + } + } + + if (y < surface_level) { //TODO '<=' fix from generateTerrain() + // solid node + solid_below = true; + cons_non_solid = 0; + } else { + // non-solid node + cons_non_solid++; + if (cons_non_solid == 3 && solid_below) + return y - 1; + } } - return height; + return MAX_MAP_GENERATION_LIMIT; // No suitable spawn point found } @@ -390,6 +445,9 @@ int MapgenCarpathian::generateTerrain() noise_step_mnt->perlinMap2D(node_min.X, node_min.Z); noise_mnt_var->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z); + if (spflags & MGCARPATHIAN_RIVERS) + noise_rivers->perlinMap2D(node_min.X, node_min.Z); + //// Place nodes const v3s16 &em = vm->m_area.getExtent(); s16 stone_surface_max_y = -MAX_MAP_GENERATION_LIMIT; @@ -412,13 +470,34 @@ int MapgenCarpathian::generateTerrain() float rterabs = std::fabs(noise_ridge_terrain->result[index2d]); float n_ridge_mnt = noise_ridge_mnt->result[index2d]; float ridge_mnt = rterabs * rterabs * rterabs * - (1.f - std::fabs(n_ridge_mnt)); + (1.0f - std::fabs(n_ridge_mnt)); // Step (terraced) mountains float sterabs = std::fabs(noise_step_terrain->result[index2d]); float n_step_mnt = noise_step_mnt->result[index2d]; float step_mnt = sterabs * sterabs * sterabs * getSteps(n_step_mnt); + // Rivers + float valley = 1.0f; + float river = 0.0f; + + if ((spflags & MGCARPATHIAN_RIVERS) && node_max.Y >= water_level - 16) { + river = std::fabs(noise_rivers->result[index2d]) - river_width; + if (river <= valley_width) { + // Within river valley + if (river < 0.0f) { + // River channel + valley = river; + } else { + // Valley slopes. + // 0 at river edge, 1 at valley edge. + float riversc = river / valley_width; + // Smoothstep + valley = riversc * riversc * (3.0f - 2.0f * riversc); + } + } + } + // Initialise 3D noise index and voxelmanip index to column base u32 index3d = (z - node_min.Z) * zstride_1u1d + (x - node_min.X); u32 vi = vm->m_area.index(x, node_min.Y - 1, z); @@ -453,7 +532,20 @@ int MapgenCarpathian::generateTerrain() float mountains = hills + ridged_mountains + step_mountains; float surface_level = base_level + mountains + grad; - if (y < surface_level) { + // Rivers + if ((spflags & MGCARPATHIAN_RIVERS) && node_max.Y >= water_level - 16 && + river <= valley_width) { + if (valley < 0.0f) { + // River channel + surface_level = std::fmin(surface_level, + water_level - std::sqrt(-valley) * river_depth); + } else if (surface_level > water_level) { + // Valley slopes + surface_level = water_level + (surface_level - water_level) * valley; + } + } + + if (y < surface_level) { //TODO '<=' vm->m_data[vi] = mn_stone; // Stone if (y > stone_surface_max_y) stone_surface_max_y = y; diff --git a/src/mapgen/mapgen_carpathian.h b/src/mapgen/mapgen_carpathian.h index c32212c9a..1fbac4bfd 100644 --- a/src/mapgen/mapgen_carpathian.h +++ b/src/mapgen/mapgen_carpathian.h @@ -1,8 +1,7 @@ /* Minetest -Copyright (C) 2017-2018 vlapsley, Vaughan Lapsley <vlapsley@gmail.com> -Copyright (C) 2010-2018 paramat -Copyright (C) 2010-2018 kwolekr, Ryan Kwolek <kwolekr@minetest.net> +Copyright (C) 2017-2019 vlapsley, Vaughan Lapsley <vlapsley@gmail.com> +Copyright (C) 2017-2019 paramat 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 @@ -23,8 +22,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mapgen.h" -///////// Mapgen Carpathian flags #define MGCARPATHIAN_CAVERNS 0x01 +#define MGCARPATHIAN_RIVERS 0x02 class BiomeManager; @@ -34,6 +33,9 @@ extern FlagDesc flagdesc_mapgen_carpathian[]; struct MapgenCarpathianParams : public MapgenParams { float base_level = 12.0f; + float river_width = 0.05f; + float river_depth = 24.0f; + float valley_width = 0.25f; u32 spflags = MGCARPATHIAN_CAVERNS; float cave_width = 0.09f; @@ -56,10 +58,12 @@ struct MapgenCarpathianParams : public MapgenParams NoiseParams np_hills; NoiseParams np_ridge_mnt; NoiseParams np_step_mnt; + NoiseParams np_rivers; NoiseParams np_mnt_var; NoiseParams np_cave1; NoiseParams np_cave2; NoiseParams np_cavern; + NoiseParams np_dungeons; MapgenCarpathianParams(); ~MapgenCarpathianParams() = default; @@ -71,21 +75,19 @@ struct MapgenCarpathianParams : public MapgenParams class MapgenCarpathian : public MapgenBasic { public: - MapgenCarpathian(int mapgenid, MapgenCarpathianParams *params, - EmergeManager *emerge); + MapgenCarpathian(MapgenCarpathianParams *params, EmergeManager *emerge); ~MapgenCarpathian(); virtual MapgenType getType() const { return MAPGEN_CARPATHIAN; } - float getSteps(float noise); - inline float getLerp(float noise1, float noise2, float mod); - virtual void makeChunk(BlockMakeData *data); int getSpawnLevelAtPoint(v2s16 p); private: float base_level; - s32 grad_wl; + float river_width; + float river_depth; + float valley_width; s16 large_cave_depth; s16 dungeon_ymin; @@ -101,8 +103,12 @@ private: Noise *noise_hills; Noise *noise_ridge_mnt; Noise *noise_step_mnt; + Noise *noise_rivers = nullptr; Noise *noise_mnt_var; - float terrainLevelAtPoint(s16 x, s16 z); + s32 grad_wl; + + float getSteps(float noise); + inline float getLerp(float noise1, float noise2, float mod); int generateTerrain(); }; diff --git a/src/mapgen/mapgen_flat.cpp b/src/mapgen/mapgen_flat.cpp index 11b27f85c..773b7b10f 100644 --- a/src/mapgen/mapgen_flat.cpp +++ b/src/mapgen/mapgen_flat.cpp @@ -48,8 +48,8 @@ FlagDesc flagdesc_mapgen_flat[] = { /////////////////////////////////////////////////////////////////////////////////////// -MapgenFlat::MapgenFlat(int mapgenid, MapgenFlatParams *params, EmergeManager *emerge) - : MapgenBasic(mapgenid, params, emerge) +MapgenFlat::MapgenFlat(MapgenFlatParams *params, EmergeManager *emerge) + : MapgenBasic(MAPGEN_FLAT, params, emerge) { spflags = params->spflags; ground_level = params->ground_level; @@ -69,8 +69,9 @@ MapgenFlat::MapgenFlat(int mapgenid, MapgenFlatParams *params, EmergeManager *em if ((spflags & MGFLAT_LAKES) || (spflags & MGFLAT_HILLS)) noise_terrain = new Noise(¶ms->np_terrain, seed, csize.X, csize.Z); // 3D noise - MapgenBasic::np_cave1 = params->np_cave1; - MapgenBasic::np_cave2 = params->np_cave2; + MapgenBasic::np_cave1 = params->np_cave1; + MapgenBasic::np_cave2 = params->np_cave2; + MapgenBasic::np_dungeons = params->np_dungeons; } @@ -84,10 +85,11 @@ MapgenFlat::~MapgenFlat() MapgenFlatParams::MapgenFlatParams(): - np_terrain (0, 1, v3f(600, 600, 600), 7244, 5, 0.6, 2.0), - np_filler_depth (0, 1.2, v3f(150, 150, 150), 261, 3, 0.7, 2.0), - np_cave1 (0, 12, v3f(61, 61, 61), 52534, 3, 0.5, 2.0), - np_cave2 (0, 12, v3f(67, 67, 67), 10325, 3, 0.5, 2.0) + np_terrain (0, 1, v3f(600, 600, 600), 7244, 5, 0.6, 2.0), + np_filler_depth (0, 1.2, v3f(150, 150, 150), 261, 3, 0.7, 2.0), + np_cave1 (0, 12, v3f(61, 61, 61), 52534, 3, 0.5, 2.0), + np_cave2 (0, 12, v3f(67, 67, 67), 10325, 3, 0.5, 2.0), + np_dungeons (0.9, 0.5, v3f(500, 500, 500), 0, 2, 0.8, 2.0) { } @@ -110,6 +112,7 @@ void MapgenFlatParams::readParams(const Settings *settings) settings->getNoiseParams("mgflat_np_filler_depth", np_filler_depth); settings->getNoiseParams("mgflat_np_cave1", np_cave1); settings->getNoiseParams("mgflat_np_cave2", np_cave2); + settings->getNoiseParams("mgflat_np_dungeons", np_dungeons); } @@ -131,6 +134,7 @@ void MapgenFlatParams::writeParams(Settings *settings) const settings->setNoiseParams("mgflat_np_filler_depth", np_filler_depth); settings->setNoiseParams("mgflat_np_cave1", np_cave1); settings->setNoiseParams("mgflat_np_cave2", np_cave2); + settings->setNoiseParams("mgflat_np_dungeons", np_dungeons); } @@ -139,26 +143,31 @@ void MapgenFlatParams::writeParams(Settings *settings) const int MapgenFlat::getSpawnLevelAtPoint(v2s16 p) { - s16 level_at_point = ground_level; - float n_terrain = 0.0f; - if ((spflags & MGFLAT_LAKES) || (spflags & MGFLAT_HILLS)) - n_terrain = NoisePerlin2D(&noise_terrain->np, p.X, p.Y, seed); + s16 stone_level = ground_level; + float n_terrain = + ((spflags & MGFLAT_LAKES) || (spflags & MGFLAT_HILLS)) ? + NoisePerlin2D(&noise_terrain->np, p.X, p.Y, seed) : + 0.0f; if ((spflags & MGFLAT_LAKES) && n_terrain < lake_threshold) { - level_at_point = ground_level - - (lake_threshold - n_terrain) * lake_steepness; + s16 depress = (lake_threshold - n_terrain) * lake_steepness; + stone_level = ground_level - depress; } else if ((spflags & MGFLAT_HILLS) && n_terrain > hill_threshold) { - level_at_point = ground_level + - (n_terrain - hill_threshold) * hill_steepness; + s16 rise = (n_terrain - hill_threshold) * hill_steepness; + stone_level = ground_level + rise; } - if (ground_level < water_level) // Ocean world, allow spawn in water - return MYMAX(level_at_point, water_level); + if (ground_level < water_level) + // Ocean world, may not have islands so allow spawn in water + return MYMAX(stone_level + 2, water_level); - if (level_at_point > water_level) - return level_at_point; // Spawn on land + if (stone_level >= water_level) + // Spawn on land + // + 2 not + 1, to spawn above biome 'dust' nodes + return stone_level + 2; - return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point + // Unsuitable spawn point + return MAX_MAP_GENERATION_LIMIT; } diff --git a/src/mapgen/mapgen_flat.h b/src/mapgen/mapgen_flat.h index d8ec9f126..d2598695f 100644 --- a/src/mapgen/mapgen_flat.h +++ b/src/mapgen/mapgen_flat.h @@ -48,6 +48,7 @@ struct MapgenFlatParams : public MapgenParams NoiseParams np_filler_depth; NoiseParams np_cave1; NoiseParams np_cave2; + NoiseParams np_dungeons; MapgenFlatParams(); ~MapgenFlatParams() = default; @@ -59,7 +60,7 @@ struct MapgenFlatParams : public MapgenParams class MapgenFlat : public MapgenBasic { public: - MapgenFlat(int mapgenid, MapgenFlatParams *params, EmergeManager *emerge); + MapgenFlat(MapgenFlatParams *params, EmergeManager *emerge); ~MapgenFlat(); virtual MapgenType getType() const { return MAPGEN_FLAT; } diff --git a/src/mapgen/mapgen_fractal.cpp b/src/mapgen/mapgen_fractal.cpp index 68a66bba9..091dbacfa 100644 --- a/src/mapgen/mapgen_fractal.cpp +++ b/src/mapgen/mapgen_fractal.cpp @@ -1,7 +1,7 @@ /* Minetest -Copyright (C) 2015-2018 paramat -Copyright (C) 2015-2018 kwolekr, Ryan Kwolek <kwolekr@minetest.net> +Copyright (C) 2015-2019 paramat +Copyright (C) 2015-2016 kwolekr, Ryan Kwolek 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 @@ -41,14 +41,15 @@ with this program; if not, write to the Free Software Foundation, Inc., FlagDesc flagdesc_mapgen_fractal[] = { - {NULL, 0} + {"terrain", MGFRACTAL_TERRAIN}, + {NULL, 0} }; /////////////////////////////////////////////////////////////////////////////////////// -MapgenFractal::MapgenFractal(int mapgenid, MapgenFractalParams *params, EmergeManager *emerge) - : MapgenBasic(mapgenid, params, emerge) +MapgenFractal::MapgenFractal(MapgenFractalParams *params, EmergeManager *emerge) + : MapgenBasic(MAPGEN_FRACTAL, params, emerge) { spflags = params->spflags; cave_width = params->cave_width; @@ -66,12 +67,17 @@ MapgenFractal::MapgenFractal(int mapgenid, MapgenFractalParams *params, EmergeMa julia_z = params->julia_z; julia_w = params->julia_w; - //// 2D terrain noise - noise_seabed = new Noise(¶ms->np_seabed, seed, csize.X, csize.Z); + //// 2D noise + if (spflags & MGFRACTAL_TERRAIN) + noise_seabed = new Noise(¶ms->np_seabed, seed, csize.X, csize.Z); + noise_filler_depth = new Noise(¶ms->np_filler_depth, seed, csize.X, csize.Z); - MapgenBasic::np_cave1 = params->np_cave1; - MapgenBasic::np_cave2 = params->np_cave2; + //// 3D noise + MapgenBasic::np_dungeons = params->np_dungeons; + // Overgeneration to node_min.Y - 1 + MapgenBasic::np_cave1 = params->np_cave1; + MapgenBasic::np_cave2 = params->np_cave2; formula = fractal / 2 + fractal % 2; julia = fractal % 2 == 0; @@ -80,7 +86,9 @@ MapgenFractal::MapgenFractal(int mapgenid, MapgenFractalParams *params, EmergeMa MapgenFractal::~MapgenFractal() { - delete noise_seabed; + if (noise_seabed) + delete noise_seabed; + delete noise_filler_depth; } @@ -89,7 +97,8 @@ MapgenFractalParams::MapgenFractalParams(): np_seabed (-14, 9, v3f(600, 600, 600), 41900, 5, 0.6, 2.0), np_filler_depth (0, 1.2, v3f(150, 150, 150), 261, 3, 0.7, 2.0), np_cave1 (0, 12, v3f(61, 61, 61), 52534, 3, 0.5, 2.0), - np_cave2 (0, 12, v3f(67, 67, 67), 10325, 3, 0.5, 2.0) + np_cave2 (0, 12, v3f(67, 67, 67), 10325, 3, 0.5, 2.0), + np_dungeons (0.9, 0.5, v3f(500, 500, 500), 0, 2, 0.8, 2.0) { } @@ -116,6 +125,7 @@ void MapgenFractalParams::readParams(const Settings *settings) settings->getNoiseParams("mgfractal_np_filler_depth", np_filler_depth); settings->getNoiseParams("mgfractal_np_cave1", np_cave1); settings->getNoiseParams("mgfractal_np_cave2", np_cave2); + settings->getNoiseParams("mgfractal_np_dungeons", np_dungeons); } @@ -141,6 +151,7 @@ void MapgenFractalParams::writeParams(Settings *settings) const settings->setNoiseParams("mgfractal_np_filler_depth", np_filler_depth); settings->setNoiseParams("mgfractal_np_cave1", np_cave1); settings->setNoiseParams("mgfractal_np_cave2", np_cave2); + settings->setNoiseParams("mgfractal_np_dungeons", np_dungeons); } @@ -149,21 +160,25 @@ void MapgenFractalParams::writeParams(Settings *settings) const int MapgenFractal::getSpawnLevelAtPoint(v2s16 p) { - bool solid_below = false; // Dry solid node is present below to spawn on - u8 air_count = 0; // Consecutive air nodes above the dry solid node - s16 seabed_level = NoisePerlin2D(&noise_seabed->np, p.X, p.Y, seed); - // Seabed can rise above water_level or might be raised to create dry land - s16 search_start = MYMAX(seabed_level, water_level + 1); - if (seabed_level > water_level) - solid_below = true; - - for (s16 y = search_start; y <= search_start + 128; y++) { - if (getFractalAtPoint(p.X, y, p.Y)) { // Fractal node + bool solid_below = false; // Fractal node is present below to spawn on + u8 air_count = 0; // Consecutive air nodes above a fractal node + s16 search_start = 0; // No terrain search start + + // If terrain present, don't start search below terrain or water level + if (noise_seabed) { + s16 seabed_level = NoisePerlin2D(&noise_seabed->np, p.X, p.Y, seed); + search_start = MYMAX(search_start, MYMAX(seabed_level, water_level)); + } + + for (s16 y = search_start; y <= search_start + 4096; y++) { + if (getFractalAtPoint(p.X, y, p.Y)) { + // Fractal node solid_below = true; air_count = 0; - } else if (solid_below) { // Air above solid node + } else if (solid_below) { + // Air above fractal node air_count++; - // 3 to account for snowblock dust + // 3 and -2 to account for biome dust nodes if (air_count == 3) return y - 2; } @@ -185,10 +200,11 @@ void MapgenFractal::makeChunk(BlockMakeData *data) data->blockpos_requested.Y <= data->blockpos_max.Y && data->blockpos_requested.Z <= data->blockpos_max.Z); + //TimeTaker t("makeChunk"); + this->generating = true; - this->vm = data->vmanip; + this->vm = data->vmanip; this->ndef = data->nodedef; - //TimeTaker t("makeChunk"); v3s16 blockpos_min = data->blockpos_min; v3s16 blockpos_max = data->blockpos_max; @@ -199,7 +215,7 @@ void MapgenFractal::makeChunk(BlockMakeData *data) blockseed = getBlockSeed2(full_node_min, seed); - // Generate base terrain, mountains, and ridges with initial heightmaps + // Generate fractal and optional terrain s16 stone_surface_max_y = generateTerrain(); // Create heightmap @@ -211,16 +227,16 @@ void MapgenFractal::makeChunk(BlockMakeData *data) generateBiomes(); } + // Generate tunnels and randomwalk caves if (flags & MG_CAVES) { - // Generate tunnels generateCavesNoiseIntersection(stone_surface_max_y); - // Generate large randomwalk caves generateCavesRandomWalk(stone_surface_max_y, large_cave_depth); } // Generate the registered ores m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max); + // Generate dungeons if ((flags & MG_DUNGEONS) && full_node_min.Y >= dungeon_ymin && full_node_max.Y <= dungeon_ymax) generateDungeons(stone_surface_max_y); @@ -233,18 +249,18 @@ void MapgenFractal::makeChunk(BlockMakeData *data) if (flags & MG_BIOMES) dustTopNodes(); - //printf("makeChunk: %dms\n", t.stop()); - - updateLiquid(&data->transforming_liquid, full_node_min, full_node_max); + // Update liquids + if (spflags & MGFRACTAL_TERRAIN) + updateLiquid(&data->transforming_liquid, full_node_min, full_node_max); + // Calculate lighting if (flags & MG_LIGHT) calcLighting(node_min - v3s16(0, 1, 0), node_max + v3s16(0, 1, 0), full_node_min, full_node_max); - //setLighting(node_min - v3s16(1, 0, 1) * MAP_BLOCKSIZE, - // node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE, 0xFF); - this->generating = false; + + //printf("makeChunk: %lums\n", t.stop()); } @@ -387,24 +403,29 @@ s16 MapgenFractal::generateTerrain() s16 stone_surface_max_y = -MAX_MAP_GENERATION_LIMIT; u32 index2d = 0; - noise_seabed->perlinMap2D(node_min.X, node_min.Z); + if (noise_seabed) + noise_seabed->perlinMap2D(node_min.X, node_min.Z); for (s16 z = node_min.Z; z <= node_max.Z; z++) { for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) { u32 vi = vm->m_area.index(node_min.X, y, z); for (s16 x = node_min.X; x <= node_max.X; x++, vi++, index2d++) { - if (vm->m_data[vi].getContent() == CONTENT_IGNORE) { - s16 seabed_height = noise_seabed->result[index2d]; - - if (y <= seabed_height || getFractalAtPoint(x, y, z)) { - vm->m_data[vi] = n_stone; - if (y > stone_surface_max_y) - stone_surface_max_y = y; - } else if (y <= water_level) { - vm->m_data[vi] = n_water; - } else { - vm->m_data[vi] = n_air; - } + if (vm->m_data[vi].getContent() != CONTENT_IGNORE) + continue; + + s16 seabed_height = -MAX_MAP_GENERATION_LIMIT; + if (noise_seabed) + seabed_height = noise_seabed->result[index2d]; + + if (((spflags & MGFRACTAL_TERRAIN) && y <= seabed_height) || + getFractalAtPoint(x, y, z)) { + vm->m_data[vi] = n_stone; + if (y > stone_surface_max_y) + stone_surface_max_y = y; + } else if ((spflags & MGFRACTAL_TERRAIN) && y <= water_level) { + vm->m_data[vi] = n_water; + } else { + vm->m_data[vi] = n_air; } } index2d -= ystride; diff --git a/src/mapgen/mapgen_fractal.h b/src/mapgen/mapgen_fractal.h index 5a1948b9a..82622d4d9 100644 --- a/src/mapgen/mapgen_fractal.h +++ b/src/mapgen/mapgen_fractal.h @@ -1,7 +1,7 @@ /* Minetest -Copyright (C) 2015-2018 paramat -Copyright (C) 2015-2018 kwolekr, Ryan Kwolek <kwolekr@minetest.net> +Copyright (C) 2015-2019 paramat +Copyright (C) 2015-2016 kwolekr, Ryan Kwolek Fractal formulas from http://www.bugman123.com/Hypercomplex/index.html by Paul Nylander, and from http://www.fractalforums.com, thank you. @@ -25,13 +25,17 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mapgen.h" +///////////// Mapgen Fractal flags +#define MGFRACTAL_TERRAIN 0x01 + class BiomeManager; extern FlagDesc flagdesc_mapgen_fractal[]; + struct MapgenFractalParams : public MapgenParams { - u32 spflags = 0; + u32 spflags = MGFRACTAL_TERRAIN; float cave_width = 0.09f; s16 large_cave_depth = -33; s16 lava_depth = -256; @@ -51,6 +55,7 @@ struct MapgenFractalParams : public MapgenParams NoiseParams np_filler_depth; NoiseParams np_cave1; NoiseParams np_cave2; + NoiseParams np_dungeons; MapgenFractalParams(); ~MapgenFractalParams() = default; @@ -59,10 +64,11 @@ struct MapgenFractalParams : public MapgenParams void writeParams(Settings *settings) const; }; + class MapgenFractal : public MapgenBasic { public: - MapgenFractal(int mapgenid, MapgenFractalParams *params, EmergeManager *emerge); + MapgenFractal(MapgenFractalParams *params, EmergeManager *emerge); ~MapgenFractal(); virtual MapgenType getType() const { return MAPGEN_FRACTAL; } @@ -88,5 +94,5 @@ private: float julia_y; float julia_z; float julia_w; - Noise *noise_seabed; + Noise *noise_seabed = nullptr; }; diff --git a/src/mapgen/mapgen_singlenode.cpp b/src/mapgen/mapgen_singlenode.cpp index 76f7e6e8e..b64524e1c 100644 --- a/src/mapgen/mapgen_singlenode.cpp +++ b/src/mapgen/mapgen_singlenode.cpp @@ -29,9 +29,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "emerge.h" -MapgenSinglenode::MapgenSinglenode(int mapgenid, - MapgenParams *params, EmergeManager *emerge) - : Mapgen(mapgenid, params, emerge) +MapgenSinglenode::MapgenSinglenode(MapgenParams *params, EmergeManager *emerge) + : Mapgen(MAPGEN_SINGLENODE, params, emerge) { const NodeDefManager *ndef = emerge->ndef; diff --git a/src/mapgen/mapgen_singlenode.h b/src/mapgen/mapgen_singlenode.h index ebfb3c729..c21089eda 100644 --- a/src/mapgen/mapgen_singlenode.h +++ b/src/mapgen/mapgen_singlenode.h @@ -38,7 +38,7 @@ public: content_t c_node; u8 set_light; - MapgenSinglenode(int mapgenid, MapgenParams *params, EmergeManager *emerge); + MapgenSinglenode(MapgenParams *params, EmergeManager *emerge); ~MapgenSinglenode() = default; virtual MapgenType getType() const { return MAPGEN_SINGLENODE; } diff --git a/src/mapgen/mapgen_v5.cpp b/src/mapgen/mapgen_v5.cpp index c5be727b9..bf99fd335 100644 --- a/src/mapgen/mapgen_v5.cpp +++ b/src/mapgen/mapgen_v5.cpp @@ -45,8 +45,8 @@ FlagDesc flagdesc_mapgen_v5[] = { }; -MapgenV5::MapgenV5(int mapgenid, MapgenV5Params *params, EmergeManager *emerge) - : MapgenBasic(mapgenid, params, emerge) +MapgenV5::MapgenV5(MapgenV5Params *params, EmergeManager *emerge) + : MapgenBasic(MAPGEN_V5, params, emerge) { spflags = params->spflags; cave_width = params->cave_width; @@ -67,9 +67,10 @@ MapgenV5::MapgenV5(int mapgenid, MapgenV5Params *params, EmergeManager *emerge) // 1-up 1-down overgeneration noise_ground = new Noise(¶ms->np_ground, seed, csize.X, csize.Y + 2, csize.Z); // 1 down overgeneration - MapgenBasic::np_cave1 = params->np_cave1; - MapgenBasic::np_cave2 = params->np_cave2; - MapgenBasic::np_cavern = params->np_cavern; + MapgenBasic::np_cave1 = params->np_cave1; + MapgenBasic::np_cave2 = params->np_cave2; + MapgenBasic::np_cavern = params->np_cavern; + MapgenBasic::np_dungeons = params->np_dungeons; } @@ -83,13 +84,14 @@ MapgenV5::~MapgenV5() MapgenV5Params::MapgenV5Params(): - np_filler_depth (0, 1, v3f(150, 150, 150), 261, 4, 0.7, 2.0), - np_factor (0, 1, v3f(250, 250, 250), 920381, 3, 0.45, 2.0), - np_height (0, 10, v3f(250, 250, 250), 84174, 4, 0.5, 2.0), - np_ground (0, 40, v3f(80, 80, 80), 983240, 4, 0.55, 2.0, NOISE_FLAG_EASED), - np_cave1 (0, 12, v3f(61, 61, 61), 52534, 3, 0.5, 2.0), - np_cave2 (0, 12, v3f(67, 67, 67), 10325, 3, 0.5, 2.0), - np_cavern (0, 1, v3f(384, 128, 384), 723, 5, 0.63, 2.0) + np_filler_depth (0, 1, v3f(150, 150, 150), 261, 4, 0.7, 2.0), + np_factor (0, 1, v3f(250, 250, 250), 920381, 3, 0.45, 2.0), + np_height (0, 10, v3f(250, 250, 250), 84174, 4, 0.5, 2.0), + np_ground (0, 40, v3f(80, 80, 80), 983240, 4, 0.55, 2.0, NOISE_FLAG_EASED), + np_cave1 (0, 12, v3f(61, 61, 61), 52534, 3, 0.5, 2.0), + np_cave2 (0, 12, v3f(67, 67, 67), 10325, 3, 0.5, 2.0), + np_cavern (0, 1, v3f(384, 128, 384), 723, 5, 0.63, 2.0), + np_dungeons (0.9, 0.5, v3f(500, 500, 500), 0, 2, 0.8, 2.0) { } @@ -113,6 +115,7 @@ void MapgenV5Params::readParams(const Settings *settings) settings->getNoiseParams("mgv5_np_cave1", np_cave1); settings->getNoiseParams("mgv5_np_cave2", np_cave2); settings->getNoiseParams("mgv5_np_cavern", np_cavern); + settings->getNoiseParams("mgv5_np_dungeons", np_dungeons); } @@ -135,6 +138,7 @@ void MapgenV5Params::writeParams(Settings *settings) const settings->setNoiseParams("mgv5_np_cave1", np_cave1); settings->setNoiseParams("mgv5_np_cave2", np_cave2); settings->setNoiseParams("mgv5_np_cavern", np_cavern); + settings->setNoiseParams("mgv5_np_dungeons", np_dungeons); } diff --git a/src/mapgen/mapgen_v5.h b/src/mapgen/mapgen_v5.h index a1b56a070..1a3b6d3c3 100644 --- a/src/mapgen/mapgen_v5.h +++ b/src/mapgen/mapgen_v5.h @@ -48,6 +48,7 @@ struct MapgenV5Params : public MapgenParams NoiseParams np_cave1; NoiseParams np_cave2; NoiseParams np_cavern; + NoiseParams np_dungeons; MapgenV5Params(); ~MapgenV5Params() = default; @@ -59,7 +60,7 @@ struct MapgenV5Params : public MapgenParams class MapgenV5 : public MapgenBasic { public: - MapgenV5(int mapgenid, MapgenV5Params *params, EmergeManager *emerge); + MapgenV5(MapgenV5Params *params, EmergeManager *emerge); ~MapgenV5(); virtual MapgenType getType() const { return MAPGEN_V5; } diff --git a/src/mapgen/mapgen_v6.cpp b/src/mapgen/mapgen_v6.cpp index fdfebe575..4e876fc53 100644 --- a/src/mapgen/mapgen_v6.cpp +++ b/src/mapgen/mapgen_v6.cpp @@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc., */ +#include <cmath> #include "mapgen.h" #include "voxel.h" #include "noise.h" @@ -55,11 +56,11 @@ FlagDesc flagdesc_mapgen_v6[] = { ///////////////////////////////////////////////////////////////////////////// -MapgenV6::MapgenV6(int mapgenid, MapgenV6Params *params, EmergeManager *emerge) - : Mapgen(mapgenid, params, emerge) +MapgenV6::MapgenV6(MapgenV6Params *params, EmergeManager *emerge) + : Mapgen(MAPGEN_V6, params, emerge) { m_emerge = emerge; - ystride = csize.X; //////fix this + ystride = csize.X; heightmap = new s16[csize.X * csize.Z]; @@ -74,6 +75,8 @@ MapgenV6::MapgenV6(int mapgenid, MapgenV6Params *params, EmergeManager *emerge) np_trees = ¶ms->np_trees; np_apple_trees = ¶ms->np_apple_trees; + np_dungeons = NoiseParams(0.9, 0.5, v3f(500.0, 500.0, 500.0), 0, 2, 0.8, 2.0); + //// Create noise objects noise_terrain_base = new Noise(¶ms->np_terrain_base, seed, csize.X, csize.Y); noise_terrain_higher = new Noise(¶ms->np_terrain_higher, seed, csize.X, csize.Y); @@ -535,7 +538,7 @@ void MapgenV6::makeChunk(BlockMakeData *data) updateHeightmap(node_min, node_max); const s16 max_spread_amount = MAP_BLOCKSIZE; - // Limit dirt flow area by 1 because mud is flown into neighbors. + // Limit dirt flow area by 1 because mud is flowed into neighbors s16 mudflow_minpos = -max_spread_amount + 1; s16 mudflow_maxpos = central_area_size.X + max_spread_amount - 2; @@ -561,48 +564,54 @@ void MapgenV6::makeChunk(BlockMakeData *data) // Add dungeons if ((flags & MG_DUNGEONS) && stone_surface_max_y >= node_min.Y && full_node_min.Y >= dungeon_ymin && full_node_max.Y <= dungeon_ymax) { - DungeonParams dp; - - dp.seed = seed; - dp.only_in_ground = true; - dp.corridor_len_min = 1; - dp.corridor_len_max = 13; - dp.rooms_min = 2; - dp.rooms_max = 16; - - dp.np_density - = NoiseParams(0.9, 0.5, v3f(500.0, 500.0, 500.0), 0, 2, 0.8, 2.0); - dp.np_alt_wall - = NoiseParams(-0.4, 1.0, v3f(40.0, 40.0, 40.0), 32474, 6, 1.1, 2.0); - - if (getBiome(0, v2s16(node_min.X, node_min.Z)) == BT_DESERT) { - dp.c_wall = c_desert_stone; - dp.c_alt_wall = CONTENT_IGNORE; - dp.c_stair = c_stair_desert_stone; - - dp.diagonal_dirs = true; - dp.holesize = v3s16(2, 3, 2); - dp.room_size_min = v3s16(6, 9, 6); - dp.room_size_max = v3s16(10, 11, 10); - dp.room_size_large_min = v3s16(10, 13, 10); - dp.room_size_large_max = v3s16(18, 21, 18); - dp.notifytype = GENNOTIFY_TEMPLE; - } else { - dp.c_wall = c_cobble; - dp.c_alt_wall = c_mossycobble; - dp.c_stair = c_stair_cobble; - - 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.notifytype = GENNOTIFY_DUNGEON; - } + u16 num_dungeons = std::fmax(std::floor( + NoisePerlin3D(&np_dungeons, node_min.X, node_min.Y, node_min.Z, seed)), 0.0f); + + if (num_dungeons >= 1) { + PseudoRandom ps(blockseed + 4713); + + DungeonParams dp; + + dp.seed = seed; + dp.num_dungeons = num_dungeons; + dp.only_in_ground = true; + dp.corridor_len_min = 1; + dp.corridor_len_max = 13; + dp.num_rooms = ps.range(2, 16); + dp.large_room_chance = (ps.range(1, 4) == 1) ? 1 : 0; + + dp.np_alt_wall + = NoiseParams(-0.4, 1.0, v3f(40.0, 40.0, 40.0), 32474, 6, 1.1, 2.0); + + if (getBiome(0, v2s16(node_min.X, node_min.Z)) == BT_DESERT) { + dp.c_wall = c_desert_stone; + dp.c_alt_wall = CONTENT_IGNORE; + dp.c_stair = c_stair_desert_stone; + + dp.diagonal_dirs = true; + dp.holesize = v3s16(2, 3, 2); + dp.room_size_min = v3s16(6, 9, 6); + dp.room_size_max = v3s16(10, 11, 10); + dp.room_size_large_min = v3s16(10, 13, 10); + dp.room_size_large_max = v3s16(18, 21, 18); + dp.notifytype = GENNOTIFY_TEMPLE; + } else { + dp.c_wall = c_cobble; + dp.c_alt_wall = c_mossycobble; + dp.c_stair = c_stair_cobble; + + 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.notifytype = GENNOTIFY_DUNGEON; + } - DungeonGen dgen(ndef, &gennotify, &dp); - dgen.generate(vm, blockseed, full_node_min, full_node_max); + DungeonGen dgen(ndef, &gennotify, &dp); + dgen.generate(vm, blockseed, full_node_min, full_node_max); + } } // Add top and bottom side of water to transforming_liquid queue @@ -764,128 +773,113 @@ void MapgenV6::addMud() void MapgenV6::flowMud(s16 &mudflow_minpos, s16 &mudflow_maxpos) { - // 340ms @cs=8 - //TimeTaker timer1("flow mud"); - - // Iterate a few times - for (s16 k = 0; k < 3; k++) { + const v3s16 &em = vm->m_area.getExtent(); + static const v3s16 dirs4[4] = { + v3s16(0, 0, 1), // Back + v3s16(1, 0, 0), // Right + v3s16(0, 0, -1), // Front + v3s16(-1, 0, 0), // Left + }; + + // Iterate twice + for (s16 k = 0; k < 2; k++) { for (s16 z = mudflow_minpos; z <= mudflow_maxpos; z++) for (s16 x = mudflow_minpos; x <= mudflow_maxpos; x++) { - // Invert coordinates every 2nd iteration - if (k % 2 == 0) { - x = mudflow_maxpos - (x - mudflow_minpos); - z = mudflow_maxpos - (z - mudflow_minpos); - } + // Node column position + v2s16 p2d; + // Invert coordinates on second iteration to process columns in + // opposite order, to avoid a directional bias. + if (k == 1) + p2d = v2s16(node_max.X, node_max.Z) - v2s16(x, z); + else + p2d = v2s16(node_min.X, node_min.Z) + v2s16(x, z); - // Node position in 2d - v2s16 p2d = v2s16(node_min.X, node_min.Z) + v2s16(x, z); - - const v3s16 &em = vm->m_area.getExtent(); - u32 i = vm->m_area.index(p2d.X, node_max.Y, p2d.Y); s16 y = node_max.Y; while (y >= node_min.Y) { + for (;; y--) { + u32 i = vm->m_area.index(p2d.X, y, p2d.Y); + MapNode *n = nullptr; + + // Find next mud node in mapchunk column + for (; y >= node_min.Y; y--) { + n = &vm->m_data[i]; + if (n->getContent() == c_dirt || + n->getContent() == c_dirt_with_grass || + n->getContent() == c_gravel) + break; - for (;; y--) { - MapNode *n = NULL; - // Find mud - for (; y >= node_min.Y; y--) { - n = &vm->m_data[i]; - if (n->getContent() == c_dirt || - n->getContent() == c_dirt_with_grass || - n->getContent() == c_gravel) + VoxelArea::add_y(em, i, -1); + } + if (y < node_min.Y) + // No mud found in mapchunk column, process the next column break; - VoxelArea::add_y(em, i, -1); - } - - // Stop if out of area - //if(vmanip.m_area.contains(i) == false) - if (y < node_min.Y) - break; - - if (n->getContent() == c_dirt || - n->getContent() == c_dirt_with_grass) { - // Make it exactly mud - n->setContent(c_dirt); - - // Don't flow it if the stuff under it is not mud - { + if (n->getContent() == c_dirt || n->getContent() == c_dirt_with_grass) { + // Convert dirt_with_grass to dirt + n->setContent(c_dirt); + // Don't flow mud if the stuff under it is not mud, + // to leave at least 1 node of mud. u32 i2 = i; VoxelArea::add_y(em, i2, -1); - // Cancel if out of area - if (!vm->m_area.contains(i2)) - continue; MapNode *n2 = &vm->m_data[i2]; if (n2->getContent() != c_dirt && n2->getContent() != c_dirt_with_grass) + // Find next mud node in column continue; } - } - static const v3s16 dirs4[4] = { - v3s16(0, 0, 1), // back - v3s16(1, 0, 0), // right - v3s16(0, 0, -1), // front - v3s16(-1, 0, 0), // left - }; - - // Check that upper is walkable. Cancel - // dropping if upper keeps it in place. - u32 i3 = i; - VoxelArea::add_y(em, i3, 1); - MapNode *n3 = NULL; - - if (vm->m_area.contains(i3)) { - n3 = &vm->m_data[i3]; + // Check if node above is walkable. If so, cancel + // flowing as if node above keeps it in place. + u32 i3 = i; + VoxelArea::add_y(em, i3, 1); + MapNode *n3 = &vm->m_data[i3]; if (ndef->get(*n3).walkable) + // Find next mud node in column continue; - } - // Drop mud on side - for (const v3s16 &dirp : dirs4) { - u32 i2 = i; - // Move to side - VoxelArea::add_p(em, i2, dirp); - // Fail if out of area - if (!vm->m_area.contains(i2)) - continue; - // Check that side is air - MapNode *n2 = &vm->m_data[i2]; - if (ndef->get(*n2).walkable) - continue; - // Check that under side is air - VoxelArea::add_y(em, i2, -1); - if (!vm->m_area.contains(i2)) - continue; - n2 = &vm->m_data[i2]; - if (ndef->get(*n2).walkable) - continue; - // Loop further down until not air - bool dropped_to_unknown = false; - do { + // Drop mud on one side + for (const v3s16 &dirp : dirs4) { + u32 i2 = i; + // Move to side + VoxelArea::add_p(em, i2, dirp); + // Check that side is air + MapNode *n2 = &vm->m_data[i2]; + if (ndef->get(*n2).walkable) + continue; + + // Check that under side is air VoxelArea::add_y(em, i2, -1); n2 = &vm->m_data[i2]; - // if out of known area - if (!vm->m_area.contains(i2) || - n2->getContent() == CONTENT_IGNORE) { - dropped_to_unknown = true; - break; - } - } while (!ndef->get(*n2).walkable); - // Loop one up so that we're in air - VoxelArea::add_y(em, i2, 1); - - // Move mud to new place. Outside mapchunk remove - // any decorations above removed or placed mud. - if (!dropped_to_unknown) - moveMud(i, i2, i3, p2d, em); + if (ndef->get(*n2).walkable) + continue; - // Done - break; + // Loop further down until not air + s16 y2 = y - 1; // y of i2 + bool dropped_to_unknown = false; + do { + y2--; + VoxelArea::add_y(em, i2, -1); + n2 = &vm->m_data[i2]; + // If out of area or in ungenerated world + if (y2 < full_node_min.Y || n2->getContent() == CONTENT_IGNORE) { + dropped_to_unknown = true; + break; + } + } while (!ndef->get(*n2).walkable); + + if (!dropped_to_unknown) { + // Move up one so that we're in air + VoxelArea::add_y(em, i2, 1); + // Move mud to new place, and if outside mapchunk remove + // any decorations above removed or placed mud. + moveMud(i, i2, i3, p2d, em); + } + // Done, find next mud node in column + break; + } } } - } } } } diff --git a/src/mapgen/mapgen_v6.h b/src/mapgen/mapgen_v6.h index 056281f2f..7d5229559 100644 --- a/src/mapgen/mapgen_v6.h +++ b/src/mapgen/mapgen_v6.h @@ -108,6 +108,8 @@ public: NoiseParams *np_trees; NoiseParams *np_apple_trees; + NoiseParams np_dungeons; + float freq_desert; float freq_beach; s16 dungeon_ymin; @@ -132,7 +134,7 @@ public: content_t c_stair_cobble; content_t c_stair_desert_stone; - MapgenV6(int mapgenid, MapgenV6Params *params, EmergeManager *emerge); + MapgenV6(MapgenV6Params *params, EmergeManager *emerge); ~MapgenV6(); virtual MapgenType getType() const { return MAPGEN_V6; } diff --git a/src/mapgen/mapgen_v7.cpp b/src/mapgen/mapgen_v7.cpp index 1354bf256..c9568760f 100644 --- a/src/mapgen/mapgen_v7.cpp +++ b/src/mapgen/mapgen_v7.cpp @@ -52,8 +52,8 @@ FlagDesc flagdesc_mapgen_v7[] = { //////////////////////////////////////////////////////////////////////////////// -MapgenV7::MapgenV7(int mapgenid, MapgenV7Params *params, EmergeManager *emerge) - : MapgenBasic(mapgenid, params, emerge) +MapgenV7::MapgenV7(MapgenV7Params *params, EmergeManager *emerge) + : MapgenBasic(MAPGEN_V7, params, emerge) { spflags = params->spflags; mount_zero_level = params->mount_zero_level; @@ -113,9 +113,10 @@ MapgenV7::MapgenV7(int mapgenid, MapgenV7Params *params, EmergeManager *emerge) new Noise(¶ms->np_mountain, seed, csize.X, csize.Y + 2, csize.Z); // 3D noise, 1 down overgeneration - MapgenBasic::np_cave1 = params->np_cave1; - MapgenBasic::np_cave2 = params->np_cave2; - MapgenBasic::np_cavern = params->np_cavern; + MapgenBasic::np_cave1 = params->np_cave1; + MapgenBasic::np_cave2 = params->np_cave2; + MapgenBasic::np_cavern = params->np_cavern; + MapgenBasic::np_dungeons = params->np_dungeons; } @@ -159,7 +160,8 @@ MapgenV7Params::MapgenV7Params(): np_ridge (0.0, 1.0, v3f(100, 100, 100), 6467, 4, 0.75, 2.0), np_cavern (0.0, 1.0, v3f(384, 128, 384), 723, 5, 0.63, 2.0), np_cave1 (0.0, 12.0, v3f(61, 61, 61), 52534, 3, 0.5, 2.0), - np_cave2 (0.0, 12.0, v3f(67, 67, 67), 10325, 3, 0.5, 2.0) + np_cave2 (0.0, 12.0, v3f(67, 67, 67), 10325, 3, 0.5, 2.0), + np_dungeons (0.9, 0.5, v3f(500, 500, 500), 0, 2, 0.8, 2.0) { } @@ -196,6 +198,7 @@ void MapgenV7Params::readParams(const Settings *settings) settings->getNoiseParams("mgv7_np_cavern", np_cavern); settings->getNoiseParams("mgv7_np_cave1", np_cave1); settings->getNoiseParams("mgv7_np_cave2", np_cave2); + settings->getNoiseParams("mgv7_np_dungeons", np_dungeons); } @@ -231,6 +234,7 @@ void MapgenV7Params::writeParams(Settings *settings) const settings->setNoiseParams("mgv7_np_cavern", np_cavern); settings->setNoiseParams("mgv7_np_cave1", np_cave1); settings->setNoiseParams("mgv7_np_cave2", np_cave2); + settings->setNoiseParams("mgv7_np_dungeons", np_dungeons); } diff --git a/src/mapgen/mapgen_v7.h b/src/mapgen/mapgen_v7.h index b55c80d3a..50039b16a 100644 --- a/src/mapgen/mapgen_v7.h +++ b/src/mapgen/mapgen_v7.h @@ -66,6 +66,7 @@ struct MapgenV7Params : public MapgenParams { NoiseParams np_cavern; NoiseParams np_cave1; NoiseParams np_cave2; + NoiseParams np_dungeons; MapgenV7Params(); ~MapgenV7Params() = default; @@ -77,7 +78,7 @@ struct MapgenV7Params : public MapgenParams { class MapgenV7 : public MapgenBasic { public: - MapgenV7(int mapgenid, MapgenV7Params *params, EmergeManager *emerge); + MapgenV7(MapgenV7Params *params, EmergeManager *emerge); ~MapgenV7(); virtual MapgenType getType() const { return MAPGEN_V7; } diff --git a/src/mapgen/mapgen_valleys.cpp b/src/mapgen/mapgen_valleys.cpp index 5f9267875..d0b36f29b 100644 --- a/src/mapgen/mapgen_valleys.cpp +++ b/src/mapgen/mapgen_valleys.cpp @@ -1,7 +1,7 @@ /* Minetest -Copyright (C) 2016-2018 Duane Robertson <duane@duanerobertson.com> -Copyright (C) 2016-2018 paramat +Copyright (C) 2016-2019 Duane Robertson <duane@duanerobertson.com> +Copyright (C) 2016-2019 paramat Based on Valleys Mapgen by Gael de Sailly (https://forum.minetest.net/viewtopic.php?f=9&t=11430) @@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ + #include "mapgen.h" #include "voxel.h" #include "noise.h" @@ -53,18 +54,12 @@ FlagDesc flagdesc_mapgen_valleys[] = { }; -//////////////////////////////////////////////////////////////////////////////// - - -MapgenValleys::MapgenValleys(int mapgenid, MapgenValleysParams *params, - EmergeManager *emerge) - : MapgenBasic(mapgenid, params, emerge) +MapgenValleys::MapgenValleys(MapgenValleysParams *params, EmergeManager *emerge) + : MapgenBasic(MAPGEN_VALLEYS, params, emerge) { // NOTE: MapgenValleys has a hard dependency on BiomeGenOriginal m_bgen = (BiomeGenOriginal *)biomegen; - BiomeParamsOriginal *bp = (BiomeParamsOriginal *)params->bparams; - spflags = params->spflags; altitude_chill = params->altitude_chill; river_depth_bed = params->river_depth + 1.0f; @@ -92,11 +87,10 @@ MapgenValleys::MapgenValleys(int mapgenid, MapgenValleysParams *params, noise_inter_valley_fill = new Noise(¶ms->np_inter_valley_fill, seed, csize.X, csize.Y + 2, csize.Z); // 1-down overgeneraion - MapgenBasic::np_cave1 = params->np_cave1; - MapgenBasic::np_cave2 = params->np_cave2; - MapgenBasic::np_cavern = params->np_cavern; - - humidity_adjust = bp->np_humidity.offset - 50.0f; + MapgenBasic::np_cave1 = params->np_cave1; + MapgenBasic::np_cave2 = params->np_cave2; + MapgenBasic::np_cavern = params->np_cavern; + MapgenBasic::np_dungeons = params->np_dungeons; } @@ -122,7 +116,8 @@ MapgenValleysParams::MapgenValleysParams(): np_valley_profile (0.6, 0.50, v3f(512, 512, 512), 777, 1, 1.0, 2.0), np_cave1 (0.0, 12.0, v3f(61, 61, 61), 52534, 3, 0.5, 2.0), np_cave2 (0.0, 12.0, v3f(67, 67, 67), 10325, 3, 0.5, 2.0), - np_cavern (0.0, 1.0, v3f(768, 256, 768), 59033, 6, 0.63, 2.0) + np_cavern (0.0, 1.0, v3f(768, 256, 768), 59033, 6, 0.63, 2.0), + np_dungeons (0.9, 0.5, v3f(500, 500, 500), 0, 2, 0.8, 2.0) { } @@ -153,6 +148,7 @@ void MapgenValleysParams::readParams(const Settings *settings) settings->getNoiseParams("mgvalleys_np_cave1", np_cave1); settings->getNoiseParams("mgvalleys_np_cave2", np_cave2); settings->getNoiseParams("mgvalleys_np_cavern", np_cavern); + settings->getNoiseParams("mgvalleys_np_dungeons", np_dungeons); } @@ -182,12 +178,10 @@ void MapgenValleysParams::writeParams(Settings *settings) const settings->setNoiseParams("mgvalleys_np_cave1", np_cave1); settings->setNoiseParams("mgvalleys_np_cave2", np_cave2); settings->setNoiseParams("mgvalleys_np_cavern", np_cavern); + settings->setNoiseParams("mgvalleys_np_dungeons", np_dungeons); } -//////////////////////////////////////////////////////////////////////////////// - - void MapgenValleys::makeChunk(BlockMakeData *data) { // Pre-conditions @@ -220,19 +214,16 @@ void MapgenValleys::makeChunk(BlockMakeData *data) // biome-related noises. m_bgen->calcBiomeNoise(node_min); - // Generate noise maps and base terrain height. - // Modify heat and humidity maps. - calculateNoise(); - - // Generate base terrain with initial heightmaps + // Generate terrain s16 stone_surface_max_y = generateTerrain(); - // Recalculate heightmap + // Create heightmap updateHeightmap(node_min, node_max); // Place biome-specific nodes and build biomemap - if (flags & MG_BIOMES) + if (flags & MG_BIOMES) { generateBiomes(); + } // Generate tunnels, caverns and large randomwalk caves if (flags & MG_CAVES) { @@ -281,244 +272,151 @@ void MapgenValleys::makeChunk(BlockMakeData *data) } -void MapgenValleys::calculateNoise() -{ - int x = node_min.X; - int y = node_min.Y - 1; - int z = node_min.Z; - - noise_inter_valley_slope->perlinMap2D(x, z); - noise_rivers->perlinMap2D(x, z); - noise_terrain_height->perlinMap2D(x, z); - noise_valley_depth->perlinMap2D(x, z); - noise_valley_profile->perlinMap2D(x, z); - - noise_inter_valley_fill->perlinMap3D(x, y, z); - - float heat_offset = 0.0f; - float humidity_scale = 1.0f; - // Altitude chill tends to reduce the average heat. - if (spflags & MGVALLEYS_ALT_CHILL) - heat_offset = 5.0f; - // River humidity tends to increase the humidity range. - if (spflags & MGVALLEYS_HUMID_RIVERS) - humidity_scale = 0.8f; - - for (s32 index = 0; index < csize.X * csize.Z; index++) { - m_bgen->heatmap[index] += heat_offset; - m_bgen->humidmap[index] *= humidity_scale; - } - - TerrainNoise tn; - - u32 index = 0; - for (tn.z = node_min.Z; tn.z <= node_max.Z; tn.z++) - for (tn.x = node_min.X; tn.x <= node_max.X; tn.x++, index++) { - // The parameters that we actually need to generate terrain are passed - // by address (and the return value). - tn.terrain_height = noise_terrain_height->result[index]; - // River noise is replaced with base terrain, which is basically the - // height of the water table. - tn.rivers = &noise_rivers->result[index]; - // Valley depth noise is replaced with the valley number that represents - // the height of terrain over rivers and is used to determine how close - // a river is for humidity calculation. - tn.valley = &noise_valley_depth->result[index]; - tn.valley_profile = noise_valley_profile->result[index]; - // Slope noise is replaced by the calculated slope which is used to get - // terrain height in the slow method, to create sharper mountains. - tn.slope = &noise_inter_valley_slope->result[index]; - tn.inter_valley_fill = noise_inter_valley_fill->result[index]; - - // This is the actual terrain height. - float mount = terrainLevelFromNoise(&tn); - noise_terrain_height->result[index] = mount; - } -} - - -float MapgenValleys::terrainLevelFromNoise(TerrainNoise *tn) -{ - // The square function changes the behaviour of this noise: very often - // small, and sometimes very high. - float valley_d = MYSQUARE(*tn->valley); - - // valley_d is here because terrain is generally higher where valleys are - // deep (mountains). base represents the height of the rivers, most of the - // surface is above. - float base = tn->terrain_height + valley_d; - - // "river" represents the distance from the river - float river = std::fabs(*tn->rivers) - river_size_factor; - - // Use the curve of the function 1-exp(-(x/a)^2) to model valleys. - // "valley" represents the height of the terrain, from the rivers. - float tv = std::fmax(river / tn->valley_profile, 0.0f); - *tn->valley = valley_d * (1.0f - std::exp(-MYSQUARE(tv))); - - // Approximate height of the terrain at this point - float mount = base + *tn->valley; - - *tn->slope *= *tn->valley; - - // Base ground is returned as rivers since it's basically the water table. - *tn->rivers = base; - - // Rivers are placed where "river" is negative, so where the original noise - // value is close to zero. - if (river < 0.0f) { - // Use the the function -sqrt(1-x^2) which models a circle - float tr = river / river_size_factor + 1.0f; - float depth = (river_depth_bed * - std::sqrt(std::fmax(0.0f, 1.0f - MYSQUARE(tr)))); - - // base - depth : height of the bottom of the river - // water_level - 3 : don't make rivers below 3 nodes under the surface. - // We use three because that's as low as the swamp biomes go. - // There is no logical equivalent to this using rangelim. - mount = - std::fmin(std::fmax(base - depth, (float)(water_level - 3)), mount); - - // Slope has no influence on rivers - *tn->slope = 0.0f; - } - - return mount; -} - - -// This avoids duplicating the code in terrainLevelFromNoise, adding only the -// final step of terrain generation without a noise map. - -float MapgenValleys::adjustedTerrainLevelFromNoise(TerrainNoise *tn) -{ - float mount = terrainLevelFromNoise(tn); - float result = mount; - s16 y_start = myround(mount); - float fill = - NoisePerlin3D(&noise_inter_valley_fill->np, tn->x, y_start, tn->z, seed); - bool is_ground = fill * *tn->slope >= y_start - mount; - s16 search_direction = is_ground ? 1 : -1; - - for (s16 i = 1; i <= 1000; i++) { - s16 y = y_start + i * search_direction; - fill = - NoisePerlin3D(&noise_inter_valley_fill->np, tn->x, y, tn->z, seed); - - bool was_ground = is_ground; - is_ground = fill * *tn->slope >= y - mount; - if (is_ground) - result = y; - if (is_ground != was_ground) - break; - } - - return result; -} - - int MapgenValleys::getSpawnLevelAtPoint(v2s16 p) { - // Check if in a river - float rivers = NoisePerlin2D(&noise_rivers->np, p.X, p.Y, seed); - if (std::fabs(rivers) < river_size_factor) - return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point - - s16 level_at_point = terrainLevelAtPoint(p.X, p.Y); - if (level_at_point <= water_level || - level_at_point > water_level + 16) - return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point - - // +1 to account for biome dust that can be 1 node deep - return level_at_point + 1; -} - - -float MapgenValleys::terrainLevelAtPoint(s16 x, s16 z) -{ - TerrainNoise tn; - - float rivers = NoisePerlin2D(&noise_rivers->np, x, z, seed); - float valley = NoisePerlin2D(&noise_valley_depth->np, x, z, seed); - float inter_valley_slope = - NoisePerlin2D(&noise_inter_valley_slope->np, x, z, seed); - - tn.x = x; - tn.z = z; - tn.terrain_height = NoisePerlin2D(&noise_terrain_height->np, x, z, seed); - tn.rivers = &rivers; - tn.valley = &valley; - tn.valley_profile = NoisePerlin2D(&noise_valley_profile->np, x, z, seed); - tn.slope = &inter_valley_slope; - tn.inter_valley_fill = 0.0f; - - return adjustedTerrainLevelFromNoise(&tn); + // Check if in a river channel + float n_rivers = NoisePerlin2D(&noise_rivers->np, p.X, p.Y, seed); + if (std::fabs(n_rivers) <= river_size_factor) + // Unsuitable spawn point + return MAX_MAP_GENERATION_LIMIT; + + float n_slope = NoisePerlin2D(&noise_inter_valley_slope->np, p.X, p.Y, seed); + float n_terrain_height = NoisePerlin2D(&noise_terrain_height->np, p.X, p.Y, seed); + float n_valley = NoisePerlin2D(&noise_valley_depth->np, p.X, p.Y, seed); + float n_valley_profile = NoisePerlin2D(&noise_valley_profile->np, p.X, p.Y, seed); + + float valley_d = n_valley * n_valley; + float base = n_terrain_height + valley_d; + float river = std::fabs(n_rivers) - river_size_factor; + float tv = std::fmax(river / n_valley_profile, 0.0f); + float valley_h = valley_d * (1.0f - std::exp(-tv * tv)); + float surface_y = base + valley_h; + float slope = n_slope * valley_h; + float river_y = base - 1.0f; + + // Raising the maximum spawn level above 'water_level + 16' is necessary for custom + // parameters that set average terrain level much higher than water_level. + s16 max_spawn_y = std::fmax( + noise_terrain_height->np.offset + + noise_valley_depth->np.offset * noise_valley_depth->np.offset, + water_level + 16); + + // Starting spawn search at max_spawn_y + 128 ensures 128 nodes of open + // space above spawn position. Avoids spawning in possibly sealed voids. + for (s16 y = max_spawn_y + 128; y >= water_level; y--) { + float n_fill = NoisePerlin3D(&noise_inter_valley_fill->np, p.X, y, p.Y, seed); + float surface_delta = (float)y - surface_y; + float density = slope * n_fill - surface_delta; + + if (density > 0.0f) { // If solid + // Sometimes surface level is below river water level in places that are not + // river channels. + if (y < water_level || y > max_spawn_y || y < (s16)river_y) + // Unsuitable spawn point + return MAX_MAP_GENERATION_LIMIT; + + // y + 2 because y is surface and due to biome 'dust' nodes. + return y + 2; + } + } + // Unsuitable spawn position, no ground found + return MAX_MAP_GENERATION_LIMIT; } int MapgenValleys::generateTerrain() { - // Raising this reduces the rate of evaporation - static const float evaporation = 300.0f; - static const float humidity_dropoff = 4.0f; - // Constant to convert altitude chill to heat - static const float alt_to_heat = 20.0f; - // Humidity reduction by altitude - static const float alt_to_humid = 10.0f; - MapNode n_air(CONTENT_AIR); MapNode n_river_water(c_river_water_source); MapNode n_stone(c_stone); MapNode n_water(c_water_source); + noise_inter_valley_slope->perlinMap2D(node_min.X, node_min.Z); + noise_rivers->perlinMap2D(node_min.X, node_min.Z); + noise_terrain_height->perlinMap2D(node_min.X, node_min.Z); + noise_valley_depth->perlinMap2D(node_min.X, node_min.Z); + noise_valley_profile->perlinMap2D(node_min.X, node_min.Z); + + noise_inter_valley_fill->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z); + const v3s16 &em = vm->m_area.getExtent(); s16 surface_max_y = -MAX_MAP_GENERATION_LIMIT; u32 index_2d = 0; for (s16 z = node_min.Z; z <= node_max.Z; z++) for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) { - float river_y = noise_rivers->result[index_2d]; - float surface_y = noise_terrain_height->result[index_2d]; - float slope = noise_inter_valley_slope->result[index_2d]; - float t_heat = m_bgen->heatmap[index_2d]; - - heightmap[index_2d] = -MAX_MAP_GENERATION_LIMIT; - - if (surface_y > surface_max_y) - surface_max_y = std::ceil(surface_y); + float n_slope = noise_inter_valley_slope->result[index_2d]; + float n_rivers = noise_rivers->result[index_2d]; + float n_terrain_height = noise_terrain_height->result[index_2d]; + float n_valley = noise_valley_depth->result[index_2d]; + float n_valley_profile = noise_valley_profile->result[index_2d]; + + float valley_d = n_valley * n_valley; + // 'base' represents the level of the river banks + float base = n_terrain_height + valley_d; + // 'river' represents the distance from the river edge + float river = std::fabs(n_rivers) - river_size_factor; + // Use the curve of the function 1-exp(-(x/a)^2) to model valleys. + // 'valley_h' represents the height of the terrain, from the rivers. + float tv = std::fmax(river / n_valley_profile, 0.0f); + float valley_h = valley_d * (1.0f - std::exp(-tv * tv)); + // Approximate height of the terrain + float surface_y = base + valley_h; + float slope = n_slope * valley_h; + // River water surface is 1 node below river banks + float river_y = base - 1.0f; + + // Rivers are placed where 'river' is negative + if (river < 0.0f) { + // Use the the function -sqrt(1-x^2) which models a circle + float tr = river / river_size_factor + 1.0f; + float depth = (river_depth_bed * + std::sqrt(std::fmax(0.0f, 1.0f - tr * tr))); + // There is no logical equivalent to this using rangelim + surface_y = std::fmin( + std::fmax(base - depth, (float)(water_level - 3)), + surface_y); + slope = 0.0f; + } // Optionally vary river depth according to heat and humidity if (spflags & MGVALLEYS_VARY_RIVER_DEPTH) { - float heat = ((spflags & MGVALLEYS_ALT_CHILL) && - (surface_y > 0.0f || river_y > 0.0f)) ? - t_heat - alt_to_heat * - std::fmax(surface_y, river_y) / altitude_chill : + float t_heat = m_bgen->heatmap[index_2d]; + float heat = (spflags & MGVALLEYS_ALT_CHILL) ? + // Match heat value calculated below in + // 'Optionally decrease heat with altitude'. + // In rivers, 'ground height ignoring riverbeds' is 'base'. + // As this only affects river water we can assume y > water_level. + t_heat + 5.0f - (base - water_level) * 20.0f / altitude_chill : t_heat; float delta = m_bgen->humidmap[index_2d] - 50.0f; if (delta < 0.0f) { - float t_evap = (heat - 32.0f) / evaporation; + float t_evap = (heat - 32.0f) / 300.0f; river_y += delta * std::fmax(t_evap, 0.08f); } } + // Highest solid node in column + s16 column_max_y = surface_y; u32 index_3d = (z - node_min.Z) * zstride_1u1d + (x - node_min.X); u32 index_data = vm->m_area.index(x, node_min.Y - 1, z); for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) { if (vm->m_data[index_data].getContent() == CONTENT_IGNORE) { - float fill = noise_inter_valley_fill->result[index_3d]; + float n_fill = noise_inter_valley_fill->result[index_3d]; float surface_delta = (float)y - surface_y; - bool river = y < river_y - 1; + // Density = density noise + density gradient + float density = slope * n_fill - surface_delta; - if (slope * fill > surface_delta) { + if (density > 0.0f) { vm->m_data[index_data] = n_stone; // Stone - if (y > heightmap[index_2d]) - heightmap[index_2d] = y; if (y > surface_max_y) surface_max_y = y; + if (y > column_max_y) + column_max_y = y; } else if (y <= water_level) { vm->m_data[index_data] = n_water; // Water - } else if (river) { + } else if (y <= (s16)river_y) { vm->m_data[index_data] = n_river_water; // River water } else { vm->m_data[index_data] = n_air; // Air @@ -529,26 +427,13 @@ int MapgenValleys::generateTerrain() index_3d += ystride; } - if (heightmap[index_2d] == -MAX_MAP_GENERATION_LIMIT) { - s16 surface_y_int = myround(surface_y); - - if (surface_y_int > node_max.Y + 1 || - surface_y_int < node_min.Y - 1) { - // If surface_y is outside the chunk, it's good enough - heightmap[index_2d] = surface_y_int; - } else { - // If the ground is outside of this chunk, but surface_y is - // within the chunk, give a value outside. - heightmap[index_2d] = node_min.Y - 2; - } - } - // Optionally increase humidity around rivers if (spflags & MGVALLEYS_HUMID_RIVERS) { + // Compensate to avoid increasing average humidity + m_bgen->humidmap[index_2d] *= 0.8f; // Ground height ignoring riverbeds - float t_alt = std::fmax(noise_rivers->result[index_2d], - (float)heightmap[index_2d]); - float water_depth = (t_alt - river_y) / humidity_dropoff; + float t_alt = std::fmax(base, (float)column_max_y); + float water_depth = (t_alt - base) / 4.0f; m_bgen->humidmap[index_2d] *= 1.0f + std::pow(0.5f, std::fmax(water_depth, 1.0f)); } @@ -556,21 +441,23 @@ int MapgenValleys::generateTerrain() // Optionally decrease humidity with altitude if (spflags & MGVALLEYS_ALT_DRY) { // Ground height ignoring riverbeds - float t_alt = std::fmax(noise_rivers->result[index_2d], - (float)heightmap[index_2d]); - if (t_alt > 0.0f) + float t_alt = std::fmax(base, (float)column_max_y); + // Only decrease above water_level + if (t_alt > water_level) m_bgen->humidmap[index_2d] -= - alt_to_humid * t_alt / altitude_chill; + (t_alt - water_level) * 10.0f / altitude_chill; } // Optionally decrease heat with altitude if (spflags & MGVALLEYS_ALT_CHILL) { + // Compensate to avoid reducing the average heat + m_bgen->heatmap[index_2d] += 5.0f; // Ground height ignoring riverbeds - float t_alt = std::fmax(noise_rivers->result[index_2d], - (float)heightmap[index_2d]); - if (t_alt > 0.0f) + float t_alt = std::fmax(base, (float)column_max_y); + // Only decrease above water_level + if (t_alt > water_level) m_bgen->heatmap[index_2d] -= - alt_to_heat * t_alt / altitude_chill; + (t_alt - water_level) * 20.0f / altitude_chill; } } diff --git a/src/mapgen/mapgen_valleys.h b/src/mapgen/mapgen_valleys.h index 8bde7a622..ab80dc5c9 100644 --- a/src/mapgen/mapgen_valleys.h +++ b/src/mapgen/mapgen_valleys.h @@ -1,11 +1,11 @@ /* Minetest -Copyright (C) 2016-2018 Duane Robertson <duane@duanerobertson.com> -Copyright (C) 2016-2018 paramat +Copyright (C) 2016-2019 Duane Robertson <duane@duanerobertson.com> +Copyright (C) 2016-2019 paramat Based on Valleys Mapgen by Gael de Sailly (https://forum.minetest.net/viewtopic.php?f=9&t=11430) -and mapgen_v7 by kwolekr and paramat. +and mapgen_v7, mapgen_flat by kwolekr and paramat. Licensing changed by permission of Gael de Sailly. @@ -24,20 +24,16 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ + #pragma once #include "mapgen.h" -/////////////////// Mapgen Valleys flags #define MGVALLEYS_ALT_CHILL 0x01 #define MGVALLEYS_HUMID_RIVERS 0x02 #define MGVALLEYS_VARY_RIVER_DEPTH 0x04 #define MGVALLEYS_ALT_DRY 0x08 -// Feed only one variable into these -#define MYSQUARE(x) (x) * (x) -#define MYCUBE(x) (x) * (x) * (x) - class BiomeManager; class BiomeGenOriginal; @@ -71,6 +67,7 @@ struct MapgenValleysParams : public MapgenParams { NoiseParams np_cave1; NoiseParams np_cave2; NoiseParams np_cavern; + NoiseParams np_dungeons; MapgenValleysParams(); ~MapgenValleysParams() = default; @@ -79,21 +76,11 @@ struct MapgenValleysParams : public MapgenParams { void writeParams(Settings *settings) const; }; -struct TerrainNoise { - s16 x; - s16 z; - float terrain_height; - float *rivers; - float *valley; - float valley_profile; - float *slope; - float inter_valley_fill; -}; class MapgenValleys : public MapgenBasic { public: - MapgenValleys(int mapgenid, MapgenValleysParams *params, + MapgenValleys(MapgenValleysParams *params, EmergeManager *emerge); ~MapgenValleys(); @@ -106,7 +93,6 @@ private: BiomeGenOriginal *m_bgen; float altitude_chill; - float humidity_adjust; float river_depth_bed; float river_size_factor; @@ -121,9 +107,5 @@ private: Noise *noise_valley_depth; Noise *noise_valley_profile; - float terrainLevelAtPoint(s16 x, s16 z); - void calculateNoise(); virtual int generateTerrain(); - float terrainLevelFromNoise(TerrainNoise *tn); - float adjustedTerrainLevelFromNoise(TerrainNoise *tn); }; diff --git a/src/mapgen/mg_biome.cpp b/src/mapgen/mg_biome.cpp index 7f717011c..345bc8c6a 100644 --- a/src/mapgen/mg_biome.cpp +++ b/src/mapgen/mg_biome.cpp @@ -63,6 +63,7 @@ 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_nnlistsizes.push_back(1); 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_riverbed, "mapgen_stone", CONTENT_AIR, 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_alt, "ignore", CONTENT_IGNORE, false); getIdFromNrBacklog(&c_dungeon_stair, "ignore", CONTENT_IGNORE, false); diff --git a/src/mapgen/mg_biome.h b/src/mapgen/mg_biome.h index 1f60f7bac..ee148adbc 100644 --- a/src/mapgen/mg_biome.h +++ b/src/mapgen/mg_biome.h @@ -52,7 +52,7 @@ public: content_t c_river_water; content_t c_riverbed; content_t c_dust; - content_t c_cave_liquid; + std::vector<content_t> c_cave_liquid; content_t c_dungeon; content_t c_dungeon_alt; content_t c_dungeon_stair; diff --git a/src/mapgen/mg_schematic.cpp b/src/mapgen/mg_schematic.cpp index 36f1dd76b..c1acbfd9d 100644 --- a/src/mapgen/mg_schematic.cpp +++ b/src/mapgen/mg_schematic.cpp @@ -246,7 +246,7 @@ void Schematic::placeOnMap(ServerMap *map, v3s16 p, u32 flags, for (it = modified_blocks.begin(); it != modified_blocks.end(); ++it) event.modified_blocks.insert(it->first); - map->dispatchEvent(&event); + map->dispatchEvent(event); } diff --git a/src/mapgen/treegen.cpp b/src/mapgen/treegen.cpp index 4c351fcef..0d8af2851 100644 --- a/src/mapgen/treegen.cpp +++ b/src/mapgen/treegen.cpp @@ -135,7 +135,7 @@ treegen::error spawn_ltree(ServerEnvironment *env, v3s16 p0, event.type = MEET_OTHER; for (auto &modified_block : modified_blocks) event.modified_blocks.insert(modified_block.first); - map->dispatchEvent(&event); + map->dispatchEvent(event); return SUCCESS; } |