X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fmapgen_v7.cpp;h=53f385b5396a8ab8f6e2cd6a24084cafbb881404;hb=ee9a442ecc26f2623a1b085344d37636342973eb;hp=c4583578f412fd5c281218c50f782035b06ba0ad;hpb=57eaf62c697cec91890d9cb28d10385d293d2d3f;p=minetest.git diff --git a/src/mapgen_v7.cpp b/src/mapgen_v7.cpp index c4583578f..53f385b53 100644 --- a/src/mapgen_v7.cpp +++ b/src/mapgen_v7.cpp @@ -1,7 +1,7 @@ /* Minetest -Copyright (C) 2010-2015 kwolekr, Ryan Kwolek -Copyright (C) 2010-2015 paramat, Matt Gregory +Copyright (C) 2013-2016 kwolekr, Ryan Kwolek +Copyright (C) 2014-2017 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 @@ -40,11 +40,12 @@ with this program; if not, write to the Free Software Foundation, Inc., FlagDesc flagdesc_mapgen_v7[] = { - {"mountains", MGV7_MOUNTAINS}, - {"ridges", MGV7_RIDGES}, - {"floatlands", MGV7_FLOATLANDS}, - {"caverns", MGV7_CAVERNS}, - {NULL, 0} + {"mountains", MGV7_MOUNTAINS}, + {"ridges", MGV7_RIDGES}, + {"floatlands", MGV7_FLOATLANDS}, + {"caverns", MGV7_CAVERNS}, + {"biomerepeat", MGV7_BIOMEREPEAT}, + {NULL, 0} }; @@ -54,15 +55,22 @@ FlagDesc flagdesc_mapgen_v7[] = { MapgenV7::MapgenV7(int mapgenid, MapgenV7Params *params, EmergeManager *emerge) : MapgenBasic(mapgenid, params, emerge) { - this->spflags = params->spflags; - this->cave_width = params->cave_width; - this->float_mount_density = params->float_mount_density; - this->float_mount_height = params->float_mount_height; - this->floatland_level = params->floatland_level; - this->shadow_limit = params->shadow_limit; - this->cavern_limit = params->cavern_limit; - this->cavern_taper = params->cavern_taper; - this->cavern_threshold = params->cavern_threshold; + spflags = params->spflags; + mount_zero_level = params->mount_zero_level; + cave_width = params->cave_width; + large_cave_depth = params->large_cave_depth; + lava_depth = params->lava_depth; + float_mount_density = params->float_mount_density; + floatland_level = params->floatland_level; + shadow_limit = params->shadow_limit; + cavern_limit = params->cavern_limit; + cavern_taper = params->cavern_taper; + cavern_threshold = params->cavern_threshold; + + // This is to avoid a divide-by-zero. + // Parameter will be saved to map_meta.txt in limited form. + params->float_mount_height = MYMAX(params->float_mount_height, 1.0f); + float_mount_height = params->float_mount_height; // 2D noise noise_terrain_base = new Noise(¶ms->np_terrain_base, seed, csize.X, csize.Z); @@ -97,52 +105,55 @@ MapgenV7::MapgenV7(int mapgenid, MapgenV7Params *params, EmergeManager *emerge) MapgenV7::~MapgenV7() { delete noise_terrain_base; + delete noise_terrain_alt; delete noise_terrain_persist; delete noise_height_select; - delete noise_terrain_alt; delete noise_filler_depth; - delete noise_mount_height; - delete noise_ridge_uwater; - delete noise_floatland_base; - delete noise_float_base_height; - delete noise_mountain; - delete noise_ridge; + + if (spflags & MGV7_MOUNTAINS) + delete noise_mount_height; + + if (spflags & MGV7_FLOATLANDS) { + delete noise_floatland_base; + delete noise_float_base_height; + } + + if (spflags & MGV7_RIDGES) { + delete noise_ridge_uwater; + delete noise_ridge; + } + + if ((spflags & MGV7_MOUNTAINS) || (spflags & MGV7_FLOATLANDS)) + delete noise_mountain; } -MapgenV7Params::MapgenV7Params() +MapgenV7Params::MapgenV7Params(): + np_terrain_base (4, 70, v3f(600, 600, 600), 82341, 5, 0.6, 2.0), + np_terrain_alt (4, 25, v3f(600, 600, 600), 5934, 5, 0.6, 2.0), + np_terrain_persist (0.6, 0.1, v3f(2000, 2000, 2000), 539, 3, 0.6, 2.0), + np_height_select (-8, 16, v3f(500, 500, 500), 4213, 6, 0.7, 2.0), + np_filler_depth (0, 1.2, v3f(150, 150, 150), 261, 3, 0.7, 2.0), + np_mount_height (256, 112, v3f(1000, 1000, 1000), 72449, 3, 0.6, 2.0), + np_ridge_uwater (0, 1, v3f(1000, 1000, 1000), 85039, 5, 0.6, 2.0), + np_floatland_base (-0.6, 1.5, v3f(600, 600, 600), 114, 5, 0.6, 2.0), + np_float_base_height (48, 24, v3f(300, 300, 300), 907, 4, 0.7, 2.0), + np_mountain (-0.6, 1, v3f(250, 350, 250), 5333, 5, 0.63, 2.0), + np_ridge (0, 1, v3f(100, 100, 100), 6467, 4, 0.75, 2.0), + np_cavern (0, 1, v3f(384, 128, 384), 723, 5, 0.63, 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) { - spflags = MGV7_MOUNTAINS | MGV7_RIDGES | MGV7_CAVERNS; - cave_width = 0.09; - float_mount_density = 0.6; - float_mount_height = 128.0; - floatland_level = 1280; - shadow_limit = 1024; - cavern_limit = -256; - cavern_taper = 256; - cavern_threshold = 0.7; - - np_terrain_base = NoiseParams(4, 70, v3f(600, 600, 600), 82341, 5, 0.6, 2.0); - np_terrain_alt = NoiseParams(4, 25, v3f(600, 600, 600), 5934, 5, 0.6, 2.0); - np_terrain_persist = NoiseParams(0.6, 0.1, v3f(2000, 2000, 2000), 539, 3, 0.6, 2.0); - np_height_select = NoiseParams(-8, 16, v3f(500, 500, 500), 4213, 6, 0.7, 2.0); - np_filler_depth = NoiseParams(0, 1.2, v3f(150, 150, 150), 261, 3, 0.7, 2.0); - np_mount_height = NoiseParams(256, 112, v3f(1000, 1000, 1000), 72449, 3, 0.6, 2.0); - np_ridge_uwater = NoiseParams(0, 1, v3f(1000, 1000, 1000), 85039, 5, 0.6, 2.0); - np_floatland_base = NoiseParams(-0.6, 1.5, v3f(600, 600, 600), 114, 5, 0.6, 2.0); - np_float_base_height = NoiseParams(48, 24, v3f(300, 300, 300), 907, 4, 0.7, 2.0); - np_mountain = NoiseParams(-0.6, 1, v3f(250, 350, 250), 5333, 5, 0.63, 2.0); - np_ridge = NoiseParams(0, 1, v3f(100, 100, 100), 6467, 4, 0.75, 2.0); - np_cavern = NoiseParams(0, 1, v3f(384, 128, 384), 723, 5, 0.63, 2.0); - np_cave1 = NoiseParams(0, 12, v3f(61, 61, 61), 52534, 3, 0.5, 2.0); - np_cave2 = NoiseParams(0, 12, v3f(67, 67, 67), 10325, 3, 0.5, 2.0); } void MapgenV7Params::readParams(const Settings *settings) { settings->getFlagStrNoEx("mgv7_spflags", spflags, flagdesc_mapgen_v7); + settings->getS16NoEx("mgv7_mount_zero_level", mount_zero_level); settings->getFloatNoEx("mgv7_cave_width", cave_width); + settings->getS16NoEx("mgv7_large_cave_depth", large_cave_depth); + settings->getS16NoEx("mgv7_lava_depth", lava_depth); settings->getFloatNoEx("mgv7_float_mount_density", float_mount_density); settings->getFloatNoEx("mgv7_float_mount_height", float_mount_height); settings->getS16NoEx("mgv7_floatland_level", floatland_level); @@ -171,7 +182,10 @@ void MapgenV7Params::readParams(const Settings *settings) void MapgenV7Params::writeParams(Settings *settings) const { settings->setFlagStr("mgv7_spflags", spflags, flagdesc_mapgen_v7, U32_MAX); + settings->setS16("mgv7_mount_zero_level", mount_zero_level); settings->setFloat("mgv7_cave_width", cave_width); + settings->setS16("mgv7_large_cave_depth", large_cave_depth); + settings->setS16("mgv7_lava_depth", lava_depth); settings->setFloat("mgv7_float_mount_density", float_mount_density); settings->setFloat("mgv7_float_mount_height", float_mount_height); settings->setS16("mgv7_floatland_level", floatland_level); @@ -202,10 +216,7 @@ void MapgenV7Params::writeParams(Settings *settings) const int MapgenV7::getSpawnLevelAtPoint(v2s16 p) { - // Base terrain calculation - s16 y = baseTerrainLevelAtPoint(p.X, p.Y); - - // If enabled, check if inside a river + // If rivers are enabled, first check if in a river if (spflags & MGV7_RIDGES) { float width = 0.2; float uwatern = NoisePerlin2D(&noise_ridge_uwater->np, p.X, p.Y, seed) * 2; @@ -213,28 +224,42 @@ int MapgenV7::getSpawnLevelAtPoint(v2s16 p) return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point } - // If mountains are disabled, terrain level is base terrain level - // Avoids spawn on non-existant mountain terrain + // Terrain noise 'offset' is the average level of that terrain. + // At least 50% of terrain will be below the higher of base and alt terrain + // 'offset's. + // Raising the maximum spawn level above 'water_level + 16' is necessary + // for when terrain 'offset's are set much higher than water_level. + s16 max_spawn_y = MYMAX(MYMAX(noise_terrain_alt->np.offset, + noise_terrain_base->np.offset), + water_level + 16); + // Base terrain calculation + s16 y = baseTerrainLevelAtPoint(p.X, p.Y); + + // If mountains are disabled, terrain level is base terrain level. + // Avoids mid-air spawn where mountain terrain would have been. if (!(spflags & MGV7_MOUNTAINS)) { - if (y <= water_level || y > water_level + 16) + if (y < water_level || y > max_spawn_y) return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point - else - return y; + + // y + 2 because y is surface level and due to biome 'dust' + return y + 2; } - // Mountain terrain calculation - int iters = 128; - while (iters--) { - if (!getMountainTerrainAtPoint(p.X, y + 1, p.Y)) { // If air above - if (y <= water_level || y > water_level + 16) + // Search upwards for first node without mountain terrain + int iters = 256; + while (iters > 0 && y <= max_spawn_y) { + if (!getMountainTerrainAtPoint(p.X, y + 1, p.Y)) { + if (y <= water_level || y > max_spawn_y) return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point - else - return y; + + // y + 1 due to biome 'dust' + return y + 1; } y++; + iters--; } - // Unsuitable spawn point, no mountain surface found + // Unsuitable spawn point return MAX_MAP_GENERATION_LIMIT; } @@ -265,6 +290,12 @@ void MapgenV7::makeChunk(BlockMakeData *data) blockseed = getBlockSeed2(full_node_min, seed); + // Get zero level for biomes and decorations + // Optionally repeat surface biomes in floatlands + s16 biome_zero_level = ((spflags & MGV7_FLOATLANDS) && + (spflags & MGV7_BIOMEREPEAT) && node_max.Y >= shadow_limit) ? + floatland_level - 1 : water_level - 1; + // Generate base and mountain terrain // An initial heightmap is no longer created here for use in generateRidgeTerrain() s16 stone_surface_max_y = generateTerrain(); @@ -278,34 +309,39 @@ void MapgenV7::makeChunk(BlockMakeData *data) // Init biome generator, place biome-specific nodes, and build biomemap biomegen->calcBiomeNoise(node_min); - MgStoneType stone_type = generateBiomes(); + + MgStoneType mgstone_type; + content_t biome_stone; + generateBiomes(&mgstone_type, &biome_stone, water_level - 1); // Generate caverns, tunnels and classic caves if (flags & MG_CAVES) { - bool has_cavern = false; + bool near_cavern = false; // Generate caverns if (spflags & MGV7_CAVERNS) - has_cavern = generateCaverns(stone_surface_max_y); + near_cavern = generateCaverns(stone_surface_max_y); // Generate tunnels and classic caves - if (has_cavern) + if (near_cavern) // Disable classic caves in this mapchunk by setting // 'large cave depth' to world base. Avoids excessive liquid in // large caverns and floating blobs of overgenerated liquid. generateCaves(stone_surface_max_y, -MAX_MAP_GENERATION_LIMIT); else - generateCaves(stone_surface_max_y, water_level); + generateCaves(stone_surface_max_y, large_cave_depth); } // Generate dungeons if (flags & MG_DUNGEONS) - generateDungeons(stone_surface_max_y, stone_type); + generateDungeons(stone_surface_max_y, mgstone_type, biome_stone); // Generate the registered decorations if (flags & MG_DECORATIONS) - m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max); + m_emerge->decomgr->placeAllDecos(this, blockseed, + node_min, node_max, biome_zero_level); // Generate the registered ores - m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max); + m_emerge->oremgr->placeAllOres(this, blockseed, + node_min, node_max, water_level - 1); // Sprinkle some dust on top after everything else was generated dustTopNodes(); @@ -366,8 +402,9 @@ float MapgenV7::baseTerrainLevelFromMap(int index) bool MapgenV7::getMountainTerrainAtPoint(s16 x, s16 y, s16 z) { - float mnt_h_n = NoisePerlin2D(&noise_mount_height->np, x, z, seed); - float density_gradient = -((float)y / mnt_h_n); + float mnt_h_n = + MYMAX(NoisePerlin2D(&noise_mount_height->np, x, z, seed), 1.0f); + float density_gradient = -((float)(y - mount_zero_level) / mnt_h_n); float mnt_n = NoisePerlin3D(&noise_mountain->np, x, y, z, seed); return mnt_n + density_gradient >= 0.0; @@ -376,8 +413,8 @@ bool MapgenV7::getMountainTerrainAtPoint(s16 x, s16 y, s16 z) bool MapgenV7::getMountainTerrainFromMap(int idx_xyz, int idx_xz, s16 y) { - float mounthn = noise_mount_height->result[idx_xz]; - float density_gradient = -((float)y / mounthn); + float mounthn = MYMAX(noise_mount_height->result[idx_xz], 1.0f); + float density_gradient = -((float)(y - mount_zero_level) / mounthn); float mountn = noise_mountain->result[idx_xyz]; return mountn + density_gradient >= 0.0; @@ -405,7 +442,8 @@ void MapgenV7::floatBaseExtentFromMap(s16 *float_base_min, s16 *float_base_max, float n_base = noise_floatland_base->result[idx_xz]; if (n_base > 0.0f) { - float n_base_height = noise_float_base_height->result[idx_xz]; + float n_base_height = + MYMAX(noise_float_base_height->result[idx_xz], 1.0f); float amp = n_base * n_base_height; float ridge = n_base_height / 3.0f; base_min = floatland_level - amp / 1.5f; @@ -455,7 +493,7 @@ int MapgenV7::generateTerrain() } //// Place nodes - v3s16 em = vm->m_area.getExtent(); + const v3s16 &em = vm->m_area.getExtent(); s16 stone_surface_max_y = -MAX_MAP_GENERATION_LIMIT; u32 index2d = 0; @@ -509,7 +547,8 @@ int MapgenV7::generateTerrain() void MapgenV7::generateRidgeTerrain() { - if ((node_max.Y < water_level - 16) || (node_max.Y > shadow_limit)) + if (node_max.Y < water_level - 16 || + ((spflags & MGV7_FLOATLANDS) && node_max.Y > shadow_limit)) return; noise_ridge->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);