X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fmapgen_v6.cpp;h=cd337b380f7f087fcc771794850d240ab81f782c;hb=f231112cc4f0c1fe7f8bb937a49e4469157a2fa7;hp=8492adfd92a3ead5c82b4a93ffc462763d0e0604;hpb=452df1c723722183ebf3a332f7bcc355be5b2998;p=dragonfireclient.git diff --git a/src/mapgen_v6.cpp b/src/mapgen_v6.cpp index 8492adfd9..cd337b380 100644 --- a/src/mapgen_v6.cpp +++ b/src/mapgen_v6.cpp @@ -1,6 +1,8 @@ /* Minetest -Copyright (C) 2010-2013 celeron55, Perttu Ahola +Copyright (C) 2010-2015 celeron55, Perttu Ahola +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 @@ -17,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 "mapgen.h" #include "voxel.h" #include "noise.h" @@ -37,45 +40,48 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mg_decoration.h" #include "mapgen_v6.h" + FlagDesc flagdesc_mapgen_v6[] = { {"jungles", MGV6_JUNGLES}, {"biomeblend", MGV6_BIOMEBLEND}, {"mudflow", MGV6_MUDFLOW}, {"snowbiomes", MGV6_SNOWBIOMES}, + {"flat", MGV6_FLAT}, + {"trees", MGV6_TREES}, {NULL, 0} }; -/////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// -MapgenV6::MapgenV6(int mapgenid, MapgenParams *params, EmergeManager *emerge) + +MapgenV6::MapgenV6(int mapgenid, MapgenV6Params *params, EmergeManager *emerge) : Mapgen(mapgenid, params, emerge) { - this->m_emerge = emerge; - this->ystride = csize.X; //////fix this + m_emerge = emerge; + ystride = csize.X; //////fix this - this->heightmap = new s16[csize.X * csize.Z]; + heightmap = new s16[csize.X * csize.Z]; - MapgenV6Params *sp = (MapgenV6Params *)params->sparams; - this->spflags = sp->spflags; - this->freq_desert = sp->freq_desert; - this->freq_beach = sp->freq_beach; + spflags = params->spflags; + freq_desert = params->freq_desert; + freq_beach = params->freq_beach; - np_cave = &sp->np_cave; - np_humidity = &sp->np_humidity; - np_trees = &sp->np_trees; - np_apple_trees = &sp->np_apple_trees; + np_cave = ¶ms->np_cave; + np_humidity = ¶ms->np_humidity; + np_trees = ¶ms->np_trees; + np_apple_trees = ¶ms->np_apple_trees; //// Create noise objects - noise_terrain_base = new Noise(&sp->np_terrain_base, seed, csize.X, csize.Y); - noise_terrain_higher = new Noise(&sp->np_terrain_higher, seed, csize.X, csize.Y); - noise_steepness = new Noise(&sp->np_steepness, seed, csize.X, csize.Y); - noise_height_select = new Noise(&sp->np_height_select, seed, csize.X, csize.Y); - noise_mud = new Noise(&sp->np_mud, seed, csize.X, csize.Y); - noise_beach = new Noise(&sp->np_beach, seed, csize.X, csize.Y); - noise_biome = new Noise(&sp->np_biome, seed, + 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); + noise_steepness = new Noise(¶ms->np_steepness, seed, csize.X, csize.Y); + noise_height_select = new Noise(¶ms->np_height_select, seed, csize.X, csize.Y); + noise_mud = new Noise(¶ms->np_mud, seed, csize.X, csize.Y); + noise_beach = new Noise(¶ms->np_beach, seed, csize.X, csize.Y); + noise_biome = new Noise(¶ms->np_biome, seed, csize.X + 2 * MAP_BLOCKSIZE, csize.Y + 2 * MAP_BLOCKSIZE); - noise_humidity = new Noise(&sp->np_humidity, seed, + noise_humidity = new Noise(¶ms->np_humidity, seed, csize.X + 2 * MAP_BLOCKSIZE, csize.Y + 2 * MAP_BLOCKSIZE); //// Resolve nodes to be used @@ -95,18 +101,12 @@ MapgenV6::MapgenV6(int mapgenid, MapgenParams *params, EmergeManager *emerge) c_snowblock = ndef->getId("mapgen_snowblock"); c_ice = ndef->getId("mapgen_ice"); - c_cobble = ndef->getId("mapgen_cobble"); - c_stair_cobble = ndef->getId("mapgen_stair_cobble"); - c_mossycobble = ndef->getId("mapgen_mossycobble"); - - if (c_desert_sand == CONTENT_IGNORE) - c_desert_sand = c_sand; + if (c_gravel == CONTENT_IGNORE) + c_gravel = c_stone; if (c_desert_stone == CONTENT_IGNORE) c_desert_stone = c_stone; - if (c_mossycobble == CONTENT_IGNORE) - c_mossycobble = c_cobble; - if (c_stair_cobble == CONTENT_IGNORE) - c_stair_cobble = c_cobble; + if (c_desert_sand == CONTENT_IGNORE) + c_desert_sand = c_sand; if (c_dirt_with_snow == CONTENT_IGNORE) c_dirt_with_snow = c_dirt_with_grass; if (c_snow == CONTENT_IGNORE) @@ -115,6 +115,18 @@ MapgenV6::MapgenV6(int mapgenid, MapgenParams *params, EmergeManager *emerge) c_snowblock = c_dirt_with_grass; if (c_ice == CONTENT_IGNORE) c_ice = c_water_source; + + 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"); + + 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; } @@ -133,23 +145,19 @@ MapgenV6::~MapgenV6() } -MapgenV6Params::MapgenV6Params() +MapgenV6Params::MapgenV6Params(): + np_terrain_base (-4, 20.0, v3f(250.0, 250.0, 250.0), 82341, 5, 0.6, 2.0), + np_terrain_higher (20, 16.0, v3f(500.0, 500.0, 500.0), 85039, 5, 0.6, 2.0), + np_steepness (0.85, 0.5, v3f(125.0, 125.0, 125.0), -932, 5, 0.7, 2.0), + np_height_select (0, 1.0, v3f(250.0, 250.0, 250.0), 4213, 5, 0.69, 2.0), + np_mud (4, 2.0, v3f(200.0, 200.0, 200.0), 91013, 3, 0.55, 2.0), + np_beach (0, 1.0, v3f(250.0, 250.0, 250.0), 59420, 3, 0.50, 2.0), + np_biome (0, 1.0, v3f(500.0, 500.0, 500.0), 9130, 3, 0.50, 2.0), + np_cave (6, 6.0, v3f(250.0, 250.0, 250.0), 34329, 3, 0.50, 2.0), + np_humidity (0.5, 0.5, v3f(500.0, 500.0, 500.0), 72384, 3, 0.50, 2.0), + np_trees (0, 1.0, v3f(125.0, 125.0, 125.0), 2, 4, 0.66, 2.0), + np_apple_trees (0, 1.0, v3f(100.0, 100.0, 100.0), 342902, 3, 0.45, 2.0) { - spflags = MGV6_BIOMEBLEND | MGV6_MUDFLOW; - freq_desert = 0.45; - freq_beach = 0.15; - - np_terrain_base = NoiseParams(-4, 20.0, v3f(250.0, 250.0, 250.0), 82341, 5, 0.6, 2.0); - np_terrain_higher = NoiseParams(20, 16.0, v3f(500.0, 500.0, 500.0), 85039, 5, 0.6, 2.0); - np_steepness = NoiseParams(0.85, 0.5, v3f(125.0, 125.0, 125.0), -932, 5, 0.7, 2.0); - np_height_select = NoiseParams(0, 1.0, v3f(250.0, 250.0, 250.0), 4213, 5, 0.69, 2.0); - np_mud = NoiseParams(4, 2.0, v3f(200.0, 200.0, 200.0), 91013, 3, 0.55, 2.0); - np_beach = NoiseParams(0, 1.0, v3f(250.0, 250.0, 250.0), 59420, 3, 0.50, 2.0); - np_biome = NoiseParams(0, 1.0, v3f(500.0, 500.0, 500.0), 9130, 3, 0.50, 2.0); - np_cave = NoiseParams(6, 6.0, v3f(250.0, 250.0, 250.0), 34329, 3, 0.50, 2.0); - np_humidity = NoiseParams(0.5, 0.5, v3f(500.0, 500.0, 500.0), 72384, 3, 0.50, 2.0); - np_trees = NoiseParams(0, 1.0, v3f(125.0, 125.0, 125.0), 2, 4, 0.66, 2.0); - np_apple_trees = NoiseParams(0, 1.0, v3f(100.0, 100.0, 100.0), 342902, 3, 0.45, 2.0); } @@ -175,7 +183,7 @@ void MapgenV6Params::readParams(const Settings *settings) void MapgenV6Params::writeParams(Settings *settings) const { - settings->setFlagStr("mgv6_spflags", spflags, flagdesc_mapgen_v6, (u32)-1); + settings->setFlagStr("mgv6_spflags", spflags, flagdesc_mapgen_v6, U32_MAX); settings->setFloat("mgv6_freq_desert", freq_desert); settings->setFloat("mgv6_freq_beach", freq_beach); @@ -195,11 +203,10 @@ void MapgenV6Params::writeParams(Settings *settings) const //////////////////////// Some helper functions for the map generator - // Returns Y one under area minimum if not found s16 MapgenV6::find_stone_level(v2s16 p2d) { - v3s16 em = vm->m_area.getExtent(); + const v3s16 &em = vm->m_area.getExtent(); s16 y_nodes_max = vm->m_area.MaxEdge.Y; s16 y_nodes_min = vm->m_area.MinEdge.Y; u32 i = vm->m_area.index(p2d.X, y_nodes_max, p2d.Y); @@ -226,8 +233,8 @@ bool MapgenV6::block_is_underground(u64 seed, v3s16 blockpos) if(blockpos.Y * MAP_BLOCKSIZE + MAP_BLOCKSIZE <= minimum_groundlevel) return true; - else - return false; + + return false; } @@ -263,7 +270,7 @@ float MapgenV6::baseTerrainLevel(float terrain_base, float terrain_higher, float MapgenV6::baseTerrainLevelFromNoise(v2s16 p) { - if (flags & MG_FLAT) + if (spflags & MGV6_FLAT) return water_level; float terrain_base = NoisePerlin2D_PO(&noise_terrain_base->np, @@ -289,7 +296,7 @@ float MapgenV6::baseTerrainLevelFromMap(v2s16 p) float MapgenV6::baseTerrainLevelFromMap(int index) { - if (flags & MG_FLAT) + if (spflags & MGV6_FLAT) return water_level; float terrain_base = noise_terrain_base->result[index]; @@ -304,13 +311,24 @@ float MapgenV6::baseTerrainLevelFromMap(int index) s16 MapgenV6::find_ground_level_from_noise(u64 seed, v2s16 p2d, s16 precision) { - return baseTerrainLevelFromNoise(p2d) + AVERAGE_MUD_AMOUNT; + return baseTerrainLevelFromNoise(p2d) + MGV6_AVERAGE_MUD_AMOUNT; } int MapgenV6::getGroundLevelAtPoint(v2s16 p) { - return baseTerrainLevelFromNoise(p) + AVERAGE_MUD_AMOUNT; + return baseTerrainLevelFromNoise(p) + MGV6_AVERAGE_MUD_AMOUNT; +} + + +int MapgenV6::getSpawnLevelAtPoint(v2s16 p) +{ + s16 level_at_point = baseTerrainLevelFromNoise(p) + MGV6_AVERAGE_MUD_AMOUNT; + if (level_at_point <= water_level || + level_at_point > water_level + 16) + return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point + + return level_at_point; } @@ -367,8 +385,8 @@ float MapgenV6::getTreeAmount(v2s16 p) float zeroval = -0.39; if (noise < zeroval) return 0; - else - return 0.04 * (noise - zeroval) / (1.0 - zeroval); + + return 0.04 * (noise - zeroval) / (1.0 - zeroval); } @@ -386,8 +404,8 @@ bool MapgenV6::getHaveAppleTree(v2s16 p) float MapgenV6::getMudAmount(int index) { - if (flags & MG_FLAT) - return AVERAGE_MUD_AMOUNT; + if (spflags & MGV6_FLAT) + return MGV6_AVERAGE_MUD_AMOUNT; /*return ((float)AVERAGE_MUD_AMOUNT + 2.0 * noise2d_perlin( 0.5+(float)p.X/200, 0.5+(float)p.Y/200, @@ -422,32 +440,35 @@ BiomeV6Type MapgenV6::getBiome(int index, v2s16 p) if (spflags & MGV6_SNOWBIOMES) { float blend = (spflags & MGV6_BIOMEBLEND) ? noise2d(p.X, p.Y, seed) / 40 : 0; - if (d > FREQ_HOT + blend) { - if (h > FREQ_JUNGLE + blend) + if (d > MGV6_FREQ_HOT + blend) { + if (h > MGV6_FREQ_JUNGLE + blend) return BT_JUNGLE; - else - return BT_DESERT; - } else if (d < FREQ_SNOW + blend) { - if (h > FREQ_TAIGA + blend) - return BT_TAIGA; - else - return BT_TUNDRA; - } else { - return BT_NORMAL; - } - } else { - if (d > freq_desert) - return BT_DESERT; - if ((spflags & MGV6_BIOMEBLEND) && (d > freq_desert - 0.10) && - ((noise2d(p.X, p.Y, seed) + 1.0) > (freq_desert - d) * 20.0)) return BT_DESERT; + } - if ((spflags & MGV6_JUNGLES) && h > 0.75) - return BT_JUNGLE; - else - return BT_NORMAL; + if (d < MGV6_FREQ_SNOW + blend) { + if (h > MGV6_FREQ_TAIGA + blend) + return BT_TAIGA; + + return BT_TUNDRA; + } + + return BT_NORMAL; } + + if (d > freq_desert) + return BT_DESERT; + + if ((spflags & MGV6_BIOMEBLEND) && (d > freq_desert - 0.10) && + ((noise2d(p.X, p.Y, seed) + 1.0) > (freq_desert - d) * 20.0)) + return BT_DESERT; + + if ((spflags & MGV6_JUNGLES) && h > 0.75) + return BT_JUNGLE; + + return BT_NORMAL; + } @@ -466,11 +487,11 @@ void MapgenV6::makeChunk(BlockMakeData *data) assert(data->vmanip); assert(data->nodedef); assert(data->blockpos_requested.X >= data->blockpos_min.X && - data->blockpos_requested.Y >= data->blockpos_min.Y && - data->blockpos_requested.Z >= data->blockpos_min.Z); + data->blockpos_requested.Y >= data->blockpos_min.Y && + data->blockpos_requested.Z >= data->blockpos_min.Z); assert(data->blockpos_requested.X <= data->blockpos_max.X && - data->blockpos_requested.Y <= data->blockpos_max.Y && - data->blockpos_requested.Z <= data->blockpos_max.Z); + data->blockpos_requested.Y <= data->blockpos_max.Y && + data->blockpos_requested.Z <= data->blockpos_max.Z); this->generating = true; this->vm = data->vmanip; @@ -491,13 +512,6 @@ void MapgenV6::makeChunk(BlockMakeData *data) central_area_size = node_max - node_min + v3s16(1, 1, 1); assert(central_area_size.X == central_area_size.Z); - int volume_blocks = (blockpos_max.X - blockpos_min.X + 1) - * (blockpos_max.Y - blockpos_min.Y + 1) - * (blockpos_max.Z - blockpos_max.Z + 1); - - volume_nodes = volume_blocks * - MAP_BLOCKSIZE * MAP_BLOCKSIZE * MAP_BLOCKSIZE; - // Create a block-specific seed blockseed = get_blockseed(data->seed, full_node_min); @@ -542,34 +556,51 @@ void MapgenV6::makeChunk(BlockMakeData *data) if ((flags & MG_DUNGEONS) && (stone_surface_max_y >= node_min.Y)) { DungeonParams dp; - dp.np_rarity = nparams_dungeon_rarity; - dp.np_density = nparams_dungeon_density; - dp.np_wetness = nparams_dungeon_wetness; - dp.c_water = c_water_source; + dp.seed = seed; + dp.c_water = c_water_source; + dp.c_river_water = c_water_source; + + dp.only_in_ground = true; + dp.corridor_len_min = 1; + dp.corridor_len_max = 13; + dp.rooms_min = 2; + dp.rooms_max = 16; + dp.y_min = -MAX_MAP_GENERATION_LIMIT; + dp.y_max = MAX_MAP_GENERATION_LIMIT; + + 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_cobble = c_desert_stone; - dp.c_moss = c_desert_stone; - dp.c_stair = c_desert_stone; - - dp.diagonal_dirs = true; - dp.mossratio = 0.0; - dp.holesize = v3s16(2, 3, 2); - dp.roomsize = v3s16(2, 5, 2); - dp.notifytype = GENNOTIFY_TEMPLE; + 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_cobble = c_cobble; - dp.c_moss = c_mossycobble; - dp.c_stair = c_stair_cobble; - - dp.diagonal_dirs = false; - dp.mossratio = 3.0; - dp.holesize = v3s16(1, 2, 1); - dp.roomsize = v3s16(0, 0, 0); - dp.notifytype = GENNOTIFY_DUNGEON; + 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(this, &dp); - dgen.generate(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 @@ -579,18 +610,23 @@ void MapgenV6::makeChunk(BlockMakeData *data) growGrass(); // Generate some trees, and add grass, if a jungle - if (flags & MG_TREES) + if (spflags & MGV6_TREES) placeTreesAndJungleGrass(); // Generate the registered decorations - m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max); + if (flags & MG_DECORATIONS) + m_emerge->decomgr->placeAllDecos(this, blockseed, + node_min, node_max, water_level - 1); // 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); // Calculate lighting if (flags & MG_LIGHT) - calcLighting(node_min, node_max); + calcLighting(node_min - v3s16(1, 1, 1) * MAP_BLOCKSIZE, + node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE, + full_node_min, full_node_max); this->generating = false; } @@ -603,7 +639,7 @@ void MapgenV6::calculateNoise() int fx = full_node_min.X; int fz = full_node_min.Z; - if (!(flags & MG_FLAT)) { + if (!(spflags & MGV6_FLAT)) { noise_terrain_base->perlinMap2D_PO(x, 0.5, z, 0.5); noise_terrain_higher->perlinMap2D_PO(x, 0.5, z, 0.5); noise_steepness->perlinMap2D_PO(x, 0.5, z, 0.5); @@ -641,16 +677,16 @@ int MapgenV6::generateGround() BiomeV6Type bt = getBiome(v2s16(x, z)); // Fill ground with stone - v3s16 em = vm->m_area.getExtent(); + const v3s16 &em = vm->m_area.getExtent(); u32 i = vm->m_area.index(x, node_min.Y, z); for (s16 y = node_min.Y; y <= node_max.Y; y++) { if (vm->m_data[i].getContent() == CONTENT_IGNORE) { if (y <= surface_y) { - vm->m_data[i] = (y >= DESERT_STONE_BASE + vm->m_data[i] = (y >= MGV6_DESERT_STONE_BASE && bt == BT_DESERT) ? n_desert_stone : n_stone; } else if (y <= water_level) { - vm->m_data[i] = (y >= ICE_BASE + vm->m_data[i] = (y >= MGV6_ICE_BASE && bt == BT_TUNDRA) ? n_ice : n_water_source; } else { @@ -710,7 +746,7 @@ void MapgenV6::addMud() // Add mud on ground s16 mudcount = 0; - v3s16 em = vm->m_area.getExtent(); + const v3s16 &em = vm->m_area.getExtent(); s16 y_start = surface_y + 1; u32 i = vm->m_area.index(x, y_start, z); for (s16 y = y_start; y <= node_max.Y; y++) { @@ -744,7 +780,7 @@ void MapgenV6::flowMud(s16 &mudflow_minpos, s16 &mudflow_maxpos) // Node position in 2d v2s16 p2d = v2s16(node_min.X, node_min.Z) + v2s16(x, z); - v3s16 em = vm->m_area.getExtent(); + 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; @@ -778,7 +814,7 @@ void MapgenV6::flowMud(s16 &mudflow_minpos, s16 &mudflow_maxpos) u32 i2 = i; vm->m_area.add_y(em, i2, -1); // Cancel if out of area - if (vm->m_area.contains(i2) == false) + if (!vm->m_area.contains(i2)) continue; MapNode *n2 = &vm->m_data[i2]; if (n2->getContent() != c_dirt && @@ -794,22 +830,25 @@ void MapgenV6::flowMud(s16 &mudflow_minpos, s16 &mudflow_maxpos) v3s16(-1, 0, 0), // left }; - // Check that upper is air or doesn't exist. - // Cancel dropping if upper keeps it in place + // Check that upper is walkable. Cancel + // dropping if upper keeps it in place. u32 i3 = i; vm->m_area.add_y(em, i3, 1); - if (vm->m_area.contains(i3) == true && - ndef->get(vm->m_data[i3]).walkable) - continue; + MapNode *n3 = NULL; + + if (vm->m_area.contains(i3)) { + n3 = &vm->m_data[i3]; + if (ndef->get(*n3).walkable) + continue; + } // Drop mud on side - for(u32 di = 0; di < 4; di++) { - v3s16 dirp = dirs4[di]; + for (const v3s16 &dirp : dirs4) { u32 i2 = i; // Move to side vm->m_area.add_p(em, i2, dirp); // Fail if out of area - if (vm->m_area.contains(i2) == false) + if (!vm->m_area.contains(i2)) continue; // Check that side is air MapNode *n2 = &vm->m_data[i2]; @@ -817,7 +856,7 @@ void MapgenV6::flowMud(s16 &mudflow_minpos, s16 &mudflow_maxpos) continue; // Check that under side is air vm->m_area.add_y(em, i2, -1); - if (vm->m_area.contains(i2) == false) + if (!vm->m_area.contains(i2)) continue; n2 = &vm->m_data[i2]; if (ndef->get(*n2).walkable) @@ -828,26 +867,19 @@ void MapgenV6::flowMud(s16 &mudflow_minpos, s16 &mudflow_maxpos) vm->m_area.add_y(em, i2, -1); n2 = &vm->m_data[i2]; // if out of known area - if(vm->m_area.contains(i2) == false || + if (!vm->m_area.contains(i2) || n2->getContent() == CONTENT_IGNORE) { dropped_to_unknown = true; break; } - } while (ndef->get(*n2).walkable == false); + } while (!ndef->get(*n2).walkable); // Loop one up so that we're in air vm->m_area.add_y(em, i2, 1); - n2 = &vm->m_data[i2]; - bool old_is_water = (n->getContent() == c_water_source); - // Move mud to new place - if (!dropped_to_unknown) { - *n2 = *n; - // Set old place to be air (or water) - if(old_is_water) - *n = MapNode(c_water_source); - else - *n = MapNode(CONTENT_AIR); - } + // 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); // Done break; @@ -859,6 +891,45 @@ void MapgenV6::flowMud(s16 &mudflow_minpos, s16 &mudflow_maxpos) } +void MapgenV6::moveMud(u32 remove_index, u32 place_index, + u32 above_remove_index, v2s16 pos, v3s16 em) +{ + MapNode n_air(CONTENT_AIR); + // Copy mud from old place to new place + vm->m_data[place_index] = vm->m_data[remove_index]; + // Set old place to be air + vm->m_data[remove_index] = n_air; + // Outside the mapchunk decorations may need to be removed if above removed + // mud or if half-buried in placed mud. Placed mud is to the side of pos so + // use 'pos.X >= node_max.X' etc. + if (pos.X >= node_max.X || pos.X <= node_min.X || + pos.Y >= node_max.Z || pos.Y <= node_min.Z) { + // 'above remove' node is above removed mud. If it is not air, water or + // 'ignore' it is a decoration that needs removing. Also search upwards + // to remove a possible stacked decoration. + // Check for 'ignore' because stacked decorations can penetrate into + // 'ignore' nodes above the mapchunk. + while (vm->m_area.contains(above_remove_index) && + vm->m_data[above_remove_index].getContent() != CONTENT_AIR && + vm->m_data[above_remove_index].getContent() != c_water_source && + vm->m_data[above_remove_index].getContent() != CONTENT_IGNORE) { + vm->m_data[above_remove_index] = n_air; + vm->m_area.add_y(em, above_remove_index, 1); + } + // Mud placed may have partially-buried a stacked decoration, search + // above and remove. + vm->m_area.add_y(em, place_index, 1); + while (vm->m_area.contains(place_index) && + vm->m_data[place_index].getContent() != CONTENT_AIR && + vm->m_data[place_index].getContent() != c_water_source && + vm->m_data[place_index].getContent() != CONTENT_IGNORE) { + vm->m_data[place_index] = n_air; + vm->m_area.add_y(em, place_index, 1); + } + } +} + + void MapgenV6::placeTreesAndJungleGrass() { //TimeTaker t("placeTrees"); @@ -871,7 +942,7 @@ void MapgenV6::placeTreesAndJungleGrass() if (c_junglegrass == CONTENT_IGNORE) c_junglegrass = CONTENT_AIR; MapNode n_junglegrass(c_junglegrass); - v3s16 em = vm->m_area.getExtent(); + const v3s16 &em = vm->m_area.getExtent(); // Divide area into parts s16 div = 8; @@ -946,14 +1017,13 @@ void MapgenV6::placeTreesAndJungleGrass() continue; v3s16 p(x, y, z); - // Trees grow only on mud and grass and snowblock + // Trees grow only on mud and grass { u32 i = vm->m_area.index(p); content_t c = vm->m_data[i].getContent(); if (c != c_dirt && c != c_dirt_with_grass && - c != c_dirt_with_snow && - c != c_snowblock) + c != c_dirt_with_snow) continue; } p.Y++; @@ -980,7 +1050,7 @@ void MapgenV6::growGrass() // Add surface nodes MapNode n_dirt_with_snow(c_dirt_with_snow); MapNode n_snowblock(c_snowblock); MapNode n_snow(c_snow); - v3s16 em = vm->m_area.getExtent(); + const v3s16 &em = vm->m_area.getExtent(); u32 index = 0; for (s16 z = full_node_min.Z; z <= full_node_max.Z; z++) @@ -1008,15 +1078,15 @@ void MapgenV6::growGrass() // Add surface nodes content_t c = vm->m_data[i].getContent(); if (surface_y >= water_level - 20) { if (bt == BT_TAIGA && c == c_dirt) { - vm->m_data[i] = n_snowblock; - vm->m_area.add_y(em, i, -1); vm->m_data[i] = n_dirt_with_snow; } else if (bt == BT_TUNDRA) { if (c == c_dirt) { + vm->m_data[i] = n_snowblock; + vm->m_area.add_y(em, i, -1); vm->m_data[i] = n_dirt_with_snow; } else if (c == c_stone && surface_y < node_max.Y) { vm->m_area.add_y(em, i, 1); - vm->m_data[i] = n_snow; + vm->m_data[i] = n_snowblock; } } else if (c == c_dirt) { vm->m_data[i] = n_dirt_with_grass; @@ -1046,9 +1116,10 @@ void MapgenV6::generateCaves(int max_stone_y) } for (u32 i = 0; i < caves_count + bruises_count; i++) { - bool large_cave = (i >= caves_count); - CaveV6 cave(this, &ps, &ps2, large_cave); + CavesV6 cave(ndef, &gennotify, water_level, c_water_source, c_lava_source); - cave.makeCave(node_min, node_max, max_stone_y); + bool large_cave = (i >= caves_count); + cave.makeCave(vm, node_min, node_max, &ps, &ps2, + large_cave, max_stone_y, heightmap); } }