void MapgenV6::addMud() { // 15ms @cs=8 //TimeTaker timer1("add mud"); MapNode n_dirt(c_dirt), n_gravel(c_gravel); MapNode n_sand(c_sand), n_desert_sand(c_desert_sand); MapNode addnode; u32 index = 0; for (s16 z = node_min.Z; z <= node_max.Z; z++) for (s16 x = node_min.X; x <= node_max.X; x++, index++) { // Randomize mud amount s16 mud_add_amount = getMudAmount(index) / 2.0 + 0.5; // Find ground level s16 surface_y = find_stone_level(v2s16(x, z)); /////////////////optimize this! // Handle area not found if (surface_y == vm->m_area.MinEdge.Y - 1) continue; BiomeV6Type bt = getBiome(v3POS(x, surface_y, z)); addnode = (bt == BT_DESERT) ? n_desert_sand : n_dirt; if (bt == BT_DESERT && surface_y + mud_add_amount <= water_level + 1) { addnode = n_sand; } else if (mud_add_amount <= 0) { mud_add_amount = 1 - mud_add_amount; addnode = n_gravel; } else if (bt != BT_DESERT && getHaveBeach(index) && surface_y + mud_add_amount <= water_level + 2) { addnode = n_sand; } if ((bt == BT_DESERT || bt == BT_TUNDRA) && surface_y > 20) mud_add_amount = MYMAX(0, mud_add_amount - (surface_y - 20) / 5); /* If topmost node is grass, change it to mud. It might be if it was // flown to there from a neighboring chunk and then converted. u32 i = vm->m_area.index(x, surface_y, z); if (vm->m_data[i].getContent() == c_dirt_with_grass) vm->m_data[i] = n_dirt;*/ // Add mud on ground s16 mudcount = 0; 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++) { if (mudcount >= mud_add_amount) break; vm->m_data[i] = addnode; mudcount++; vm->m_area.add_y(em, i, 1); } } }
int MapgenIndev::generateGround() { //TimeTaker timer1("Generating ground level"); MapNode n_air(CONTENT_AIR), n_water_source(c_water_source); MapNode n_stone(c_stone), n_desert_stone(c_desert_stone); MapNode n_ice(c_ice), n_dirt(c_dirt),n_sand(c_sand), n_gravel(c_gravel), n_lava_source(c_lava_source); int stone_surface_max_y = -MAX_MAP_GENERATION_LIMIT; u32 index = 0; for (s16 z = node_min.Z; z <= node_max.Z; z++) for (s16 x = node_min.X; x <= node_max.X; x++, index++) { // Surface height s16 surface_y = (s16)baseTerrainLevelFromMap(index); // Log it if (surface_y > stone_surface_max_y) stone_surface_max_y = surface_y; auto bt = getBiome(index, v3POS(x, surface_y, z)); s16 heat = m_emerge->env->m_use_weather ? m_emerge->env->getServerMap().updateBlockHeat(m_emerge->env, v3POS(x,node_max.Y,z), nullptr, &heat_cache) : 0; // Fill ground with stone v3POS 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]) { if (y <= surface_y) { int index3 = (z - node_min.Z) * zstride + (y - node_min.Y) * ystride + (x - node_min.X) * xstride; if (cave_noise_threshold && noise_cave_indev->result[index3] > cave_noise_threshold) { vm->m_data[i] = n_air; } else { auto n = (y > water_level - surface_y && bt == BT_DESERT) ? n_desert_stone : layers_get(index3); bool protect = n.getContent() != CONTENT_AIR; if (cave_noise_threshold && noise_cave_indev->result[index3] > cave_noise_threshold - 50) { vm->m_data[i] = protect ? n_stone : n; //cave shell without layers protect = true; } else { vm->m_data[i] = n; } if (protect) vm->m_flags[i] |= VOXELFLAG_CHECKED2; // no cave liquid } } else if (y <= water_level) { vm->m_data[i] = (heat < 0 && y > heat/3) ? n_ice : n_water_source; if (liquid_pressure && y <= 0) vm->m_data[i].addLevel(m_emerge->ndef, water_level - y, 1); } else { vm->m_data[i] = n_air; } } vm->m_area.add_y(em, i, 1); } } return stone_surface_max_y; }
void MapgenV6::growGrass() // Add surface nodes { MapNode n_dirt_with_grass(c_dirt_with_grass); MapNode n_dirt_with_snow(c_dirt_with_snow); MapNode n_snowblock(c_snowblock); MapNode n_snow(c_snow); MapNode n_dirt(c_dirt); v3s16 em = vm->m_area.getExtent(); u32 index = 0; for (s16 z = full_node_min.Z; z <= full_node_max.Z; z++) for (s16 x = full_node_min.X; x <= full_node_max.X; x++, index++) { // Find the lowest surface to which enough light ends up to make // grass grow. Basically just wait until not air and not leaves. s16 surface_y = 0; { u32 i = vm->m_area.index(x, node_max.Y, z); s16 y; // Go to ground level for (y = node_max.Y; y >= full_node_min.Y; y--) { MapNode &n = vm->m_data[i]; if (ndef->get(n).param_type != CPT_LIGHT || ndef->get(n).liquid_type != LIQUID_NONE || n.getContent() == c_ice) break; vm->m_area.add_y(em, i, -1); } surface_y = (y >= full_node_min.Y) ? y : full_node_min.Y; } BiomeV6Type bt = getBiome(index, v3POS(x, surface_y, z)); u32 i = vm->m_area.index(x, surface_y, z); content_t c = vm->m_data[i].getContent(); if (m_emerge->env->m_use_weather && c == c_dirt) { int heat = m_emerge->env->getServerMap().updateBlockHeat(m_emerge->env, v3POS(x, surface_y, z), nullptr, &heat_cache); vm->m_data[i] = (heat < -10 ? n_dirt_with_snow : (heat < -5 || heat > 50) ? n_dirt : n_dirt_with_grass); } else 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_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; } } else if (c == c_dirt) { vm->m_data[i] = n_dirt_with_grass; } } } }
void MapgenValleys::generateSimpleCaves(s16 max_stone_y) { PseudoRandom ps(blockseed + 72202); MapNode n_air(CONTENT_AIR); MapNode n_dirt(c_dirt); MapNode n_lava(c_lava_source); MapNode n_water(c_river_water_source); v3s16 em = vm->m_area.getExtent(); s16 base_water_chance = 0; if (water_features < 11) base_water_chance = ceil(MAX_MAP_GENERATION_LIMIT / (water_features * 1000)); if (max_stone_y >= node_min.Y) { u32 index_2d = 0; u32 index_3d = 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++) { bool air_above = false; //bool underground = false; u32 index_data = vm->m_area.index(x, node_max.Y + 1, z); index_3d = (z - node_min.Z) * zstride + (csize.Y + 1) * ystride + (x - node_min.X); // Dig caves on down loop to check for air above. for (s16 y = node_max.Y + 1; y >= node_min.Y - 1; y--, index_3d -= ystride, vm->m_area.add_y(em, index_data, -1)) { float terrain = noise_terrain_height->result[index_2d]; // Saves some time and prevents removing above ground nodes. if (y > terrain + 1) { air_above = true; continue; } content_t c = vm->m_data[index_data].getContent(); bool n1 = (fabs(noise_simple_caves_1->result[index_3d]) < 0.07f); bool n2 = (fabs(noise_simple_caves_2->result[index_3d]) < 0.07f); // River water is (foolishly) not set as ground content // in the default game. This can produce strange results // when a cave undercuts a river. However, that's not for // the mapgen to correct. Fix it in lua. if (c == CONTENT_AIR) { air_above = true; } else if (n1 && n2 && ndef->get(c).is_ground_content) { // When both n's are true, we're in a cave. vm->m_data[index_data] = n_air; air_above = true; } else if (air_above && (c == c_stone || c == c_sandstone || c == c_desert_stone)) { // At the cave floor s16 sr = ps.next() & 1023; u32 j = index_data; vm->m_area.add_y(em, j, 1); if (sr > (terrain - y) * 25) { // Put dirt in caves near the surface. Biome *biome = (Biome *)bmgr->getRaw(biomemap[index_2d]); vm->m_data[index_data] = MapNode(biome->c_filler); } else { s16 lava_chance = 0; if (y <= lava_max_height && c == c_stone) { // Lava spawns increase with depth. lava_chance = ceil((lava_max_height - y + 1) / 10000); if (sr < lava_chance) vm->m_data[j] = n_lava; } if (base_water_chance > 0 && y <= cave_water_max_height) { s16 water_chance = base_water_chance - (abs(y - water_level) / (water_features * 1000)); // Waterfalls may get out of control above ground. sr -= lava_chance; // If sr < 0 then we should have already placed lava -- // don't immediately dump water on it. if (sr >= 0 && sr < water_chance) vm->m_data[j] = n_water; } } air_above = false; } // If we're not in a cave, there's no open space. if (!(n1 && n2)) air_above = false; } } } }