void DungeonGen::generate(ManualMapVoxelManipulator *vm, u32 bseed, v3s16 nmin, v3s16 nmax) { //TimeTaker t("gen dungeons"); int approx_groundlevel = 10 + water_level; if ((nmin.Y + nmax.Y) / 2 >= approx_groundlevel || NoisePerlin3D(np_rarity, nmin.X, nmin.Y, nmin.Z, mapseed) < 0.2) return; this->vmanip = vm; this->blockseed = bseed; random.seed(bseed + 2); cid_water_source = ndef->getId("mapgen_water_source"); cid_cobble = ndef->getId("mapgen_cobble"); cid_mossycobble = ndef->getId("mapgen_mossycobble"); //cid_torch = ndef->getId("default:torch"); cid_cobblestair = ndef->getId("mapgen_stair_cobble"); // Dungeon generator doesn't modify places which have this set vmanip->clearFlag(VMANIP_FLAG_DUNGEON_INSIDE | VMANIP_FLAG_DUNGEON_PRESERVE); // Set all air and water to be untouchable to make dungeons open // to caves and open air for (s16 z = nmin.Z; z <= nmax.Z; z++) { for (s16 y = nmin.Y; y <= nmax.Y; y++) { u32 i = vmanip->m_area.index(nmin.X, y, z); for (s16 x = nmin.X; x <= nmax.X; x++) { content_t c = vmanip->m_data[i].getContent(); if (c == CONTENT_AIR || c == cid_water_source) vmanip->m_flags[i] |= VMANIP_FLAG_DUNGEON_PRESERVE; i++; } } } // Add it makeDungeon(v3s16(1,1,1) * MAP_BLOCKSIZE); // Convert some cobble to mossy cobble for (s16 z = nmin.Z; z <= nmax.Z; z++) { for (s16 y = nmin.Y; y <= nmax.Y; y++) { u32 i = vmanip->m_area.index(nmin.X, y, z); for (s16 x = nmin.X; x <= nmax.X; x++) { if (vmanip->m_data[i].getContent() == cid_cobble) { float wetness = NoisePerlin3D(np_wetness, x, y, z, mapseed); float density = NoisePerlin3D(np_density, x, y, z, blockseed); if (density < wetness / 3.0) vmanip->m_data[i].setContent(cid_mossycobble); } i++; } } } //printf("== gen dungeons: %dms\n", t.stop()); }
void DungeonGen::generate(MMVManip *vm, u32 bseed, v3s16 nmin, v3s16 nmax) { assert(vm); //TimeTaker t("gen dungeons"); if (nmin.Y < dp.y_min || nmax.Y > dp.y_max) return; float nval_density = NoisePerlin3D(&dp.np_density, nmin.X, nmin.Y, nmin.Z, dp.seed); if (nval_density < 1.0f) return; this->vm = vm; this->blockseed = bseed; random.seed(bseed + 2); // Dungeon generator doesn't modify places which have this set vm->clearFlag(VMANIP_FLAG_DUNGEON_INSIDE | VMANIP_FLAG_DUNGEON_PRESERVE); // Set all air and water to be untouchable // to make dungeons open to caves and open air 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); for (s16 x = nmin.X; x <= nmax.X; x++) { content_t c = vm->m_data[i].getContent(); if (c == CONTENT_AIR || c == dp.c_water || c == dp.c_river_water) vm->m_flags[i] |= VMANIP_FLAG_DUNGEON_PRESERVE; i++; } } } // Add them for (u32 i = 0; i < floor(nval_density); i++) makeDungeon(v3s16(1, 1, 1) * MAP_BLOCKSIZE); // Optionally convert some structure to alternative structure if (dp.c_alt_wall == CONTENT_IGNORE) return; 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); for (s16 x = nmin.X; x <= nmax.X; x++) { if (vm->m_data[i].getContent() == dp.c_wall) { if (NoisePerlin3D(&dp.np_alt_wall, x, y, z, blockseed) > 0.0f) vm->m_data[i].setContent(dp.c_alt_wall); } i++; } } //printf("== gen dungeons: %dms\n", t.stop()); }
void DungeonGen::generate(u32 bseed, v3s16 nmin, v3s16 nmax) { //TimeTaker t("gen dungeons"); if (NoisePerlin3D(&dp.np_rarity, nmin.X, nmin.Y, nmin.Z, mg->seed) < 0.2) return; this->blockseed = bseed; random.seed(bseed + 2); // Dungeon generator doesn't modify places which have this set vm->clearFlag(VMANIP_FLAG_DUNGEON_INSIDE | VMANIP_FLAG_DUNGEON_PRESERVE); bool no_float = !g_settings->getBool("enable_floating_dungeons"); // Set all air and water (and optionally ignore) to be untouchable // to make dungeons open to caves and open air 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); for (s16 x = nmin.X; x <= nmax.X; x++) { content_t c = vm->m_data[i].getContent(); if (c == CONTENT_AIR || c == dp.c_water || (no_float && c == CONTENT_IGNORE)) vm->m_flags[i] |= VMANIP_FLAG_DUNGEON_PRESERVE; i++; } } } // Add it makeDungeon(v3s16(1, 1, 1) * MAP_BLOCKSIZE); // Convert some cobble to mossy cobble if (dp.mossratio != 0.0) { 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); for (s16 x = nmin.X; x <= nmax.X; x++) { if (vm->m_data[i].getContent() == dp.c_cobble) { float wetness = NoisePerlin3D(&dp.np_wetness, x, y, z, mg->seed); float density = NoisePerlin3D(&dp.np_density, x, y, z, blockseed); if (density < wetness / dp.mossratio) vm->m_data[i].setContent(dp.c_moss); } i++; } } } //printf("== gen dungeons: %dms\n", t.stop()); }
int MapgenV5::getGroundLevelAtPoint(v2s16 p) { //TimeTaker t("getGroundLevelAtPoint", NULL, PRECISION_MICRO); float f = 0.55 + NoisePerlin2D(&noise_factor->np, p.X, p.Y, seed); if (f < 0.01) f = 0.01; else if (f >= 1.0) f *= 1.6; float h = NoisePerlin2D(&noise_height->np, p.X, p.Y, seed); s16 search_top = water_level + 15; s16 search_base = water_level; s16 level = -31000; for (s16 y = search_top; y >= search_base; y--) { float n_ground = NoisePerlin3D(&noise_ground->np, p.X, y, p.Y, seed); if (n_ground * f > y - h) { if (y >= search_top - 7) break; else level = y; break; } } //printf("getGroundLevelAtPoint: %dus\n", t.stop()); return level; }
int MapgenV5::getSpawnLevelAtPoint(v2s16 p) { //TimeTaker t("getGroundLevelAtPoint", NULL, PRECISION_MICRO); float f = 0.55 + NoisePerlin2D(&noise_factor->np, p.X, p.Y, seed); if (f < 0.01) f = 0.01; else if (f >= 1.0) f *= 1.6; float h = NoisePerlin2D(&noise_height->np, p.X, p.Y, seed); for (s16 y = 128; y >= -128; y--) { float n_ground = NoisePerlin3D(&noise_ground->np, p.X, y, p.Y, seed); if (n_ground * f > y - h) { // If solid // If either top 2 nodes of search are solid this is inside a // mountain or floatland with possibly no space for the player to spawn. if (y >= 127) { return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point } else { // Ground below at least 2 nodes of empty space if (y <= water_level || y > water_level + 16) return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point else return y; } } } //printf("getGroundLevelAtPoint: %dus\n", t.stop()); return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn position, no ground found }
void OreScatter::generate(ManualMapVoxelManipulator *vm, int seed, u32 blockseed, v3s16 nmin, v3s16 nmax) { PseudoRandom pr(blockseed); MapNode n_ore(ore, 0, ore_param2); int volume = (nmax.X - nmin.X + 1) * (nmax.Y - nmin.Y + 1) * (nmax.Z - nmin.Z + 1); int csize = clust_size; int orechance = (csize * csize * csize) / clust_num_ores; int nclusters = volume / clust_scarcity; for (int i = 0; i != nclusters; i++) { int x0 = pr.range(nmin.X, nmax.X - csize + 1); int y0 = pr.range(nmin.Y, nmax.Y - csize + 1); int z0 = pr.range(nmin.Z, nmax.Z - csize + 1); if (np && (NoisePerlin3D(np, x0, y0, z0, seed) < nthresh)) continue; for (int z1 = 0; z1 != csize; z1++) for (int y1 = 0; y1 != csize; y1++) for (int x1 = 0; x1 != csize; x1++) { if (pr.range(1, orechance) != 1) continue; u32 i = vm->m_area.index(x0 + x1, y0 + y1, z0 + z1); for (size_t ii = 0; ii < wherein.size(); ii++) if (vm->m_data[i].getContent() == wherein[ii]) vm->m_data[i] = n_ore; } } }
int MapgenV5::getGroundLevelAtPoint(v2s16 p) { //TimeTaker t("getGroundLevelAtPoint", NULL, PRECISION_MICRO); float f = 0.55 + NoisePerlin2D(&noise_factor->np, p.X, p.Y, seed); if (f < 0.01) f = 0.01; else if (f >= 1.0) f *= 1.6; float h = NoisePerlin2D(&noise_height->np, p.X, p.Y, seed); s16 search_start = 128; // Only bother searching this range, actual s16 search_end = -128; // ground level is rarely higher or lower. for (s16 y = search_start; y >= search_end; y--) { float n_ground = NoisePerlin3D(&noise_ground->np, p.X, y, p.Y, seed); // If solid if (n_ground * f > y - h) { // If either top 2 nodes of search are solid this is inside a // mountain or floatland with no space for the player to spawn. if (y >= search_start - 1) return MAX_MAP_GENERATION_LIMIT; else return y; // Ground below at least 2 nodes of space } } //printf("getGroundLevelAtPoint: %dus\n", t.stop()); return -MAX_MAP_GENERATION_LIMIT; }
bool MapgenV7::getMountainTerrainAtPoint(int x, int y, int z) { float mnt_h_n = NoisePerlin2D(&noise_mount_height->np, x, z, seed); float height_modifier = -((float)y / rangelim(mnt_h_n, 80.0, 150.0)); float mnt_n = NoisePerlin3D(&noise_mountain->np, x, y, z, seed); return mnt_n + height_modifier >= 0.6; }
int MapgenV5::getSpawnLevelAtPoint(v2s16 p) { float f = 0.55 + NoisePerlin2D(&noise_factor->np, p.X, p.Y, seed); if (f < 0.01) f = 0.01; else if (f >= 1.0) f *= 1.6; float h = NoisePerlin2D(&noise_height->np, p.X, p.Y, seed); // noise_height 'offset' is the average level of terrain. At least 50% of // terrain will be below this. // Raising the maximum spawn level above 'water_level + 16' is necessary // for when noise_height 'offset' is set much higher than water_level. s16 max_spawn_y = MYMAX(noise_height->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_ground = NoisePerlin3D(&noise_ground->np, p.X, y, p.Y, seed); if (n_ground * f > y - h) { // If solid if (y < water_level || y > max_spawn_y) return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point // 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; }
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_n = NoisePerlin3D(&noise_mountain->np, x, y, z, seed); return mnt_n + density_gradient >= 0.0; }
int LuaPerlinNoise::l_get3d(lua_State *L) { NO_MAP_LOCK_REQUIRED; LuaPerlinNoise *o = checkobject(L, 1); v3f p = check_v3f(L, 2); lua_Number val = NoisePerlin3D(&o->np, p.X, p.Y, p.Z, 0); lua_pushnumber(L, val); return 1; }
void TestNoise::testNoise3dPoint() { NoiseParams np_normal(20, 40, v3f(50, 50, 50), 9, 5, 0.6, 2.0); u32 i = 0; for (u32 z = 0; z != 10; z++) for (u32 y = 0; y != 10; y++) for (u32 x = 0; x != 10; x++, i++) { float actual = NoisePerlin3D(&np_normal, x, y, z, 1337); float expected = expected_3d_results[i]; UASSERT(fabs(actual - expected) <= 0.00001); } }
float MapgenCarpathian::terrainLevelAtPoint(s16 x, s16 z) { float ground = NoisePerlin2D(&noise_base->np, x, z, seed); 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; for (s16 y = 1; y <= 30; y++) { float mnt_var = NoisePerlin3D(&noise_mnt_var->np, x, y, z, seed); // Gradient & shallow seabed s32 grad = (y < water_level) ? grad_wl + (water_level - y) * 3 : 1 - y; // Hill/Mountain height (hilliness) 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 * pow(n_hills, 2.f); float hills = pow(hter, 3.f) * hill_mnt; // Ridged mountains float ridge_mnt = hilliness * (1.f - fabs(n_ridge_mnt)); float ridged_mountains = pow(rter, 3.f) * ridge_mnt; // Step (terraced) mountains float step_mnt = hilliness * getSteps(n_step_mnt); float step_mountains = pow(ster, 3.f) * step_mnt; // Final terrain level float mountains = hills + ridged_mountains + step_mountains; float surface_level = ground + mountains + grad; if (y > surface_level && height < 0) height = y; } return height; }
// 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); s16 y_start = myround(mount); for (s16 y = y_start; y <= y_start + 1000; y++) { float fill = NoisePerlin3D(&noise_inter_valley_fill->np, tn->x, y, tn->z, seed); if (fill * *tn->slope <= y - mount) { mount = MYMAX(y - 1, mount); break; } } return mount; }
void OreScatter::generate(MMVManip *vm, int mapseed, u32 blockseed, v3s16 nmin, v3s16 nmax, u8 *biomemap) { PcgRandom pr(blockseed); MapNode n_ore(c_ore, 0, ore_param2); u32 sizex = (nmax.X - nmin.X + 1); u32 volume = (nmax.X - nmin.X + 1) * (nmax.Y - nmin.Y + 1) * (nmax.Z - nmin.Z + 1); u32 csize = clust_size; u32 cvolume = csize * csize * csize; u32 nclusters = volume / clust_scarcity; if (clust_scarcity > volume && 1 >= pr.range(0, clust_scarcity/volume)) nclusters = 1; for (u32 i = 0; i != nclusters; i++) { int x0 = pr.range(nmin.X, nmax.X - csize + 1); int y0 = pr.range(nmin.Y, nmax.Y - csize + 1); int z0 = pr.range(nmin.Z, nmax.Z - csize + 1); if ((flags & OREFLAG_USE_NOISE) && (NoisePerlin3D(&np, x0, y0, z0, mapseed) < nthresh)) continue; if (biomemap && !biomes.empty()) { u32 index = sizex * (z0 - nmin.Z) + (x0 - nmin.X); std::set<u8>::iterator it = biomes.find(biomemap[index]); if (it == biomes.end()) continue; } for (u32 z1 = 0; z1 != csize; z1++) for (u32 y1 = 0; y1 != csize; y1++) for (u32 x1 = 0; x1 != csize; x1++) { if (pr.range(1, cvolume) > clust_num_ores) continue; u32 i = vm->m_area.index(x0 + x1, y0 + y1, z0 + z1); if (!CONTAINS(c_wherein, vm->m_data[i].getContent())) continue; vm->m_data[i] = n_ore; } } }
// 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); if (!fast_terrain) { for (s16 y = round(mount); y <= round(mount) + 1000; y++) { float fill = NoisePerlin3D(&noise_inter_valley_fill->np, tn->x, y, tn->z, seed); if (fill * *tn->slope <= y - mount) { mount = fmax(y - 1, mount); break; } } } return mount; }
int MapgenV7::getGroundLevelAtPoint(v2s16 p) { s16 groundlevel = baseTerrainLevelAtPoint(p.X, p.Y); float heat = NoisePerlin2D(bmgr->np_heat, p.X, p.Y, seed); float humidity = NoisePerlin2D(bmgr->np_humidity, p.X, p.Y, seed); Biome *b = bmgr->getBiome(heat, humidity, groundlevel); s16 y = groundlevel; if (y > water_level) { int iters = 1024; // don't even bother iterating more than 1024 times.. while (iters--) { float ridgenoise = NoisePerlin3D(noise_ridge->np, p.X, y, p.Y, seed); if (ridgenoise * (float)(y * y) < 15.0) break; y--; } } return y + b->top_depth; }
void OreScatter::generate(MMVManip *vm, int mapseed, u32 blockseed, v3s16 nmin, v3s16 nmax) { PseudoRandom pr(blockseed); MapNode n_ore(c_ore, 0, ore_param2); int volume = (nmax.X - nmin.X + 1) * (nmax.Y - nmin.Y + 1) * (nmax.Z - nmin.Z + 1); int csize = clust_size; int orechance = (csize * csize * csize) / clust_num_ores; int nclusters = volume / clust_scarcity; for (int i = 0; i != nclusters; i++) { int x0 = pr.range(nmin.X, nmax.X - csize + 1); int y0 = pr.range(nmin.Y, nmax.Y - csize + 1); int z0 = pr.range(nmin.Z, nmax.Z - csize + 1); if ((flags & OREFLAG_USE_NOISE) && (NoisePerlin3D(&np, x0, y0, z0, mapseed) < nthresh)) continue; for (int z1 = 0; z1 != csize; z1++) for (int y1 = 0; y1 != csize; y1++) for (int x1 = 0; x1 != csize; x1++) { if (pr.range(1, orechance) != 1) continue; u32 i = vm->m_area.index(x0 + x1, y0 + y1, z0 + z1); if (!CONTAINS(c_wherein, vm->m_data[i].getContent())) continue; vm->m_data[i] = n_ore; } } }
void CaveFractal::carveRoute(v3f vec, float f, bool randomize_xz) { MapNode airnode(CONTENT_AIR); MapNode waternode(c_water_source); MapNode lavanode(c_lava_source); v3s16 startp(orp.X, orp.Y, orp.Z); startp += of; float nval = NoisePerlin3D(np_caveliquids, startp.X, startp.Y, startp.Z, mg->seed); MapNode liquidnode = (nval < 0.40 && node_max.Y < MGFRACTAL_LAVA_DEPTH) ? lavanode : waternode; v3f fp = orp + vec * f; fp.X += 0.1 * ps->range(-10, 10); fp.Z += 0.1 * ps->range(-10, 10); v3s16 cp(fp.X, fp.Y, fp.Z); s16 d0 = -rs/2; s16 d1 = d0 + rs; if (randomize_xz) { d0 += ps->range(-1, 1); d1 += ps->range(-1, 1); } for (s16 z0 = d0; z0 <= d1; z0++) { s16 si = rs / 2 - MYMAX(0, abs(z0) - rs / 7 - 1); for (s16 x0 = -si - ps->range(0,1); x0 <= si - 1 + ps->range(0,1); x0++) { s16 maxabsxz = MYMAX(abs(x0), abs(z0)); s16 si2 = rs / 2 - MYMAX(0, maxabsxz - rs / 7 - 1); for (s16 y0 = -si2; y0 <= si2; y0++) { if (large_cave_is_flat) { // Make large caves not so tall if (rs > 7 && abs(y0) >= rs / 3) continue; } v3s16 p(cp.X + x0, cp.Y + y0, cp.Z + z0); p += of; if (vm->m_area.contains(p) == false) continue; u32 i = vm->m_area.index(p); content_t c = vm->m_data[i].getContent(); if (!ndef->get(c).is_ground_content) continue; int full_ymin = node_min.Y - MAP_BLOCKSIZE; int full_ymax = node_max.Y + MAP_BLOCKSIZE; if (flooded && full_ymin < water_level && full_ymax > water_level) vm->m_data[i] = (p.Y <= water_level) ? waternode : airnode; else if (flooded && full_ymax < water_level) vm->m_data[i] = (p.Y < startp.Y - 4) ? liquidnode : airnode; else vm->m_data[i] = airnode; } } } }
void CaveV5::carveRoute(v3f vec, float f, bool randomize_xz) { MapNode airnode(CONTENT_AIR); MapNode waternode(c_water_source); MapNode lavanode(c_lava_source); MapNode n_ice(c_ice); v3s16 startp(orp.X, orp.Y, orp.Z); startp += of; float nval = NoisePerlin3D(np_caveliquids, startp.X, startp.Y, startp.Z, mg->seed); //MapNode liquidnode = nval < 0.40 ? lavanode : waternode; v3f fp = orp + vec * f; fp.X += 0.1 * ps->range(-10, 10); fp.Z += 0.1 * ps->range(-10, 10); v3s16 cp(fp.X, fp.Y, fp.Z); s16 d0 = -rs/2; s16 d1 = d0 + rs; if (randomize_xz) { d0 += ps->range(-1, 1); d1 += ps->range(-1, 1); } for (s16 z0 = d0; z0 <= d1; z0++) { s16 si = rs / 2 - MYMAX(0, abs(z0) - rs / 7 - 1); for (s16 x0 = -si - ps->range(0,1); x0 <= si - 1 + ps->range(0,1); x0++) { s16 maxabsxz = MYMAX(abs(x0), abs(z0)); s16 si2 = rs / 2 - MYMAX(0, maxabsxz - rs / 7 - 1); for (s16 y0 = -si2; y0 <= si2; y0++) { if (large_cave_is_flat) { // Make large caves not so tall if (rs > 7 && abs(y0) >= rs / 3) continue; } v3s16 p(cp.X + x0, cp.Y + y0, cp.Z + z0); p += of; if (vm->m_area.contains(p) == false) continue; u32 i = vm->m_area.index(p); content_t c = vm->m_data[i].getContent(); if (!ndef->get(c).is_ground_content) continue; s16 heat = mg->m_emerge->env->m_use_weather ? mg->m_emerge->env->getServerMap().updateBlockHeat(mg->m_emerge->env, p, nullptr, &mg->heat_cache) : 0; MapNode n_water_or_ice = (heat < 0 && (p.Y > water_level + heat/4 || p.Y > startp.Y - 2 + heat/4)) ? n_ice : waternode; MapNode liquidnode = nval < 0.40 ? lavanode : n_water_or_ice; int full_ymin = node_min.Y - MAP_BLOCKSIZE; int full_ymax = node_max.Y + MAP_BLOCKSIZE; if (flooded && full_ymin < water_level && full_ymax > water_level) vm->m_data[i] = (p.Y <= water_level) ? n_water_or_ice : airnode; else if (flooded && full_ymax < water_level) vm->m_data[i] = (p.Y < startp.Y - 4) ? liquidnode : airnode; else vm->m_data[i] = airnode; } } } }
bool MapgenV7::getMountainTerrainAtPoint(int x, int y, int z) { float mnt_h_n = NoisePerlin2D(&noise_mount_height->np, x, z, seed); float mnt_n = NoisePerlin3D(&noise_mountain->np, x, y, z, seed); return mnt_n * mnt_h_n >= (float)y; }
void CaveV7::carveRoute(v3f vec, float f, bool randomize_xz, bool is_ravine) { MapNode airnode(CONTENT_AIR); MapNode waternode(c_water_source); MapNode lavanode(c_lava_source); v3s16 startp(orp.X, orp.Y, orp.Z); startp += of; float nval = NoisePerlin3D(np_caveliquids, startp.X, startp.Y, startp.Z, mg->seed); MapNode liquidnode = (nval < 0.40 && node_max.Y < -256) ? lavanode : waternode; v3f fp = orp + vec * f; fp.X += 0.1 * ps->range(-10, 10); fp.Z += 0.1 * ps->range(-10, 10); v3s16 cp(fp.X, fp.Y, fp.Z); s16 d0 = -rs/2; s16 d1 = d0 + rs; if (randomize_xz) { d0 += ps->range(-1, 1); d1 += ps->range(-1, 1); } bool should_make_cave_hole = ps->range(1, 10) == 1; for (s16 z0 = d0; z0 <= d1; z0++) { s16 si = rs / 2 - MYMAX(0, abs(z0) - rs / 7 - 1); for (s16 x0 = -si - ps->range(0,1); x0 <= si - 1 + ps->range(0,1); x0++) { s16 maxabsxz = MYMAX(abs(x0), abs(z0)); s16 si2 = is_ravine ? MYMIN(ps->range(25, 26), ar.Y) : rs / 2 - MYMAX(0, maxabsxz - rs / 7 - 1); for (s16 y0 = -si2; y0 <= si2; y0++) { if (large_cave_is_flat) { // Make large caves not so tall if (rs > 7 && abs(y0) >= rs / 3) continue; } v3s16 p(cp.X + x0, cp.Y + y0, cp.Z + z0); p += of; if (!is_ravine && mg->heightmap && should_make_cave_hole && p.X <= node_max.X && p.Z <= node_max.Z) { int maplen = node_max.X - node_min.X + 1; int idx = (p.Z - node_min.Z) * maplen + (p.X - node_min.X); if (p.Y >= mg->heightmap[idx] - 2) continue; } if (vm->m_area.contains(p) == false) continue; u32 i = vm->m_area.index(p); content_t c = vm->m_data[i].getContent(); if (!ndef->get(c).is_ground_content) continue; int full_ymin = node_min.Y - MAP_BLOCKSIZE; int full_ymax = node_max.Y + MAP_BLOCKSIZE; if (flooded && full_ymin < water_level && full_ymax > water_level) vm->m_data[i] = (p.Y <= water_level) ? waternode : airnode; else if (flooded && full_ymax < water_level) vm->m_data[i] = (p.Y < startp.Y - 4) ? liquidnode : airnode; else vm->m_data[i] = airnode; } } } }