diff options
Diffstat (limited to 'src/mapgen')
29 files changed, 3540 insertions, 3376 deletions
diff --git a/src/mapgen/cavegen.cpp b/src/mapgen/cavegen.cpp index a51476135..340079821 100644 --- a/src/mapgen/cavegen.cpp +++ b/src/mapgen/cavegen.cpp @@ -32,13 +32,14 @@ with this program; if not, write to the Free Software Foundation, Inc., // 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); + //// //// CavesNoiseIntersection //// -CavesNoiseIntersection::CavesNoiseIntersection(const NodeDefManager *nodedef, - BiomeManager *biomemgr, v3s16 chunksize, NoiseParams *np_cave1, - NoiseParams *np_cave2, s32 seed, float cave_width) +CavesNoiseIntersection::CavesNoiseIntersection( + const NodeDefManager *nodedef, BiomeManager *biomemgr, v3s16 chunksize, + NoiseParams *np_cave1, NoiseParams *np_cave2, s32 seed, float cave_width) { assert(nodedef); assert(biomemgr); @@ -49,7 +50,7 @@ CavesNoiseIntersection::CavesNoiseIntersection(const NodeDefManager *nodedef, m_csize = chunksize; m_cave_width = cave_width; - m_ystride = m_csize.X; + m_ystride = m_csize.X; m_zstride_1d = m_csize.X * (m_csize.Y + 1); // Noises are created using 1-down overgeneration @@ -59,14 +60,16 @@ CavesNoiseIntersection::CavesNoiseIntersection(const NodeDefManager *nodedef, noise_cave2 = new Noise(np_cave2, seed, m_csize.X, m_csize.Y + 1, m_csize.Z); } + CavesNoiseIntersection::~CavesNoiseIntersection() { delete noise_cave1; delete noise_cave2; } -void CavesNoiseIntersection::generateCaves( - MMVManip *vm, v3s16 nmin, v3s16 nmax, biome_t *biomemap) + +void CavesNoiseIntersection::generateCaves(MMVManip *vm, + v3s16 nmin, v3s16 nmax, biome_t *biomemap) { assert(vm); assert(biomemap); @@ -75,120 +78,114 @@ void CavesNoiseIntersection::generateCaves( noise_cave2->perlinMap3D(nmin.X, nmin.Y - 1, nmin.Z); const v3s16 &em = vm->m_area.getExtent(); - u32 index2d = 0; // Biomemap index + u32 index2d = 0; // Biomemap index for (s16 z = nmin.Z; z <= nmax.Z; z++) - for (s16 x = nmin.X; x <= nmax.X; x++, index2d++) { - bool column_is_open = false; // Is column open to overground - bool is_under_river = false; // Is column under river water - bool is_under_tunnel = false; // Is tunnel or is under tunnel - bool is_top_filler_above = false; // Is top or filler above node - // Indexes at column top - u32 vi = vm->m_area.index(x, nmax.Y, z); - u32 index3d = (z - nmin.Z) * m_zstride_1d + - m_csize.Y * m_ystride + - (x - nmin.X); // 3D noise index - // Biome of column - Biome *biome = (Biome *)m_bmgr->getRaw(biomemap[index2d]); - u16 depth_top = biome->depth_top; - u16 base_filler = depth_top + biome->depth_filler; - u16 depth_riverbed = biome->depth_riverbed; - u16 nplaced = 0; - // Don't excavate the overgenerated stone at nmax.Y + 1, - // this creates a 'roof' over the tunnel, preventing light in - // tunnels at mapchunk borders when generating mapchunks upwards. - // This 'roof' is removed when the mapchunk above is generated. - for (s16 y = nmax.Y; y >= nmin.Y - 1; y--, index3d -= m_ystride, - VoxelArea::add_y(em, vi, -1)) { - content_t c = vm->m_data[vi].getContent(); - - if (c == CONTENT_AIR || c == biome->c_water_top || - c == biome->c_water) { - column_is_open = true; - is_top_filler_above = false; - continue; - } - - if (c == biome->c_river_water) { - column_is_open = true; - is_under_river = true; - is_top_filler_above = false; - continue; - } + for (s16 x = nmin.X; x <= nmax.X; x++, index2d++) { + bool column_is_open = false; // Is column open to overground + bool is_under_river = false; // Is column under river water + bool is_under_tunnel = false; // Is tunnel or is under tunnel + bool is_top_filler_above = false; // Is top or filler above node + // Indexes at column top + u32 vi = vm->m_area.index(x, nmax.Y, z); + u32 index3d = (z - nmin.Z) * m_zstride_1d + m_csize.Y * m_ystride + + (x - nmin.X); // 3D noise index + // Biome of column + Biome *biome = (Biome *)m_bmgr->getRaw(biomemap[index2d]); + u16 depth_top = biome->depth_top; + u16 base_filler = depth_top + biome->depth_filler; + u16 depth_riverbed = biome->depth_riverbed; + u16 nplaced = 0; + // Don't excavate the overgenerated stone at nmax.Y + 1, + // this creates a 'roof' over the tunnel, preventing light in + // tunnels at mapchunk borders when generating mapchunks upwards. + // This 'roof' is removed when the mapchunk above is generated. + for (s16 y = nmax.Y; y >= nmin.Y - 1; y--, + index3d -= m_ystride, + VoxelArea::add_y(em, vi, -1)) { + content_t c = vm->m_data[vi].getContent(); + + if (c == CONTENT_AIR || c == biome->c_water_top || + c == biome->c_water) { + column_is_open = true; + is_top_filler_above = false; + continue; + } - // Ground - float d1 = contour(noise_cave1->result[index3d]); - float d2 = contour(noise_cave2->result[index3d]); + if (c == biome->c_river_water) { + column_is_open = true; + is_under_river = true; + is_top_filler_above = false; + continue; + } - if (d1 * d2 > m_cave_width && - m_ndef->get(c).is_ground_content) { - // In tunnel and ground content, excavate - vm->m_data[vi] = MapNode(CONTENT_AIR); - is_under_tunnel = true; - // If tunnel roof is top or filler, replace with - // stone - if (is_top_filler_above) - vm->m_data[vi + em.X] = - MapNode(biome->c_stone); - is_top_filler_above = false; - } else if (column_is_open && is_under_tunnel && - (c == biome->c_stone || - c == biome->c_filler)) { - // Tunnel entrance floor, place biome surface - // nodes - if (is_under_river) { - if (nplaced < depth_riverbed) { - vm->m_data[vi] = MapNode( - biome->c_riverbed); - is_top_filler_above = true; - nplaced++; - } else { - // Disable top/filler placement - column_is_open = false; - is_under_river = false; - is_under_tunnel = false; - } - } else if (nplaced < depth_top) { - vm->m_data[vi] = MapNode(biome->c_top); - is_top_filler_above = true; - nplaced++; - } else if (nplaced < base_filler) { - vm->m_data[vi] = MapNode(biome->c_filler); + // Ground + float d1 = contour(noise_cave1->result[index3d]); + float d2 = contour(noise_cave2->result[index3d]); + + if (d1 * d2 > m_cave_width && m_ndef->get(c).is_ground_content) { + // In tunnel and ground content, excavate + vm->m_data[vi] = MapNode(CONTENT_AIR); + is_under_tunnel = true; + // If tunnel roof is top or filler, replace with stone + if (is_top_filler_above) + vm->m_data[vi + em.X] = MapNode(biome->c_stone); + is_top_filler_above = false; + } else if (column_is_open && is_under_tunnel && + (c == biome->c_stone || c == biome->c_filler)) { + // Tunnel entrance floor, place biome surface nodes + if (is_under_river) { + if (nplaced < depth_riverbed) { + vm->m_data[vi] = MapNode(biome->c_riverbed); is_top_filler_above = true; nplaced++; } else { // Disable top/filler placement column_is_open = false; + is_under_river = false; is_under_tunnel = false; } + } else if (nplaced < depth_top) { + vm->m_data[vi] = MapNode(biome->c_top); + is_top_filler_above = true; + nplaced++; + } else if (nplaced < base_filler) { + vm->m_data[vi] = MapNode(biome->c_filler); + is_top_filler_above = true; + nplaced++; } else { - // Not tunnel or tunnel entrance floor - // Check node for possible replacing with stone - // for tunnel roof - if (c == biome->c_top || c == biome->c_filler) - is_top_filler_above = true; - + // Disable top/filler placement column_is_open = false; + is_under_tunnel = false; } + } else { + // Not tunnel or tunnel entrance floor + // Check node for possible replacing with stone for tunnel roof + if (c == biome->c_top || c == biome->c_filler) + is_top_filler_above = true; + + column_is_open = false; } } + } } + //// //// CavernsNoise //// -CavernsNoise::CavernsNoise(const NodeDefManager *nodedef, v3s16 chunksize, - NoiseParams *np_cavern, s32 seed, float cavern_limit, float cavern_taper, - float cavern_threshold) +CavernsNoise::CavernsNoise( + const NodeDefManager *nodedef, v3s16 chunksize, NoiseParams *np_cavern, + s32 seed, float cavern_limit, float cavern_taper, float cavern_threshold) { assert(nodedef); - m_ndef = nodedef; + m_ndef = nodedef; - m_csize = chunksize; - m_cavern_limit = cavern_limit; - m_cavern_taper = cavern_taper; + m_csize = chunksize; + m_cavern_limit = cavern_limit; + m_cavern_taper = cavern_taper; m_cavern_threshold = cavern_threshold; m_ystride = m_csize.X; @@ -208,11 +205,13 @@ CavernsNoise::CavernsNoise(const NodeDefManager *nodedef, v3s16 chunksize, c_lava_source = CONTENT_AIR; } + CavernsNoise::~CavernsNoise() { delete noise_cavern; } + bool CavernsNoise::generateCaverns(MMVManip *vm, v3s16 nmin, v3s16 nmax) { assert(vm); @@ -222,10 +221,10 @@ bool CavernsNoise::generateCaverns(MMVManip *vm, v3s16 nmin, v3s16 nmax) // Cache cavern_amp values float *cavern_amp = new float[m_csize.Y + 1]; - u8 cavern_amp_index = 0; // Index zero at column top + u8 cavern_amp_index = 0; // Index zero at column top for (s16 y = nmax.Y; y >= nmin.Y - 1; y--, cavern_amp_index++) { cavern_amp[cavern_amp_index] = - MYMIN((m_cavern_limit - y) / (float)m_cavern_taper, 1.0f); + MYMIN((m_cavern_limit - y) / (float)m_cavern_taper, 1.0f); } //// Place nodes @@ -234,57 +233,65 @@ bool CavernsNoise::generateCaverns(MMVManip *vm, v3s16 nmin, v3s16 nmax) u32 index2d = 0; for (s16 z = nmin.Z; z <= nmax.Z; z++) - for (s16 x = nmin.X; x <= nmax.X; x++, index2d++) { - // Reset cave_amp index to column top - cavern_amp_index = 0; - // Initial voxelmanip index at column top - u32 vi = vm->m_area.index(x, nmax.Y, z); - // Initial 3D noise index at column top - u32 index3d = (z - nmin.Z) * m_zstride_1d + - m_csize.Y * m_ystride + (x - nmin.X); - // Don't excavate the overgenerated stone at node_max.Y + 1, - // this creates a 'roof' over the cavern, preventing light in - // caverns at mapchunk borders when generating mapchunks upwards. - // This 'roof' is excavated when the mapchunk above is generated. - for (s16 y = nmax.Y; y >= nmin.Y - 1; y--, index3d -= m_ystride, - VoxelArea::add_y(em, vi, -1), cavern_amp_index++) { - content_t c = vm->m_data[vi].getContent(); - float n_absamp_cavern = - std::fabs(noise_cavern->result[index3d]) * - cavern_amp[cavern_amp_index]; - // Disable CavesRandomWalk at a safe distance from caverns - // to avoid excessively spreading liquids in caverns. - if (n_absamp_cavern > m_cavern_threshold - 0.1f) { - near_cavern = true; - if (n_absamp_cavern > m_cavern_threshold && - m_ndef->get(c).is_ground_content) - vm->m_data[vi] = MapNode(CONTENT_AIR); - } + for (s16 x = nmin.X; x <= nmax.X; x++, index2d++) { + // Reset cave_amp index to column top + cavern_amp_index = 0; + // Initial voxelmanip index at column top + u32 vi = vm->m_area.index(x, nmax.Y, z); + // Initial 3D noise index at column top + u32 index3d = (z - nmin.Z) * m_zstride_1d + m_csize.Y * m_ystride + + (x - nmin.X); + // Don't excavate the overgenerated stone at node_max.Y + 1, + // this creates a 'roof' over the cavern, preventing light in + // caverns at mapchunk borders when generating mapchunks upwards. + // This 'roof' is excavated when the mapchunk above is generated. + for (s16 y = nmax.Y; y >= nmin.Y - 1; y--, + index3d -= m_ystride, + VoxelArea::add_y(em, vi, -1), + cavern_amp_index++) { + content_t c = vm->m_data[vi].getContent(); + float n_absamp_cavern = std::fabs(noise_cavern->result[index3d]) * + cavern_amp[cavern_amp_index]; + // Disable CavesRandomWalk at a safe distance from caverns + // to avoid excessively spreading liquids in caverns. + if (n_absamp_cavern > m_cavern_threshold - 0.1f) { + near_cavern = true; + if (n_absamp_cavern > m_cavern_threshold && + m_ndef->get(c).is_ground_content) + vm->m_data[vi] = MapNode(CONTENT_AIR); } } + } delete[] cavern_amp; return near_cavern; } + //// //// CavesRandomWalk //// -CavesRandomWalk::CavesRandomWalk(const NodeDefManager *ndef, GenerateNotifier *gennotify, - s32 seed, int water_level, content_t water_source, content_t lava_source, - float large_cave_flooded, BiomeGen *biomegen) +CavesRandomWalk::CavesRandomWalk( + const NodeDefManager *ndef, + GenerateNotifier *gennotify, + s32 seed, + int water_level, + content_t water_source, + content_t lava_source, + float large_cave_flooded, + BiomeGen *biomegen) { assert(ndef); - this->ndef = ndef; - this->gennotify = gennotify; - this->seed = seed; - this->water_level = water_level; - this->np_caveliquids = &nparams_caveliquids; + this->ndef = ndef; + this->gennotify = gennotify; + this->seed = seed; + this->water_level = water_level; + this->np_caveliquids = &nparams_caveliquids; this->large_cave_flooded = large_cave_flooded; - this->bmgn = biomegen; + this->bmgn = biomegen; c_water_source = water_source; if (c_water_source == CONTENT_IGNORE) @@ -299,17 +306,18 @@ CavesRandomWalk::CavesRandomWalk(const NodeDefManager *ndef, GenerateNotifier *g c_lava_source = CONTENT_AIR; } -void CavesRandomWalk::makeCave(MMVManip *vm, v3s16 nmin, v3s16 nmax, PseudoRandom *ps, - bool is_large_cave, int max_stone_height, s16 *heightmap) + +void CavesRandomWalk::makeCave(MMVManip *vm, v3s16 nmin, v3s16 nmax, + PseudoRandom *ps, bool is_large_cave, int max_stone_height, s16 *heightmap) { assert(vm); assert(ps); - this->vm = vm; - this->ps = ps; - this->node_min = nmin; - this->node_max = nmax; - this->heightmap = heightmap; + this->vm = vm; + this->ps = ps; + this->node_min = nmin; + this->node_max = nmax; + this->heightmap = heightmap; this->large_cave = is_large_cave; this->ystride = nmax.X - nmin.X + 1; @@ -325,8 +333,8 @@ void CavesRandomWalk::makeCave(MMVManip *vm, v3s16 nmin, v3s16 nmax, PseudoRando 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)]; + c_biome_liquid = + biome->c_cave_liquid[ps->range(0, biome->c_cave_liquid.size() - 1)]; if (c_biome_liquid == CONTENT_AIR) flooded = false; } @@ -395,8 +403,8 @@ void CavesRandomWalk::makeCave(MMVManip *vm, v3s16 nmin, v3s16 nmax, PseudoRando // Add generation notify begin event if (gennotify) { v3s16 abs_pos(of.X + orp.X, of.Y + orp.Y, of.Z + orp.Z); - GenNotifyType notifytype = large_cave ? GENNOTIFY_LARGECAVE_BEGIN - : GENNOTIFY_CAVE_BEGIN; + GenNotifyType notifytype = large_cave ? + GENNOTIFY_LARGECAVE_BEGIN : GENNOTIFY_CAVE_BEGIN; gennotify->addEvent(notifytype, abs_pos); } @@ -407,12 +415,13 @@ void CavesRandomWalk::makeCave(MMVManip *vm, v3s16 nmin, v3s16 nmax, PseudoRando // Add generation notify end event if (gennotify) { v3s16 abs_pos(of.X + orp.X, of.Y + orp.Y, of.Z + orp.Z); - GenNotifyType notifytype = - large_cave ? GENNOTIFY_LARGECAVE_END : GENNOTIFY_CAVE_END; + GenNotifyType notifytype = large_cave ? + GENNOTIFY_LARGECAVE_END : GENNOTIFY_CAVE_END; gennotify->addEvent(notifytype, abs_pos); } } + void CavesRandomWalk::makeTunnel(bool dirswitch) { if (dirswitch && !large_cave) { @@ -431,11 +440,17 @@ void CavesRandomWalk::makeTunnel(bool dirswitch) v3s16 maxlen; if (large_cave) { - maxlen = v3s16(rs_part_max_length_rs, rs_part_max_length_rs / 2, - rs_part_max_length_rs); + maxlen = v3s16( + rs_part_max_length_rs, + rs_part_max_length_rs / 2, + rs_part_max_length_rs + ); } else { - maxlen = v3s16(rs_part_max_length_rs, ps->range(1, rs_part_max_length_rs), - rs_part_max_length_rs); + maxlen = v3s16( + rs_part_max_length_rs, + ps->range(1, rs_part_max_length_rs), + rs_part_max_length_rs + ); } v3f vec; @@ -491,6 +506,7 @@ void CavesRandomWalk::makeTunnel(bool dirswitch) orp = rp; } + void CavesRandomWalk::carveRoute(v3f vec, float f, bool randomize_xz) { MapNode airnode(CONTENT_AIR); @@ -512,16 +528,13 @@ void CavesRandomWalk::carveRoute(v3f vec, float f, bool randomize_xz) if (use_biome_liquid) { liquidnode = c_biome_liquid; } else { - // If cave liquid not defined by biome, fallback to old hardcoded - // behaviour. - // TODO 'np_caveliquids' is deprecated and should eventually be - // removed. Cave liquids are now defined and located using biome - // definitions. - float nval = NoisePerlin3D(np_caveliquids, startp.X, startp.Y, - startp.Z, seed); - liquidnode = (nval < 0.40f && node_max.Y < water_level - 256) - ? lavanode - : waternode; + // If cave liquid not defined by biome, fallback to old hardcoded behaviour. + // TODO 'np_caveliquids' is deprecated and should eventually be removed. + // Cave liquids are now defined and located using biome definitions. + float nval = NoisePerlin3D(np_caveliquids, startp.X, + startp.Y, startp.Z, seed); + liquidnode = (nval < 0.40f && node_max.Y < water_level - 256) ? + lavanode : waternode; } } @@ -536,8 +549,7 @@ void CavesRandomWalk::carveRoute(v3f vec, float f, bool randomize_xz) 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++) { + 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); @@ -568,15 +580,10 @@ void CavesRandomWalk::carveRoute(v3f vec, float f, bool randomize_xz) 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; + 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; + vm->m_data[i] = (p.Y < startp.Y - 4) ? liquidnode : airnode; else vm->m_data[i] = airnode; } else { @@ -588,9 +595,11 @@ void CavesRandomWalk::carveRoute(v3f vec, float f, bool randomize_xz) } } + inline bool CavesRandomWalk::isPosAboveSurface(v3s16 p) { - if (heightmap != NULL && p.Z >= node_min.Z && p.Z <= node_max.Z && + if (heightmap != NULL && + p.Z >= node_min.Z && p.Z <= node_max.Z && p.X >= node_min.X && p.X <= node_max.X) { u32 index = (p.Z - node_min.Z) * ystride + (p.X - node_min.X); if (heightmap[index] < p.Y) @@ -602,17 +611,18 @@ inline bool CavesRandomWalk::isPosAboveSurface(v3s16 p) return false; } + //// //// CavesV6 //// -CavesV6::CavesV6(const NodeDefManager *ndef, GenerateNotifier *gennotify, int water_level, - content_t water_source, content_t lava_source) +CavesV6::CavesV6(const NodeDefManager *ndef, GenerateNotifier *gennotify, + int water_level, content_t water_source, content_t lava_source) { assert(ndef); - this->ndef = ndef; - this->gennotify = gennotify; + this->ndef = ndef; + this->gennotify = gennotify; this->water_level = water_level; c_water_source = water_source; @@ -628,20 +638,21 @@ CavesV6::CavesV6(const NodeDefManager *ndef, GenerateNotifier *gennotify, int wa c_lava_source = CONTENT_AIR; } -void CavesV6::makeCave(MMVManip *vm, v3s16 nmin, v3s16 nmax, PseudoRandom *ps, - PseudoRandom *ps2, bool is_large_cave, int max_stone_height, - s16 *heightmap) + +void CavesV6::makeCave(MMVManip *vm, v3s16 nmin, v3s16 nmax, + PseudoRandom *ps, PseudoRandom *ps2, + bool is_large_cave, int max_stone_height, s16 *heightmap) { assert(vm); assert(ps); assert(ps2); - this->vm = vm; - this->ps = ps; - this->ps2 = ps2; - this->node_min = nmin; - this->node_max = nmax; - this->heightmap = heightmap; + this->vm = vm; + this->ps = ps; + this->ps2 = ps2; + this->node_min = nmin; + this->node_max = nmax; + this->heightmap = heightmap; this->large_cave = is_large_cave; this->ystride = nmax.X - nmin.X + 1; @@ -649,10 +660,10 @@ void CavesV6::makeCave(MMVManip *vm, v3s16 nmin, v3s16 nmax, PseudoRandom *ps, // Set initial parameters from randomness min_tunnel_diameter = 2; max_tunnel_diameter = ps->range(2, 6); - int dswitchint = ps->range(1, 14); + int dswitchint = ps->range(1, 14); if (large_cave) { - part_max_length_rs = ps->range(2, 4); - tunnel_routepoints = ps->range(5, ps->range(15, 30)); + part_max_length_rs = ps->range(2, 4); + tunnel_routepoints = ps->range(5, ps->range(15, 30)); min_tunnel_diameter = 5; max_tunnel_diameter = ps->range(7, ps->range(8, 24)); } else { @@ -707,8 +718,8 @@ void CavesV6::makeCave(MMVManip *vm, v3s16 nmin, v3s16 nmax, PseudoRandom *ps, // Add generation notify begin event if (gennotify != NULL) { v3s16 abs_pos(of.X + orp.X, of.Y + orp.Y, of.Z + orp.Z); - GenNotifyType notifytype = large_cave ? GENNOTIFY_LARGECAVE_BEGIN - : GENNOTIFY_CAVE_BEGIN; + GenNotifyType notifytype = large_cave ? + GENNOTIFY_LARGECAVE_BEGIN : GENNOTIFY_CAVE_BEGIN; gennotify->addEvent(notifytype, abs_pos); } @@ -719,12 +730,13 @@ void CavesV6::makeCave(MMVManip *vm, v3s16 nmin, v3s16 nmax, PseudoRandom *ps, // Add generation notify end event if (gennotify != NULL) { v3s16 abs_pos(of.X + orp.X, of.Y + orp.Y, of.Z + orp.Z); - GenNotifyType notifytype = - large_cave ? GENNOTIFY_LARGECAVE_END : GENNOTIFY_CAVE_END; + GenNotifyType notifytype = large_cave ? + GENNOTIFY_LARGECAVE_END : GENNOTIFY_CAVE_END; gennotify->addEvent(notifytype, abs_pos); } } + void CavesV6::makeTunnel(bool dirswitch) { if (dirswitch && !large_cave) { @@ -743,11 +755,17 @@ void CavesV6::makeTunnel(bool dirswitch) v3s16 maxlen; if (large_cave) { - maxlen = v3s16(rs_part_max_length_rs, rs_part_max_length_rs / 2, - rs_part_max_length_rs); + maxlen = v3s16( + rs_part_max_length_rs, + rs_part_max_length_rs / 2, + rs_part_max_length_rs + ); } else { - maxlen = v3s16(rs_part_max_length_rs, ps->range(1, rs_part_max_length_rs), - rs_part_max_length_rs); + maxlen = v3s16( + rs_part_max_length_rs, + ps->range(1, rs_part_max_length_rs), + rs_part_max_length_rs + ); } v3f vec; @@ -771,8 +789,9 @@ void CavesV6::makeTunnel(bool dirswitch) // If startpoint and endpoint are above ground, disable placement of nodes // in carveRoute while still running all PseudoRandom calls to ensure caves // are consistent with existing worlds. - bool tunnel_above_ground = p1.Y > getSurfaceFromHeightmap(p1) && - p2.Y > getSurfaceFromHeightmap(p2); + bool tunnel_above_ground = + p1.Y > getSurfaceFromHeightmap(p1) && + p2.Y > getSurfaceFromHeightmap(p2); vec += main_direction; @@ -809,7 +828,9 @@ void CavesV6::makeTunnel(bool dirswitch) orp = rp; } -void CavesV6::carveRoute(v3f vec, float f, bool randomize_xz, bool tunnel_above_ground) + +void CavesV6::carveRoute(v3f vec, float f, bool randomize_xz, + bool tunnel_above_ground) { MapNode airnode(CONTENT_AIR); MapNode waternode(c_water_source); @@ -832,8 +853,7 @@ void CavesV6::carveRoute(v3f vec, float f, bool randomize_xz, bool tunnel_above_ 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++) { + for (s16 x0 = -si - ps->range(0,1); x0 <= si - 1 + ps->range(0,1); x0++) { if (tunnel_above_ground) continue; @@ -861,15 +881,10 @@ void CavesV6::carveRoute(v3f vec, float f, bool randomize_xz, bool tunnel_above_ int full_ymin = node_min.Y - MAP_BLOCKSIZE; int full_ymax = node_max.Y + MAP_BLOCKSIZE; - if (full_ymin < water_level && - full_ymax > water_level) { - vm->m_data[i] = (p.Y <= water_level) - ? waternode - : airnode; + if (full_ymin < water_level && full_ymax > water_level) { + vm->m_data[i] = (p.Y <= water_level) ? waternode : airnode; } else if (full_ymax < water_level) { - vm->m_data[i] = (p.Y < startp.Y - 2) - ? lavanode - : airnode; + vm->m_data[i] = (p.Y < startp.Y - 2) ? lavanode : airnode; } else { vm->m_data[i] = airnode; } @@ -885,13 +900,16 @@ void CavesV6::carveRoute(v3f vec, float f, bool randomize_xz, bool tunnel_above_ } } + inline s16 CavesV6::getSurfaceFromHeightmap(v3s16 p) { - if (heightmap != NULL && p.Z >= node_min.Z && p.Z <= node_max.Z && + if (heightmap != NULL && + p.Z >= node_min.Z && p.Z <= node_max.Z && p.X >= node_min.X && p.X <= node_max.X) { u32 index = (p.Z - node_min.Z) * ystride + (p.X - node_min.X); return heightmap[index]; } return water_level; + } diff --git a/src/mapgen/cavegen.h b/src/mapgen/cavegen.h index 876c45936..d678d365b 100644 --- a/src/mapgen/cavegen.h +++ b/src/mapgen/cavegen.h @@ -22,7 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define VMANIP_FLAG_CAVE VOXELFLAG_CHECKED1 -typedef u16 biome_t; // copy from mg_biome.h to avoid an unnecessary include +typedef u16 biome_t; // copy from mg_biome.h to avoid an unnecessary include class GenerateNotifier; @@ -41,9 +41,9 @@ class GenerateNotifier; class CavesNoiseIntersection { public: - CavesNoiseIntersection(const NodeDefManager *nodedef, BiomeManager *biomemgr, - v3s16 chunksize, NoiseParams *np_cave1, NoiseParams *np_cave2, - s32 seed, float cave_width); + CavesNoiseIntersection(const NodeDefManager *nodedef, + BiomeManager *biomemgr, v3s16 chunksize, NoiseParams *np_cave1, + NoiseParams *np_cave2, s32 seed, float cave_width); ~CavesNoiseIntersection(); void generateCaves(MMVManip *vm, v3s16 nmin, v3s16 nmax, biome_t *biomemap); @@ -71,8 +71,8 @@ class CavernsNoise { public: CavernsNoise(const NodeDefManager *nodedef, v3s16 chunksize, - NoiseParams *np_cavern, s32 seed, float cavern_limit, - float cavern_taper, float cavern_threshold); + NoiseParams *np_cavern, s32 seed, float cavern_limit, + float cavern_taper, float cavern_threshold); ~CavernsNoise(); bool generateCaverns(MMVManip *vm, v3s16 nmin, v3s16 nmax); @@ -143,7 +143,7 @@ public: v3f orp; // starting point, relative to caved space v3s16 of; // absolute coordinates of caved space v3s16 ar; // allowed route area - s16 rs; // tunnel radius size + s16 rs; // tunnel radius size v3f main_direction; s16 route_y_min; @@ -158,11 +158,10 @@ public: // ndef is a mandatory parameter. // If gennotify is NULL, generation events are not logged. // If biomegen is NULL, cave liquids have classic behaviour. - CavesRandomWalk(const NodeDefManager *ndef, GenerateNotifier *gennotify = NULL, - s32 seed = 0, int water_level = 1, - content_t water_source = CONTENT_IGNORE, - content_t lava_source = CONTENT_IGNORE, - float large_cave_flooded = 0.5f, BiomeGen *biomegen = NULL); + CavesRandomWalk(const NodeDefManager *ndef, GenerateNotifier *gennotify = + NULL, s32 seed = 0, int water_level = 1, content_t water_source = + CONTENT_IGNORE, content_t lava_source = CONTENT_IGNORE, + float large_cave_flooded = 0.5f, BiomeGen *biomegen = NULL); // vm and ps are mandatory parameters. // If heightmap is NULL, the surface level at all points is assumed to @@ -222,7 +221,7 @@ public: v3f orp; // starting point, relative to caved space v3s16 of; // absolute coordinates of caved space v3s16 ar; // allowed route area - s16 rs; // tunnel radius size + s16 rs; // tunnel radius size v3f main_direction; s16 route_y_min; diff --git a/src/mapgen/dungeongen.cpp b/src/mapgen/dungeongen.cpp index 521eb7f7b..acdb1a0f0 100644 --- a/src/mapgen/dungeongen.cpp +++ b/src/mapgen/dungeongen.cpp @@ -31,18 +31,20 @@ with this program; if not, write to the Free Software Foundation, Inc., //#define DGEN_USE_TORCHES + /////////////////////////////////////////////////////////////////////////////// -DungeonGen::DungeonGen(const NodeDefManager *ndef, GenerateNotifier *gennotify, - DungeonParams *dparams) + +DungeonGen::DungeonGen(const NodeDefManager *ndef, + GenerateNotifier *gennotify, DungeonParams *dparams) { assert(ndef); - this->ndef = ndef; + this->ndef = ndef; this->gennotify = gennotify; #ifdef DGEN_USE_TORCHES - c_torch = ndef->getId("default:torch"); + c_torch = ndef->getId("default:torch"); #endif if (dparams) { @@ -51,29 +53,30 @@ DungeonGen::DungeonGen(const NodeDefManager *ndef, GenerateNotifier *gennotify, // Default dungeon parameters dp.seed = 0; - dp.c_wall = ndef->getId("mapgen_cobble"); + dp.c_wall = ndef->getId("mapgen_cobble"); dp.c_alt_wall = ndef->getId("mapgen_mossycobble"); - dp.c_stair = ndef->getId("mapgen_stair_cobble"); - - dp.diagonal_dirs = false; - dp.only_in_ground = true; - dp.holesize = v3s16(1, 2, 1); - dp.corridor_len_min = 1; - dp.corridor_len_max = 13; - dp.room_size_min = v3s16(4, 4, 4); - dp.room_size_max = v3s16(8, 6, 8); + dp.c_stair = ndef->getId("mapgen_stair_cobble"); + + dp.diagonal_dirs = false; + dp.only_in_ground = true; + dp.holesize = v3s16(1, 2, 1); + dp.corridor_len_min = 1; + dp.corridor_len_max = 13; + 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.large_room_chance = 1; - dp.num_rooms = 8; - dp.num_dungeons = 1; - dp.notifytype = GENNOTIFY_DUNGEON; + dp.large_room_chance = 1; + dp.num_rooms = 8; + dp.num_dungeons = 1; + dp.notifytype = GENNOTIFY_DUNGEON; - dp.np_alt_wall = NoiseParams( - -0.4, 1.0, v3f(40.0, 40.0, 40.0), 32474, 6, 1.1, 2.0); + 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) @@ -81,7 +84,7 @@ void DungeonGen::generate(MMVManip *vm, u32 bseed, v3s16 nmin, v3s16 nmax) assert(vm); - // TimeTaker t("gen dungeons"); + //TimeTaker t("gen dungeons"); this->vm = vm; this->blockseed = bseed; @@ -91,13 +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 - // 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()'. + // 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); @@ -105,10 +108,8 @@ 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 || - c == CONTENT_IGNORE || - !ndef->get(c).is_ground_content) - vm->m_flags[i] |= - VMANIP_FLAG_DUNGEON_PRESERVE; + c == CONTENT_IGNORE || !ndef->get(c).is_ground_content) + vm->m_flags[i] |= VMANIP_FLAG_DUNGEON_PRESERVE; i++; } } @@ -124,21 +125,21 @@ void DungeonGen::generate(MMVManip *vm, u32 bseed, v3s16 nmin, v3s16 nmax) 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++; + 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()); + //printf("== gen dungeons: %dms\n", t.stop()); } + void DungeonGen::makeDungeon(v3s16 start_padding) { const v3s16 &areasize = vm->m_area.getExtent(); @@ -151,12 +152,9 @@ void DungeonGen::makeDungeon(v3s16 start_padding) bool fits = false; for (u32 i = 0; i < 100 && !fits; i++) { 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); + 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); @@ -176,18 +174,16 @@ void DungeonGen::makeDungeon(v3s16 start_padding) */ fits = true; for (s16 z = 0; z < roomsize.Z; z++) - for (s16 y = 0; y < roomsize.Y; y++) - for (s16 x = 0; x < roomsize.X; x++) { - v3s16 p = roomplace + v3s16(x, y, z); - u32 vi = vm->m_area.index(p); - if ((vm->m_flags[vi] & - VMANIP_FLAG_DUNGEON_UNTOUCHABLE) || - vm->m_data[vi].getContent() == - CONTENT_IGNORE) { - fits = false; - break; - } - } + for (s16 y = 0; y < roomsize.Y; y++) + for (s16 x = 0; x < roomsize.X; x++) { + v3s16 p = roomplace + v3s16(x, y, z); + u32 vi = vm->m_area.index(p); + if ((vm->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE) || + vm->m_data[vi].getContent() == CONTENT_IGNORE) { + fits = false; + break; + } + } } // No place found if (!fits) @@ -252,15 +248,11 @@ void DungeonGen::makeDungeon(v3s16 start_padding) makeCorridor(doorplace, doordir, corridor_end, corridor_end_dir); // Find a place for a random sized room - if (dp.large_room_chance > 1 && - random.range(1, dp.large_room_chance) == 1) { + 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); + 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); @@ -281,6 +273,7 @@ void DungeonGen::makeDungeon(v3s16 start_padding) } } + void DungeonGen::makeRoom(v3s16 roomsize, v3s16 roomplace) { MapNode n_wall(dp.c_wall); @@ -288,107 +281,112 @@ void DungeonGen::makeRoom(v3s16 roomsize, v3s16 roomplace) // Make +-X walls for (s16 z = 0; z < roomsize.Z; z++) - for (s16 y = 0; y < roomsize.Y; y++) { - { - v3s16 p = roomplace + v3s16(0, y, z); - if (!vm->m_area.contains(p)) - continue; - u32 vi = vm->m_area.index(p); - if (vm->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE) - continue; - vm->m_data[vi] = n_wall; - } - { - v3s16 p = roomplace + v3s16(roomsize.X - 1, y, z); - if (!vm->m_area.contains(p)) - continue; - u32 vi = vm->m_area.index(p); - if (vm->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE) - continue; - vm->m_data[vi] = n_wall; - } + for (s16 y = 0; y < roomsize.Y; y++) { + { + v3s16 p = roomplace + v3s16(0, y, z); + if (!vm->m_area.contains(p)) + continue; + u32 vi = vm->m_area.index(p); + if (vm->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE) + continue; + vm->m_data[vi] = n_wall; + } + { + v3s16 p = roomplace + v3s16(roomsize.X - 1, y, z); + if (!vm->m_area.contains(p)) + continue; + u32 vi = vm->m_area.index(p); + if (vm->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE) + continue; + vm->m_data[vi] = n_wall; } + } // Make +-Z walls for (s16 x = 0; x < roomsize.X; x++) - for (s16 y = 0; y < roomsize.Y; y++) { - { - v3s16 p = roomplace + v3s16(x, y, 0); - if (!vm->m_area.contains(p)) - continue; - u32 vi = vm->m_area.index(p); - if (vm->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE) - continue; - vm->m_data[vi] = n_wall; - } - { - v3s16 p = roomplace + v3s16(x, y, roomsize.Z - 1); - if (!vm->m_area.contains(p)) - continue; - u32 vi = vm->m_area.index(p); - if (vm->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE) - continue; - vm->m_data[vi] = n_wall; - } + for (s16 y = 0; y < roomsize.Y; y++) { + { + v3s16 p = roomplace + v3s16(x, y, 0); + if (!vm->m_area.contains(p)) + continue; + u32 vi = vm->m_area.index(p); + if (vm->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE) + continue; + vm->m_data[vi] = n_wall; + } + { + v3s16 p = roomplace + v3s16(x, y, roomsize.Z - 1); + if (!vm->m_area.contains(p)) + continue; + u32 vi = vm->m_area.index(p); + if (vm->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE) + continue; + vm->m_data[vi] = n_wall; } + } // Make +-Y walls (floor and ceiling) for (s16 z = 0; z < roomsize.Z; z++) - for (s16 x = 0; x < roomsize.X; x++) { - { - v3s16 p = roomplace + v3s16(x, 0, z); - if (!vm->m_area.contains(p)) - continue; - u32 vi = vm->m_area.index(p); - if (vm->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE) - continue; - vm->m_data[vi] = n_wall; - } - { - v3s16 p = roomplace + v3s16(x, roomsize.Y - 1, z); - if (!vm->m_area.contains(p)) - continue; - u32 vi = vm->m_area.index(p); - if (vm->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE) - continue; - vm->m_data[vi] = n_wall; - } + for (s16 x = 0; x < roomsize.X; x++) { + { + v3s16 p = roomplace + v3s16(x, 0, z); + if (!vm->m_area.contains(p)) + continue; + u32 vi = vm->m_area.index(p); + if (vm->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE) + continue; + vm->m_data[vi] = n_wall; } + { + v3s16 p = roomplace + v3s16(x,roomsize. Y - 1, z); + if (!vm->m_area.contains(p)) + continue; + u32 vi = vm->m_area.index(p); + if (vm->m_flags[vi] & VMANIP_FLAG_DUNGEON_UNTOUCHABLE) + continue; + vm->m_data[vi] = n_wall; + } + } // Fill with air for (s16 z = 1; z < roomsize.Z - 1; z++) - for (s16 y = 1; y < roomsize.Y - 1; y++) - for (s16 x = 1; x < roomsize.X - 1; x++) { - v3s16 p = roomplace + v3s16(x, y, z); - if (!vm->m_area.contains(p)) - continue; - u32 vi = vm->m_area.index(p); - vm->m_flags[vi] |= VMANIP_FLAG_DUNGEON_UNTOUCHABLE; - vm->m_data[vi] = n_air; - } + for (s16 y = 1; y < roomsize.Y - 1; y++) + for (s16 x = 1; x < roomsize.X - 1; x++) { + v3s16 p = roomplace + v3s16(x, y, z); + if (!vm->m_area.contains(p)) + continue; + u32 vi = vm->m_area.index(p); + vm->m_flags[vi] |= VMANIP_FLAG_DUNGEON_UNTOUCHABLE; + vm->m_data[vi] = n_air; + } } -void DungeonGen::makeFill(v3s16 place, v3s16 size, u8 avoid_flags, MapNode n, u8 or_flags) + +void DungeonGen::makeFill(v3s16 place, v3s16 size, + u8 avoid_flags, MapNode n, u8 or_flags) { for (s16 z = 0; z < size.Z; z++) - for (s16 y = 0; y < size.Y; y++) - for (s16 x = 0; x < size.X; x++) { - v3s16 p = place + v3s16(x, y, z); - if (!vm->m_area.contains(p)) - continue; - u32 vi = vm->m_area.index(p); - if (vm->m_flags[vi] & avoid_flags) - continue; - vm->m_flags[vi] |= or_flags; - vm->m_data[vi] = n; - } + for (s16 y = 0; y < size.Y; y++) + for (s16 x = 0; x < size.X; x++) { + v3s16 p = place + v3s16(x, y, z); + if (!vm->m_area.contains(p)) + continue; + u32 vi = vm->m_area.index(p); + if (vm->m_flags[vi] & avoid_flags) + continue; + vm->m_flags[vi] |= or_flags; + vm->m_data[vi] = n; + } } + void DungeonGen::makeHole(v3s16 place) { - makeFill(place, dp.holesize, 0, MapNode(CONTENT_AIR), VMANIP_FLAG_DUNGEON_INSIDE); + makeFill(place, dp.holesize, 0, MapNode(CONTENT_AIR), + VMANIP_FLAG_DUNGEON_INSIDE); } + void DungeonGen::makeDoor(v3s16 doorplace, v3s16 doordir) { makeHole(doorplace); @@ -399,8 +397,9 @@ void DungeonGen::makeDoor(v3s16 doorplace, v3s16 doordir) #endif } -void DungeonGen::makeCorridor( - v3s16 doorplace, v3s16 doordir, v3s16 &result_place, v3s16 &result_dir) + +void DungeonGen::makeCorridor(v3s16 doorplace, v3s16 doordir, + v3s16 &result_place, v3s16 &result_dir) { makeHole(doorplace); v3s16 p0 = doorplace; @@ -422,16 +421,14 @@ void DungeonGen::makeCorridor( if (vm->m_area.contains(p) && vm->m_area.contains(p + v3s16(0, 1, 0))) { if (make_stairs) { makeFill(p + v3s16(-1, -1, -1), - dp.holesize + v3s16(2, 3, 2), - VMANIP_FLAG_DUNGEON_UNTOUCHABLE, - MapNode(dp.c_wall), 0); + dp.holesize + v3s16(2, 3, 2), + VMANIP_FLAG_DUNGEON_UNTOUCHABLE, + MapNode(dp.c_wall), + 0); makeFill(p, dp.holesize, VMANIP_FLAG_DUNGEON_UNTOUCHABLE, - MapNode(CONTENT_AIR), - VMANIP_FLAG_DUNGEON_INSIDE); - makeFill(p - dir, dp.holesize, - VMANIP_FLAG_DUNGEON_UNTOUCHABLE, - MapNode(CONTENT_AIR), - VMANIP_FLAG_DUNGEON_INSIDE); + MapNode(CONTENT_AIR), VMANIP_FLAG_DUNGEON_INSIDE); + makeFill(p - dir, dp.holesize, VMANIP_FLAG_DUNGEON_UNTOUCHABLE, + MapNode(CONTENT_AIR), VMANIP_FLAG_DUNGEON_INSIDE); // TODO: fix stairs code so it works 100% // (quite difficult) @@ -439,52 +436,30 @@ void DungeonGen::makeCorridor( // exclude stairs from the bottom step // exclude stairs from diagonal steps if (((dir.X ^ dir.Z) & 1) && - (((make_stairs == 1) && i != 0) || - ((make_stairs == -1) && - i != length - 1))) { + (((make_stairs == 1) && i != 0) || + ((make_stairs == -1) && i != length - 1))) { // rotate face 180 deg if // making stairs backwards int facedir = dir_to_facedir(dir * make_stairs); v3s16 ps = p; - u16 stair_width = (dir.Z != 0) ? dp.holesize.X - : dp.holesize.Z; + u16 stair_width = (dir.Z != 0) ? dp.holesize.X : dp.holesize.Z; // Stair width direction vector - v3s16 swv = (dir.Z != 0) ? v3s16(1, 0, 0) - : v3s16(0, 0, 1); + v3s16 swv = (dir.Z != 0) ? v3s16(1, 0, 0) : v3s16(0, 0, 1); for (u16 st = 0; st < stair_width; st++) { if (make_stairs == -1) { - u32 vi = vm->m_area.index( - ps.X - dir.X, - ps.Y - 1, - ps.Z - dir.Z); - if (vm->m_area.contains( - ps + - v3s16(-dir.X, -1, - -dir.Z)) && - vm->m_data[vi].getContent() == - dp.c_wall) { - vm->m_flags[vi] |= - VMANIP_FLAG_DUNGEON_UNTOUCHABLE; - vm->m_data[vi] = MapNode( - dp.c_stair, - 0, - facedir); + u32 vi = vm->m_area.index(ps.X - dir.X, ps.Y - 1, ps.Z - dir.Z); + if (vm->m_area.contains(ps + v3s16(-dir.X, -1, -dir.Z)) && + vm->m_data[vi].getContent() == dp.c_wall) { + vm->m_flags[vi] |= VMANIP_FLAG_DUNGEON_UNTOUCHABLE; + vm->m_data[vi] = MapNode(dp.c_stair, 0, facedir); } } else if (make_stairs == 1) { - u32 vi = vm->m_area.index(ps.X, - ps.Y - 1, ps.Z); - if (vm->m_area.contains( - ps + - v3s16(0, -1, 0)) && - vm->m_data[vi].getContent() == - dp.c_wall) { - vm->m_flags[vi] |= - VMANIP_FLAG_DUNGEON_UNTOUCHABLE; - vm->m_data[vi] = MapNode( - dp.c_stair, - 0, - facedir); + u32 vi = vm->m_area.index(ps.X, ps.Y - 1, ps.Z); + if (vm->m_area.contains(ps + v3s16(0, -1, 0)) && + vm->m_data[vi].getContent() == dp.c_wall) { + vm->m_flags[vi] |= VMANIP_FLAG_DUNGEON_UNTOUCHABLE; + vm->m_data[vi] = MapNode(dp.c_stair, 0, facedir); } } ps += swv; @@ -492,9 +467,10 @@ void DungeonGen::makeCorridor( } } else { makeFill(p + v3s16(-1, -1, -1), - dp.holesize + v3s16(2, 2, 2), - VMANIP_FLAG_DUNGEON_UNTOUCHABLE, - MapNode(dp.c_wall), 0); + dp.holesize + v3s16(2, 2, 2), + VMANIP_FLAG_DUNGEON_UNTOUCHABLE, + MapNode(dp.c_wall), + 0); makeHole(p); } @@ -525,6 +501,7 @@ void DungeonGen::makeCorridor( result_dir = dir; } + bool DungeonGen::findPlaceForDoor(v3s16 &result_place, v3s16 &result_dir) { for (u32 i = 0; i < 100; i++) { @@ -547,30 +524,25 @@ bool DungeonGen::findPlaceForDoor(v3s16 &result_place, v3s16 &result_dir) Determine where to move next */ // Jump one up if the actual space is there - if (vm->getNodeNoExNoEmerge(p + v3s16(0, 0, 0)).getContent() == - dp.c_wall && - vm->getNodeNoExNoEmerge(p + v3s16(0, 1, 0)) - .getContent() == - CONTENT_AIR && - vm->getNodeNoExNoEmerge(p + v3s16(0, 2, 0)) - .getContent() == - CONTENT_AIR) - p += v3s16(0, 1, 0); + if (vm->getNodeNoExNoEmerge(p + + v3s16(0, 0, 0)).getContent() == dp.c_wall && + vm->getNodeNoExNoEmerge(p + + v3s16(0, 1, 0)).getContent() == CONTENT_AIR && + vm->getNodeNoExNoEmerge(p + + v3s16(0, 2, 0)).getContent() == CONTENT_AIR) + p += v3s16(0,1,0); // Jump one down if the actual space is there - if (vm->getNodeNoExNoEmerge(p + v3s16(0, 1, 0)).getContent() == - dp.c_wall && - vm->getNodeNoExNoEmerge(p + v3s16(0, 0, 0)) - .getContent() == - CONTENT_AIR && - vm->getNodeNoExNoEmerge(p + v3s16(0, -1, 0)) - .getContent() == - CONTENT_AIR) + if (vm->getNodeNoExNoEmerge(p + + v3s16(0, 1, 0)).getContent() == dp.c_wall && + vm->getNodeNoExNoEmerge(p + + v3s16(0, 0, 0)).getContent() == CONTENT_AIR && + vm->getNodeNoExNoEmerge(p + + v3s16(0, -1, 0)).getContent() == CONTENT_AIR) p += v3s16(0, -1, 0); // Check if walking is now possible if (vm->getNodeNoExNoEmerge(p).getContent() != CONTENT_AIR || - vm->getNodeNoExNoEmerge(p + v3s16(0, 1, 0)) - .getContent() != - CONTENT_AIR) { + vm->getNodeNoExNoEmerge(p + + v3s16(0, 1, 0)).getContent() != CONTENT_AIR) { // Cannot continue walking here randomizeDir(); continue; @@ -581,8 +553,9 @@ bool DungeonGen::findPlaceForDoor(v3s16 &result_place, v3s16 &result_dir) return false; } + bool DungeonGen::findPlaceForRoomDoor(v3s16 roomsize, v3s16 &result_doorplace, - v3s16 &result_doordir, v3s16 &result_roomplace) + v3s16 &result_doordir, v3s16 &result_roomplace) { for (s16 trycount = 0; trycount < 30; trycount++) { v3s16 doorplace; @@ -594,46 +567,45 @@ bool DungeonGen::findPlaceForRoomDoor(v3s16 roomsize, v3s16 &result_doorplace, // X east, Z north, Y up if (doordir == v3s16(1, 0, 0)) // X+ roomplace = doorplace + - v3s16(0, -1, random.range(-roomsize.Z + 2, -2)); + v3s16(0, -1, random.range(-roomsize.Z + 2, -2)); if (doordir == v3s16(-1, 0, 0)) // X- roomplace = doorplace + - v3s16(-roomsize.X + 1, -1, - random.range(-roomsize.Z + 2, -2)); + v3s16(-roomsize.X + 1, -1, random.range(-roomsize.Z + 2, -2)); if (doordir == v3s16(0, 0, 1)) // Z+ roomplace = doorplace + - v3s16(random.range(-roomsize.X + 2, -2), -1, 0); + v3s16(random.range(-roomsize.X + 2, -2), -1, 0); if (doordir == v3s16(0, 0, -1)) // Z- - roomplace = doorplace + v3s16(random.range(-roomsize.X + 2, -2), - -1, -roomsize.Z + 1); + roomplace = doorplace + + v3s16(random.range(-roomsize.X + 2, -2), -1, -roomsize.Z + 1); // Check fit bool fits = true; for (s16 z = 1; z < roomsize.Z - 1; z++) - for (s16 y = 1; y < roomsize.Y - 1; y++) - for (s16 x = 1; x < roomsize.X - 1; x++) { - v3s16 p = roomplace + v3s16(x, y, z); - if (!vm->m_area.contains(p)) { - fits = false; - break; - } - if (vm->m_flags[vm->m_area.index(p)] & - VMANIP_FLAG_DUNGEON_INSIDE) { - fits = false; - break; - } - } + for (s16 y = 1; y < roomsize.Y - 1; y++) + for (s16 x = 1; x < roomsize.X - 1; x++) { + v3s16 p = roomplace + v3s16(x, y, z); + if (!vm->m_area.contains(p)) { + fits = false; + break; + } + if (vm->m_flags[vm->m_area.index(p)] & VMANIP_FLAG_DUNGEON_INSIDE) { + fits = false; + break; + } + } if (!fits) { // Find new place continue; } result_doorplace = doorplace; - result_doordir = doordir; + result_doordir = doordir; result_roomplace = roomplace; return true; } return false; } + v3s16 rand_ortho_dir(PseudoRandom &random, bool diagonal_dirs) { // Make diagonal directions somewhat rare @@ -658,6 +630,7 @@ v3s16 rand_ortho_dir(PseudoRandom &random, bool diagonal_dirs) return random.next() % 2 ? v3s16(0, 0, -1) : v3s16(0, 0, 1); } + v3s16 turn_xz(v3s16 olddir, int t) { v3s16 dir; @@ -675,6 +648,7 @@ v3s16 turn_xz(v3s16 olddir, int t) return dir; } + void random_turn(PseudoRandom &random, v3s16 &dir) { int turn = random.range(0, 2); @@ -690,6 +664,7 @@ void random_turn(PseudoRandom &random, v3s16 &dir) } } + int dir_to_facedir(v3s16 d) { if (abs(d.X) > abs(d.Z)) diff --git a/src/mapgen/dungeongen.h b/src/mapgen/dungeongen.h index f70fedb5e..35e6beef5 100644 --- a/src/mapgen/dungeongen.h +++ b/src/mapgen/dungeongen.h @@ -26,8 +26,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #define VMANIP_FLAG_DUNGEON_INSIDE VOXELFLAG_CHECKED1 #define VMANIP_FLAG_DUNGEON_PRESERVE VOXELFLAG_CHECKED2 -#define VMANIP_FLAG_DUNGEON_UNTOUCHABLE \ - (VMANIP_FLAG_DUNGEON_INSIDE | VMANIP_FLAG_DUNGEON_PRESERVE) +#define VMANIP_FLAG_DUNGEON_UNTOUCHABLE (\ + VMANIP_FLAG_DUNGEON_INSIDE|VMANIP_FLAG_DUNGEON_PRESERVE) class MMVManip; class NodeDefManager; @@ -37,8 +37,8 @@ v3s16 turn_xz(v3s16 olddir, int t); void random_turn(PseudoRandom &random, v3s16 &dir); int dir_to_facedir(v3s16 d); -struct DungeonParams -{ + +struct DungeonParams { s32 seed; content_t c_wall; @@ -82,8 +82,7 @@ struct DungeonParams GenNotifyType notifytype; }; -class DungeonGen -{ +class DungeonGen { public: MMVManip *vm = nullptr; const NodeDefManager *ndef; @@ -100,15 +99,15 @@ public: v3s16 m_pos; v3s16 m_dir; - DungeonGen(const NodeDefManager *ndef, GenerateNotifier *gennotify, - DungeonParams *dparams); + DungeonGen(const NodeDefManager *ndef, + GenerateNotifier *gennotify, DungeonParams *dparams); 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); - void makeCorridor(v3s16 doorplace, v3s16 doordir, v3s16 &result_place, - v3s16 &result_dir); + void makeCorridor(v3s16 doorplace, v3s16 doordir, + v3s16 &result_place, v3s16 &result_dir); void makeDoor(v3s16 doorplace, v3s16 doordir); void makeFill(v3s16 place, v3s16 size, u8 avoid_flags, MapNode n, u8 or_flags); void makeHole(v3s16 place); @@ -117,7 +116,10 @@ public: bool findPlaceForRoomDoor(v3s16 roomsize, v3s16 &result_doorplace, v3s16 &result_doordir, v3s16 &result_roomplace); - inline void randomizeDir() { m_dir = rand_ortho_dir(random, dp.diagonal_dirs); } + inline void randomizeDir() + { + m_dir = rand_ortho_dir(random, dp.diagonal_dirs); + } }; extern NoiseParams nparams_dungeon_density; diff --git a/src/mapgen/mapgen.cpp b/src/mapgen/mapgen.cpp index 84cb79400..f57529082 100644 --- a/src/mapgen/mapgen.cpp +++ b/src/mapgen/mapgen.cpp @@ -52,20 +52,27 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "cavegen.h" #include "dungeongen.h" -FlagDesc flagdesc_mapgen[] = {{"caves", MG_CAVES}, {"dungeons", MG_DUNGEONS}, - {"light", MG_LIGHT}, {"decorations", MG_DECORATIONS}, - {"biomes", MG_BIOMES}, {NULL, 0}}; - -FlagDesc flagdesc_gennotify[] = {{"dungeon", 1 << GENNOTIFY_DUNGEON}, - {"temple", 1 << GENNOTIFY_TEMPLE}, - {"cave_begin", 1 << GENNOTIFY_CAVE_BEGIN}, - {"cave_end", 1 << GENNOTIFY_CAVE_END}, - {"large_cave_begin", 1 << GENNOTIFY_LARGECAVE_BEGIN}, - {"large_cave_end", 1 << GENNOTIFY_LARGECAVE_END}, - {"decoration", 1 << GENNOTIFY_DECORATION}, {NULL, 0}}; - -struct MapgenDesc -{ +FlagDesc flagdesc_mapgen[] = { + {"caves", MG_CAVES}, + {"dungeons", MG_DUNGEONS}, + {"light", MG_LIGHT}, + {"decorations", MG_DECORATIONS}, + {"biomes", MG_BIOMES}, + {NULL, 0} +}; + +FlagDesc flagdesc_gennotify[] = { + {"dungeon", 1 << GENNOTIFY_DUNGEON}, + {"temple", 1 << GENNOTIFY_TEMPLE}, + {"cave_begin", 1 << GENNOTIFY_CAVE_BEGIN}, + {"cave_end", 1 << GENNOTIFY_CAVE_END}, + {"large_cave_begin", 1 << GENNOTIFY_LARGECAVE_BEGIN}, + {"large_cave_end", 1 << GENNOTIFY_LARGECAVE_END}, + {"decoration", 1 << GENNOTIFY_DECORATION}, + {NULL, 0} +}; + +struct MapgenDesc { const char *name; bool is_user_visible; }; @@ -81,30 +88,32 @@ struct MapgenDesc // 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[] = { - {"v7", true}, - {"valleys", true}, - {"carpathian", true}, - {"v5", true}, - {"flat", true}, - {"fractal", true}, - {"singlenode", true}, - {"v6", true}, + {"v7", true}, + {"valleys", true}, + {"carpathian", true}, + {"v5", true}, + {"flat", true}, + {"fractal", true}, + {"singlenode", true}, + {"v6", true}, }; -STATIC_ASSERT(ARRLEN(g_reg_mapgens) == MAPGEN_INVALID, registered_mapgens_is_wrong_size); +STATIC_ASSERT( + ARRLEN(g_reg_mapgens) == MAPGEN_INVALID, + registered_mapgens_is_wrong_size); //// //// Mapgen //// Mapgen::Mapgen(int mapgenid, MapgenParams *params, EmergeParams *emerge) : - gennotify(emerge->gen_notify_on, emerge->gen_notify_on_deco_ids) + gennotify(emerge->gen_notify_on, emerge->gen_notify_on_deco_ids) { - id = mapgenid; - water_level = params->water_level; + id = mapgenid; + water_level = params->water_level; mapgen_limit = params->mapgen_limit; - flags = params->flags; - csize = v3s16(1, 1, 1) * (params->chunksize * MAP_BLOCKSIZE); + flags = params->flags; + csize = v3s16(1, 1, 1) * (params->chunksize * MAP_BLOCKSIZE); /* We are losing half our entropy by doing this, but it is necessary to @@ -121,9 +130,10 @@ Mapgen::Mapgen(int mapgenid, MapgenParams *params, EmergeParams *emerge) : */ seed = (s32)params->seed; - ndef = emerge->ndef; + ndef = emerge->ndef; } + MapgenType Mapgen::getMapgenType(const std::string &mgname) { for (size_t i = 0; i != ARRLEN(g_reg_mapgens); i++) { @@ -134,6 +144,7 @@ MapgenType Mapgen::getMapgenType(const std::string &mgname) return MAPGEN_INVALID; } + const char *Mapgen::getMapgenName(MapgenType mgtype) { size_t index = (size_t)mgtype; @@ -143,8 +154,9 @@ const char *Mapgen::getMapgenName(MapgenType mgtype) return g_reg_mapgens[index].name; } -Mapgen *Mapgen::createMapgen( - MapgenType mgtype, MapgenParams *params, EmergeParams *emerge) + +Mapgen *Mapgen::createMapgen(MapgenType mgtype, MapgenParams *params, + EmergeParams *emerge) { switch (mgtype) { case MAPGEN_CARPATHIAN: @@ -168,6 +180,7 @@ Mapgen *Mapgen::createMapgen( } } + MapgenParams *Mapgen::createMapgenParams(MapgenType mgtype) { switch (mgtype) { @@ -192,6 +205,7 @@ MapgenParams *Mapgen::createMapgenParams(MapgenType mgtype) } } + void Mapgen::getMapgenNames(std::vector<const char *> *mgnames, bool include_hidden) { for (u32 i = 0; i != ARRLEN(g_reg_mapgens); i++) { @@ -203,7 +217,7 @@ void Mapgen::getMapgenNames(std::vector<const char *> *mgnames, bool include_hid void Mapgen::setDefaultSettings(Settings *settings) { settings->setDefault("mg_flags", flagdesc_mapgen, - MG_CAVES | MG_DUNGEONS | MG_LIGHT | MG_DECORATIONS | MG_BIOMES); + MG_CAVES | MG_DUNGEONS | MG_LIGHT | MG_DECORATIONS | MG_BIOMES); for (int i = 0; i < (int)MAPGEN_INVALID; ++i) { MapgenParams *params = createMapgenParams((MapgenType)i); @@ -214,9 +228,13 @@ void Mapgen::setDefaultSettings(Settings *settings) u32 Mapgen::getBlockSeed(v3s16 p, s32 seed) { - return (u32)seed + p.Z * 38134234 + p.Y * 42123 + p.X * 23; + return (u32)seed + + p.Z * 38134234 + + p.Y * 42123 + + p.X * 23; } + u32 Mapgen::getBlockSeed2(v3s16 p, s32 seed) { u32 n = 1619 * p.X + 31337 * p.Y + 52591 * p.Z + 1013 * seed; @@ -224,6 +242,7 @@ u32 Mapgen::getBlockSeed2(v3s16 p, s32 seed) return (n * (n * n * 60493 + 19990303) + 1376312589); } + // Returns Y one under area minimum if not found s16 Mapgen::findGroundLevelFull(v2s16 p2d) { @@ -243,6 +262,7 @@ s16 Mapgen::findGroundLevelFull(v2s16 p2d) return (y >= y_nodes_min) ? y : y_nodes_min - 1; } + // Returns -MAX_MAP_GENERATION_LIMIT if not found s16 Mapgen::findGroundLevel(v2s16 p2d, s16 ymin, s16 ymax) { @@ -260,6 +280,7 @@ s16 Mapgen::findGroundLevel(v2s16 p2d, s16 ymin, s16 ymax) return (y >= ymin) ? y : -MAX_MAP_GENERATION_LIMIT; } + // Returns -MAX_MAP_GENERATION_LIMIT if not found or if ground is found first s16 Mapgen::findLiquidSurface(v2s16 p2d, s16 ymin, s16 ymax) { @@ -280,12 +301,13 @@ s16 Mapgen::findLiquidSurface(v2s16 p2d, s16 ymin, s16 ymax) return (y >= ymin) ? y : -MAX_MAP_GENERATION_LIMIT; } + void Mapgen::updateHeightmap(v3s16 nmin, v3s16 nmax) { if (!heightmap) return; - // TimeTaker t("Mapgen::updateHeightmap", NULL, PRECISION_MICRO); + //TimeTaker t("Mapgen::updateHeightmap", NULL, PRECISION_MICRO); int index = 0; for (s16 z = nmin.Z; z <= nmax.Z; z++) { for (s16 x = nmin.X; x <= nmax.X; x++, index++) { @@ -296,8 +318,9 @@ void Mapgen::updateHeightmap(v3s16 nmin, v3s16 nmax) } } -void Mapgen::getSurfaces(v2s16 p2d, s16 ymin, s16 ymax, std::vector<s16> &floors, - std::vector<s16> &ceilings) + +void Mapgen::getSurfaces(v2s16 p2d, s16 ymin, s16 ymax, + std::vector<s16> &floors, std::vector<s16> &ceilings) { const v3s16 &em = vm->m_area.getExtent(); @@ -322,6 +345,7 @@ void Mapgen::getSurfaces(v2s16 p2d, s16 ymin, s16 ymax, std::vector<s16> &floors } } + inline bool Mapgen::isLiquidHorizontallyFlowable(u32 vi, v3s16 em) { u32 vi_neg_x = vi; @@ -358,60 +382,55 @@ inline bool Mapgen::isLiquidHorizontallyFlowable(u32 vi, v3s16 em) void Mapgen::updateLiquid(UniqueQueue<v3s16> *trans_liquid, v3s16 nmin, v3s16 nmax) { bool isignored, isliquid, wasignored, wasliquid, waschecked, waspushed; - const v3s16 &em = vm->m_area.getExtent(); + const v3s16 &em = vm->m_area.getExtent(); for (s16 z = nmin.Z + 1; z <= nmax.Z - 1; z++) - for (s16 x = nmin.X + 1; x <= nmax.X - 1; x++) { - wasignored = true; - wasliquid = false; - waschecked = false; - waspushed = false; - - u32 vi = vm->m_area.index(x, nmax.Y, z); - for (s16 y = nmax.Y; y >= nmin.Y; y--) { - isignored = vm->m_data[vi].getContent() == CONTENT_IGNORE; - isliquid = ndef->get(vm->m_data[vi]).isLiquid(); - - if (isignored || wasignored || isliquid == wasliquid) { - // Neither topmost node of liquid column nor - // topmost node below column - waschecked = false; - waspushed = false; - } else if (isliquid) { - // This is the topmost node in the column - bool ispushed = false; - if (isLiquidHorizontallyFlowable(vi, em)) { - trans_liquid->push_back(v3s16(x, y, z)); - ispushed = true; - } - // Remember waschecked and waspushed to avoid - // repeated checks/pushes in case the column - // consists of only this node - waschecked = true; - waspushed = ispushed; - } else { - // This is the topmost node below a liquid column - u32 vi_above = vi; - VoxelArea::add_y(em, vi_above, 1); - if (!waspushed && - (ndef->get(vm->m_data[vi]).floodable || - (!waschecked && isLiquidHorizontallyFlowable( - vi_above, - em)))) { - // Push back the lowest node in the column - // which is one node above this one - trans_liquid->push_back( - v3s16(x, y + 1, z)); - } + for (s16 x = nmin.X + 1; x <= nmax.X - 1; x++) { + wasignored = true; + wasliquid = false; + waschecked = false; + waspushed = false; + + u32 vi = vm->m_area.index(x, nmax.Y, z); + for (s16 y = nmax.Y; y >= nmin.Y; y--) { + isignored = vm->m_data[vi].getContent() == CONTENT_IGNORE; + isliquid = ndef->get(vm->m_data[vi]).isLiquid(); + + if (isignored || wasignored || isliquid == wasliquid) { + // Neither topmost node of liquid column nor topmost node below column + waschecked = false; + waspushed = false; + } else if (isliquid) { + // This is the topmost node in the column + bool ispushed = false; + if (isLiquidHorizontallyFlowable(vi, em)) { + trans_liquid->push_back(v3s16(x, y, z)); + ispushed = true; + } + // Remember waschecked and waspushed to avoid repeated + // checks/pushes in case the column consists of only this node + waschecked = true; + waspushed = ispushed; + } else { + // This is the topmost node below a liquid column + u32 vi_above = vi; + VoxelArea::add_y(em, vi_above, 1); + if (!waspushed && (ndef->get(vm->m_data[vi]).floodable || + (!waschecked && isLiquidHorizontallyFlowable(vi_above, em)))) { + // Push back the lowest node in the column which is one + // node above this one + trans_liquid->push_back(v3s16(x, y + 1, z)); } - - wasliquid = isliquid; - wasignored = isignored; - VoxelArea::add_y(em, vi, -1); } + + wasliquid = isliquid; + wasignored = isignored; + VoxelArea::add_y(em, vi, -1); } + } } + void Mapgen::setLighting(u8 light, v3s16 nmin, v3s16 nmax) { ScopeProfiler sp(g_profiler, "EmergeThread: update lighting", SPT_AVG); @@ -426,8 +445,9 @@ void Mapgen::setLighting(u8 light, v3s16 nmin, v3s16 nmax) } } + void Mapgen::lightSpread(VoxelArea &a, std::queue<std::pair<v3s16, u8>> &queue, - const v3s16 &p, u8 light) + const v3s16 &p, u8 light) { if (light <= 1 || !a.contains(p)) return; @@ -446,14 +466,16 @@ void Mapgen::lightSpread(VoxelArea &a, std::queue<std::pair<v3s16, u8>> &queue, // 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)) || + if ((light_day <= (n.param1 & 0x0F) && + light_night <= (n.param1 & 0xF0)) || !ndef->get(n).light_propagates) return; // Since this recursive function only terminates when there is no light from // either bank left, we need to take the max of both banks into account for // the case where spreading has stopped for one light bank but not the other. - light = MYMAX(light_day, n.param1 & 0x0F) | MYMAX(light_night, n.param1 & 0xF0); + light = MYMAX(light_day, n.param1 & 0x0F) | + MYMAX(light_night, n.param1 & 0xF0); n.param1 = light; @@ -461,21 +483,23 @@ void Mapgen::lightSpread(VoxelArea &a, std::queue<std::pair<v3s16, u8>> &queue, queue.emplace(p, light); } + void Mapgen::calcLighting(v3s16 nmin, v3s16 nmax, v3s16 full_nmin, v3s16 full_nmax, - bool propagate_shadow) + bool propagate_shadow) { ScopeProfiler sp(g_profiler, "EmergeThread: update lighting", SPT_AVG); - // TimeTaker t("updateLighting"); + //TimeTaker t("updateLighting"); propagateSunlight(nmin, nmax, propagate_shadow); spreadLight(full_nmin, full_nmax); - // printf("updateLighting: %dms\n", t.stop()); + //printf("updateLighting: %dms\n", t.stop()); } + void Mapgen::propagateSunlight(v3s16 nmin, v3s16 nmax, bool propagate_shadow) { - // TimeTaker t("propagateSunlight"); + //TimeTaker t("propagateSunlight"); VoxelArea a(nmin, nmax); bool block_is_underground = (water_level >= nmax.Y); const v3s16 &em = vm->m_area.getExtent(); @@ -505,12 +529,13 @@ void Mapgen::propagateSunlight(v3s16 nmin, v3s16 nmax, bool propagate_shadow) } } } - // printf("propagateSunlight: %dms\n", t.stop()); + //printf("propagateSunlight: %dms\n", t.stop()); } + void Mapgen::spreadLight(const v3s16 &nmin, const v3s16 &nmax) { - // TimeTaker t("spreadLight"); + //TimeTaker t("spreadLight"); std::queue<std::pair<v3s16, u8>> queue; VoxelArea a(nmin, nmax); @@ -526,9 +551,8 @@ void Mapgen::spreadLight(const v3s16 &nmin, const v3s16 &nmax) if (!cf.light_propagates) continue; - // TODO(hmmmmm): Abstract away direct param1 accesses with - // a wrapper, but something lighter than - // MapNode::get/setLight + // TODO(hmmmmm): Abstract away direct param1 accesses with a + // wrapper, but something lighter than MapNode::get/setLight u8 light_produced = cf.light_source; if (light_produced) @@ -553,18 +577,19 @@ void Mapgen::spreadLight(const v3s16 &nmin, const v3s16 &nmax) queue.pop(); } - // printf("spreadLight: %lums\n", t.stop()); + //printf("spreadLight: %lums\n", t.stop()); } + //// //// MapgenBasic //// -MapgenBasic::MapgenBasic(int mapgenid, MapgenParams *params, EmergeParams *emerge) : - Mapgen(mapgenid, params, emerge) +MapgenBasic::MapgenBasic(int mapgenid, MapgenParams *params, EmergeParams *emerge) + : Mapgen(mapgenid, params, emerge) { this->m_emerge = emerge; - this->m_bmgr = emerge->biomemgr; + this->m_bmgr = emerge->biomemgr; //// Here, 'stride' refers to the number of elements needed to skip to index //// an adjacent element for that coordinate in noise/height/biome maps @@ -593,11 +618,11 @@ MapgenBasic::MapgenBasic(int mapgenid, MapgenParams *params, EmergeParams *emerg biomemap = biomegen->biomemap; //// Look up some commonly used content - c_stone = ndef->getId("mapgen_stone"); - c_water_source = ndef->getId("mapgen_water_source"); + c_stone = ndef->getId("mapgen_stone"); + 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"); + c_lava_source = ndef->getId("mapgen_lava_source"); + c_cobble = ndef->getId("mapgen_cobble"); // Fall back to more basic content if not defined. // Lava falls back to water as both are suitable as cave liquids. @@ -605,25 +630,23 @@ MapgenBasic::MapgenBasic(int mapgenid, MapgenParams *params, EmergeParams *emerg c_lava_source = c_water_source; if (c_stone == CONTENT_IGNORE) - errorstream << "Mapgen: Mapgen alias 'mapgen_stone' is invalid!" - << std::endl; + errorstream << "Mapgen: Mapgen alias 'mapgen_stone' is invalid!" << std::endl; if (c_water_source == CONTENT_IGNORE) - errorstream << "Mapgen: Mapgen alias 'mapgen_water_source' is invalid!" - << std::endl; + errorstream << "Mapgen: Mapgen alias 'mapgen_water_source' is invalid!" << std::endl; if (c_river_water_source == CONTENT_IGNORE) - warningstream << "Mapgen: Mapgen alias 'mapgen_river_water_source' is " - "invalid!" - << std::endl; + warningstream << "Mapgen: Mapgen alias 'mapgen_river_water_source' is invalid!" << std::endl; } + MapgenBasic::~MapgenBasic() { delete biomegen; - delete[] heightmap; + delete []heightmap; delete m_emerge; // destroying EmergeParams is our responsibility } + void MapgenBasic::generateBiomes() { // can't generate biomes without a biome generator! @@ -636,158 +659,131 @@ void MapgenBasic::generateBiomes() noise_filler_depth->perlinMap2D(node_min.X, node_min.Z); for (s16 z = node_min.Z; z <= node_max.Z; z++) - for (s16 x = node_min.X; x <= node_max.X; x++, index++) { - Biome *biome = NULL; - biome_t water_biome_index = 0; - u16 depth_top = 0; - u16 base_filler = 0; - u16 depth_water_top = 0; - u16 depth_riverbed = 0; - s16 biome_y_min = -MAX_MAP_GENERATION_LIMIT; - u32 vi = vm->m_area.index(x, node_max.Y, z); - - // Check node at base of mapchunk above, either a node of a - // previously generated mapchunk or if not, a node of - // overgenerated base terrain. - content_t c_above = vm->m_data[vi + em.X].getContent(); - bool air_above = c_above == CONTENT_AIR; - bool river_water_above = c_above == c_river_water_source; - bool water_above = c_above == c_water_source || river_water_above; - - biomemap[index] = BIOME_NONE; - - // If there is air or water above enable top/filler placement, - // otherwise force nplaced to stone level by setting a number - // exceeding any possible filler depth. - u16 nplaced = (air_above || water_above) ? 0 : U16_MAX; - - for (s16 y = node_max.Y; y >= node_min.Y; y--) { - content_t c = vm->m_data[vi].getContent(); - // Biome is (re)calculated: - // 1. At the surface of stone below air or water. - // 2. At the surface of water below air. - // 3. When stone or water is detected but biome has not - // yet been calculated. - // 4. When stone or water is detected just below a biome's - // lower limit. - bool is_stone_surface = - (c == c_stone) && - (air_above || water_above || !biome || - y < biome_y_min); // 1, 3, - // 4 - - bool is_water_surface = - (c == c_water_source || - c == c_river_water_source) && - (air_above || !biome || - y < biome_y_min); // 2, 3, - // 4 - - if (is_stone_surface || is_water_surface) { - // (Re)calculate biome - biome = biomegen->getBiomeAtIndex( - index, v3s16(x, y, z)); - - // Add biome to biomemap at first stone surface - // detected - if (biomemap[index] == BIOME_NONE && - is_stone_surface) - biomemap[index] = biome->index; - - // Store biome of first water surface detected, as - // a fallback entry for the biomemap. - if (water_biome_index == 0 && is_water_surface) - water_biome_index = biome->index; - - depth_top = biome->depth_top; - base_filler = MYMAX( - depth_top + biome->depth_filler + - noise_filler_depth->result - [index], - 0.0f); - depth_water_top = biome->depth_water_top; - depth_riverbed = biome->depth_riverbed; - biome_y_min = biome->min_pos.Y; - } + for (s16 x = node_min.X; x <= node_max.X; x++, index++) { + Biome *biome = NULL; + biome_t water_biome_index = 0; + u16 depth_top = 0; + u16 base_filler = 0; + u16 depth_water_top = 0; + u16 depth_riverbed = 0; + s16 biome_y_min = -MAX_MAP_GENERATION_LIMIT; + u32 vi = vm->m_area.index(x, node_max.Y, z); + + // Check node at base of mapchunk above, either a node of a previously + // generated mapchunk or if not, a node of overgenerated base terrain. + content_t c_above = vm->m_data[vi + em.X].getContent(); + bool air_above = c_above == CONTENT_AIR; + bool river_water_above = c_above == c_river_water_source; + bool water_above = c_above == c_water_source || river_water_above; + + biomemap[index] = BIOME_NONE; + + // If there is air or water above enable top/filler placement, otherwise force + // nplaced to stone level by setting a number exceeding any possible filler depth. + u16 nplaced = (air_above || water_above) ? 0 : U16_MAX; + + for (s16 y = node_max.Y; y >= node_min.Y; y--) { + content_t c = vm->m_data[vi].getContent(); + // Biome is (re)calculated: + // 1. At the surface of stone below air or water. + // 2. At the surface of water below air. + // 3. When stone or water is detected but biome has not yet been calculated. + // 4. When stone or water is detected just below a biome's lower limit. + bool is_stone_surface = (c == c_stone) && + (air_above || water_above || !biome || y < biome_y_min); // 1, 3, 4 + + bool is_water_surface = + (c == c_water_source || c == c_river_water_source) && + (air_above || !biome || y < biome_y_min); // 2, 3, 4 + + if (is_stone_surface || is_water_surface) { + // (Re)calculate biome + biome = biomegen->getBiomeAtIndex(index, v3s16(x, y, z)); + + // Add biome to biomemap at first stone surface detected + if (biomemap[index] == BIOME_NONE && is_stone_surface) + biomemap[index] = biome->index; + + // Store biome of first water surface detected, as a fallback + // entry for the biomemap. + if (water_biome_index == 0 && is_water_surface) + water_biome_index = biome->index; + + depth_top = biome->depth_top; + base_filler = MYMAX(depth_top + + biome->depth_filler + + noise_filler_depth->result[index], 0.0f); + depth_water_top = biome->depth_water_top; + depth_riverbed = biome->depth_riverbed; + biome_y_min = biome->min_pos.Y; + } - if (c == c_stone) { - content_t c_below = vm->m_data[vi - em.X] - .getContent(); - - // If the node below isn't solid, make this node - // stone, so that any top/filler nodes above are - // structurally supported. This is done by - // aborting the cycle of top/filler placement - // immediately by forcing nplaced to stone level. - if (c_below == CONTENT_AIR || - c_below == c_water_source || - c_below == c_river_water_source) - nplaced = U16_MAX; - - if (river_water_above) { - if (nplaced < depth_riverbed) { - vm->m_data[vi] = MapNode( - biome->c_riverbed); - nplaced++; - } else { - nplaced = U16_MAX; // Disable - // top/filler - // placement - river_water_above = false; - } - } else if (nplaced < depth_top) { - vm->m_data[vi] = MapNode(biome->c_top); - nplaced++; - } else if (nplaced < base_filler) { - vm->m_data[vi] = MapNode(biome->c_filler); + if (c == c_stone) { + content_t c_below = vm->m_data[vi - em.X].getContent(); + + // If the node below isn't solid, make this node stone, so that + // any top/filler nodes above are structurally supported. + // This is done by aborting the cycle of top/filler placement + // immediately by forcing nplaced to stone level. + if (c_below == CONTENT_AIR + || c_below == c_water_source + || c_below == c_river_water_source) + nplaced = U16_MAX; + + if (river_water_above) { + if (nplaced < depth_riverbed) { + vm->m_data[vi] = MapNode(biome->c_riverbed); nplaced++; } else { - vm->m_data[vi] = MapNode(biome->c_stone); - nplaced = U16_MAX; // Disable top/filler - // placement + nplaced = U16_MAX; // Disable top/filler placement + river_water_above = false; } - - air_above = false; - water_above = false; - } else if (c == c_water_source) { - vm->m_data[vi] = MapNode( - (y > (s32)(water_level - - depth_water_top)) - ? biome->c_water_top - : biome->c_water); - nplaced = 0; // Enable top/filler placement for - // next surface - air_above = false; - water_above = true; - } else if (c == c_river_water_source) { - vm->m_data[vi] = MapNode(biome->c_river_water); - nplaced = 0; // Enable riverbed placement for next - // surface - air_above = false; - water_above = true; - river_water_above = true; - } else if (c == CONTENT_AIR) { - nplaced = 0; // Enable top/filler placement for - // next surface - air_above = true; - water_above = false; - } else { // Possible various nodes overgenerated from - // neighbouring mapchunks - nplaced = U16_MAX; // Disable top/filler placement - air_above = false; - water_above = false; + } else if (nplaced < depth_top) { + vm->m_data[vi] = MapNode(biome->c_top); + nplaced++; + } else if (nplaced < base_filler) { + vm->m_data[vi] = MapNode(biome->c_filler); + nplaced++; + } else { + vm->m_data[vi] = MapNode(biome->c_stone); + nplaced = U16_MAX; // Disable top/filler placement } - VoxelArea::add_y(em, vi, -1); + air_above = false; + water_above = false; + } else if (c == c_water_source) { + vm->m_data[vi] = MapNode((y > (s32)(water_level - depth_water_top)) + ? biome->c_water_top : biome->c_water); + nplaced = 0; // Enable top/filler placement for next surface + air_above = false; + water_above = true; + } else if (c == c_river_water_source) { + vm->m_data[vi] = MapNode(biome->c_river_water); + nplaced = 0; // Enable riverbed placement for next surface + air_above = false; + water_above = true; + river_water_above = true; + } else if (c == CONTENT_AIR) { + nplaced = 0; // Enable top/filler placement for next surface + air_above = true; + water_above = false; + } else { // Possible various nodes overgenerated from neighbouring mapchunks + nplaced = U16_MAX; // Disable top/filler placement + air_above = false; + water_above = false; } - // If no stone surface detected in mapchunk column and a water - // surface biome fallback exists, add it to the biomemap. This - // avoids water surface decorations failing in deep water. - if (biomemap[index] == BIOME_NONE && water_biome_index != 0) - biomemap[index] = water_biome_index; + + VoxelArea::add_y(em, vi, -1); } + // If no stone surface detected in mapchunk column and a water surface + // biome fallback exists, add it to the biomemap. This avoids water + // surface decorations failing in deep water. + if (biomemap[index] == BIOME_NONE && water_biome_index != 0) + biomemap[index] = water_biome_index; + } } + void MapgenBasic::dustTopNodes() { if (node_max.Y < water_level) @@ -797,59 +793,61 @@ void MapgenBasic::dustTopNodes() 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++) { - Biome *biome = (Biome *)m_bmgr->getRaw(biomemap[index]); - - if (biome->c_dust == CONTENT_IGNORE) - continue; - - // Check if mapchunk above has generated, if so, drop dust from 16 - // nodes above current mapchunk top, above decorations that will - // extend above the current mapchunk. If the mapchunk above has - // not generated, it will provide this required dust when it does. - u32 vi = vm->m_area.index(x, full_node_max.Y, z); - content_t c_full_max = vm->m_data[vi].getContent(); - s16 y_start; - - if (c_full_max == CONTENT_AIR) { - y_start = full_node_max.Y - 1; - } else if (c_full_max == CONTENT_IGNORE) { - vi = vm->m_area.index(x, node_max.Y + 1, z); - content_t c_max = vm->m_data[vi].getContent(); - - if (c_max == CONTENT_AIR) - y_start = node_max.Y; - else - continue; - } else { + for (s16 x = node_min.X; x <= node_max.X; x++, index++) { + Biome *biome = (Biome *)m_bmgr->getRaw(biomemap[index]); + + if (biome->c_dust == CONTENT_IGNORE) + continue; + + // Check if mapchunk above has generated, if so, drop dust from 16 nodes + // above current mapchunk top, above decorations that will extend above + // the current mapchunk. If the mapchunk above has not generated, it + // will provide this required dust when it does. + u32 vi = vm->m_area.index(x, full_node_max.Y, z); + content_t c_full_max = vm->m_data[vi].getContent(); + s16 y_start; + + if (c_full_max == CONTENT_AIR) { + y_start = full_node_max.Y - 1; + } else if (c_full_max == CONTENT_IGNORE) { + vi = vm->m_area.index(x, node_max.Y + 1, z); + content_t c_max = vm->m_data[vi].getContent(); + + if (c_max == CONTENT_AIR) + y_start = node_max.Y; + else continue; - } + } else { + continue; + } - vi = vm->m_area.index(x, y_start, z); - for (s16 y = y_start; y >= node_min.Y - 1; y--) { - if (vm->m_data[vi].getContent() != CONTENT_AIR) - break; + vi = vm->m_area.index(x, y_start, z); + for (s16 y = y_start; y >= node_min.Y - 1; y--) { + if (vm->m_data[vi].getContent() != CONTENT_AIR) + break; - VoxelArea::add_y(em, vi, -1); - } + VoxelArea::add_y(em, vi, -1); + } - content_t c = vm->m_data[vi].getContent(); - NodeDrawType dtype = ndef->get(c).drawtype; - // Only place on cubic, walkable, non-dust nodes. - // Dust check needed due to avoid double layer of dust caused by - // dropping dust from 16 nodes above mapchunk top. - if ((dtype == NDT_NORMAL || dtype == NDT_ALLFACES || - dtype == NDT_ALLFACES_OPTIONAL || - dtype == NDT_GLASSLIKE || - dtype == NDT_GLASSLIKE_FRAMED || - dtype == NDT_GLASSLIKE_FRAMED_OPTIONAL) && - ndef->get(c).walkable && c != biome->c_dust) { - VoxelArea::add_y(em, vi, 1); - vm->m_data[vi] = MapNode(biome->c_dust); - } + content_t c = vm->m_data[vi].getContent(); + NodeDrawType dtype = ndef->get(c).drawtype; + // Only place on cubic, walkable, non-dust nodes. + // Dust check needed due to avoid double layer of dust caused by + // dropping dust from 16 nodes above mapchunk top. + if ((dtype == NDT_NORMAL || + dtype == NDT_ALLFACES || + dtype == NDT_ALLFACES_OPTIONAL || + dtype == NDT_GLASSLIKE || + dtype == NDT_GLASSLIKE_FRAMED || + dtype == NDT_GLASSLIKE_FRAMED_OPTIONAL) && + ndef->get(c).walkable && c != biome->c_dust) { + VoxelArea::add_y(em, vi, 1); + vm->m_data[vi] = MapNode(biome->c_dust); } + } } + void MapgenBasic::generateCavesNoiseIntersection(s16 max_stone_y) { // cave_width >= 10 is used to disable generation and avoid the intensive @@ -857,12 +855,13 @@ void MapgenBasic::generateCavesNoiseIntersection(s16 max_stone_y) if (node_min.Y > max_stone_y || cave_width >= 10.0f) return; - CavesNoiseIntersection caves_noise( - ndef, m_bmgr, csize, &np_cave1, &np_cave2, seed, cave_width); + CavesNoiseIntersection caves_noise(ndef, m_bmgr, csize, + &np_cave1, &np_cave2, seed, cave_width); caves_noise.generateCaves(vm, node_min, node_max, biomemap); } + void MapgenBasic::generateCavesRandomWalk(s16 max_stone_y, s16 large_cave_ymax) { if (node_min.Y > max_stone_y) @@ -873,8 +872,8 @@ void MapgenBasic::generateCavesRandomWalk(s16 max_stone_y, s16 large_cave_ymax) u32 num_small_caves = ps.range(small_cave_num_min, small_cave_num_max); for (u32 i = 0; i < num_small_caves; i++) { - CavesRandomWalk cave(ndef, &gennotify, seed, water_level, c_water_source, - c_lava_source, large_cave_flooded, biomegen); + CavesRandomWalk cave(ndef, &gennotify, seed, water_level, + c_water_source, c_lava_source, large_cave_flooded, biomegen); cave.makeCave(vm, node_min, node_max, &ps, false, max_stone_y, heightmap); } @@ -887,32 +886,33 @@ void MapgenBasic::generateCavesRandomWalk(s16 max_stone_y, s16 large_cave_ymax) u32 num_large_caves = ps.range(large_cave_num_min, large_cave_num_max); for (u32 i = 0; i < num_large_caves; i++) { - CavesRandomWalk cave(ndef, &gennotify, seed, water_level, c_water_source, - c_lava_source, large_cave_flooded, biomegen); + CavesRandomWalk cave(ndef, &gennotify, seed, water_level, + c_water_source, c_lava_source, large_cave_flooded, biomegen); cave.makeCave(vm, node_min, node_max, &ps, true, max_stone_y, heightmap); } } + bool MapgenBasic::generateCavernsNoise(s16 max_stone_y) { if (node_min.Y > max_stone_y || node_min.Y > cavern_limit) return false; - CavernsNoise caverns_noise(ndef, csize, &np_cavern, seed, cavern_limit, - cavern_taper, cavern_threshold); + CavernsNoise caverns_noise(ndef, csize, &np_cavern, + seed, cavern_limit, cavern_taper, cavern_threshold); return caverns_noise.generateCaverns(vm, node_min, node_max); } + void MapgenBasic::generateDungeons(s16 max_stone_y) { if (node_min.Y > max_stone_y || node_min.Y > dungeon_ymax || node_max.Y < dungeon_ymin) return; - u16 num_dungeons = std::fmax(std::floor(NoisePerlin3D(&np_dungeons, node_min.X, - node_min.Y, node_min.Z, seed)), - 0.0f); + 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; @@ -921,24 +921,24 @@ void MapgenBasic::generateDungeons(s16 max_stone_y) DungeonParams dp; 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); + 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; + 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; + 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; // Get biome at mapchunk midpoint v3s16 chunk_mid = node_min + (node_max - node_min) / v3s16(2, 2, 2); @@ -952,91 +952,102 @@ void MapgenBasic::generateDungeons(s16 max_stone_y) // dungeongen.cpp. 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; - // Fallback to using cobble mapgen alias if defined + dp.c_stair = (biome->c_dungeon_stair != CONTENT_IGNORE) ? + biome->c_dungeon_stair : biome->c_dungeon; + // Fallback to using cobble mapgen alias if defined } else if (c_cobble != CONTENT_IGNORE) { - dp.c_wall = c_cobble; + dp.c_wall = c_cobble; dp.c_alt_wall = CONTENT_IGNORE; - dp.c_stair = c_cobble; - // Fallback to using biome-defined stone + dp.c_stair = c_cobble; + // Fallback to using biome-defined stone } else { - dp.c_wall = biome->c_stone; + dp.c_wall = biome->c_stone; dp.c_alt_wall = CONTENT_IGNORE; - dp.c_stair = biome->c_stone; + dp.c_stair = biome->c_stone; } DungeonGen dgen(ndef, &gennotify, &dp); dgen.generate(vm, blockseed, full_node_min, full_node_max); } + //// //// GenerateNotifier //// -GenerateNotifier::GenerateNotifier(u32 notify_on, const std::set<u32> *notify_on_deco_ids) +GenerateNotifier::GenerateNotifier(u32 notify_on, + const std::set<u32> *notify_on_deco_ids) { m_notify_on = notify_on; m_notify_on_deco_ids = notify_on_deco_ids; } + void GenerateNotifier::setNotifyOn(u32 notify_on) { m_notify_on = notify_on; } -void GenerateNotifier::setNotifyOnDecoIds(const std::set<u32> *notify_on_deco_ids) + +void GenerateNotifier::setNotifyOnDecoIds( + const std::set<u32> *notify_on_deco_ids) { m_notify_on_deco_ids = notify_on_deco_ids; } + bool GenerateNotifier::addEvent(GenNotifyType type, v3s16 pos, u32 id) { if (!(m_notify_on & (1 << type))) return false; if (type == GENNOTIFY_DECORATION && - m_notify_on_deco_ids->find(id) == m_notify_on_deco_ids->cend()) + m_notify_on_deco_ids->find(id) == m_notify_on_deco_ids->cend()) return false; GenNotifyEvent gne; gne.type = type; - gne.pos = pos; - gne.id = id; + gne.pos = pos; + gne.id = id; m_notify_events.push_back(gne); return true; } -void GenerateNotifier::getEvents(std::map<std::string, std::vector<v3s16>> &event_map) + +void GenerateNotifier::getEvents( + std::map<std::string, std::vector<v3s16> > &event_map) { std::list<GenNotifyEvent>::iterator it; for (it = m_notify_events.begin(); it != m_notify_events.end(); ++it) { GenNotifyEvent &gn = *it; - std::string name = (gn.type == GENNOTIFY_DECORATION) - ? "decoration#" + itos(gn.id) - : flagdesc_gennotify[gn.type].name; + std::string name = (gn.type == GENNOTIFY_DECORATION) ? + "decoration#"+ itos(gn.id) : + flagdesc_gennotify[gn.type].name; event_map[name].push_back(gn.pos); } } + void GenerateNotifier::clearEvents() { m_notify_events.clear(); } + //// //// MapgenParams //// + MapgenParams::~MapgenParams() { delete bparams; } + void MapgenParams::readParams(const Settings *settings) { std::string seed_str; @@ -1069,6 +1080,7 @@ void MapgenParams::readParams(const Settings *settings) } } + void MapgenParams::writeParams(Settings *settings) const { settings->set("mg_name", Mapgen::getMapgenName(mgtype)); @@ -1082,6 +1094,7 @@ void MapgenParams::writeParams(Settings *settings) const bparams->writeParams(settings); } + // Calculate exact edges of the outermost mapchunks that are within the // set 'mapgen_limit'. void MapgenParams::calcMapgenEdges() @@ -1098,8 +1111,8 @@ void MapgenParams::calcMapgenEdges() s16 ccfmax = ccmax + MAP_BLOCKSIZE; // Effective mapgen limit, in blocks // Uses same calculation as ServerMap::blockpos_over_mapgen_limit(v3s16 p) - s16 mapgen_limit_b = rangelim(mapgen_limit, 0, MAX_MAP_GENERATION_LIMIT) / - MAP_BLOCKSIZE; + s16 mapgen_limit_b = rangelim(mapgen_limit, + 0, MAX_MAP_GENERATION_LIMIT) / MAP_BLOCKSIZE; // Effective mapgen limits, in nodes s16 mapgen_limit_min = -mapgen_limit_b * MAP_BLOCKSIZE; s16 mapgen_limit_max = (mapgen_limit_b + 1) * MAP_BLOCKSIZE - 1; @@ -1114,6 +1127,7 @@ void MapgenParams::calcMapgenEdges() m_mapgen_edges_calculated = true; } + s32 MapgenParams::getSpawnRangeMax() { if (!m_mapgen_edges_calculated) diff --git a/src/mapgen/mapgen.h b/src/mapgen/mapgen.h index 7ab797658..a92b3b0d0 100644 --- a/src/mapgen/mapgen.h +++ b/src/mapgen/mapgen.h @@ -30,15 +30,15 @@ with this program; if not, write to the Free Software Foundation, Inc., #define MAPGEN_DEFAULT_NAME "v7" /////////////////// Mapgen flags -#define MG_TREES 0x01 // Obsolete. Moved into mgv6 flags -#define MG_CAVES 0x02 -#define MG_DUNGEONS 0x04 -#define MG_FLAT 0x08 // Obsolete. Moved into mgv6 flags -#define MG_LIGHT 0x10 +#define MG_TREES 0x01 // Obsolete. Moved into mgv6 flags +#define MG_CAVES 0x02 +#define MG_DUNGEONS 0x04 +#define MG_FLAT 0x08 // Obsolete. Moved into mgv6 flags +#define MG_LIGHT 0x10 #define MG_DECORATIONS 0x20 -#define MG_BIOMES 0x40 +#define MG_BIOMES 0x40 -typedef u16 biome_t; // copy from mg_biome.h to avoid an unnecessary include +typedef u16 biome_t; // copy from mg_biome.h to avoid an unnecessary include class Settings; class MMVManip; @@ -59,8 +59,7 @@ struct BlockMakeData; class VoxelArea; class Map; -enum MapgenObject -{ +enum MapgenObject { MGOBJ_VMANIP, MGOBJ_HEIGHTMAP, MGOBJ_BIOMEMAP, @@ -69,8 +68,7 @@ enum MapgenObject MGOBJ_GENNOTIFY }; -enum GenNotifyType -{ +enum GenNotifyType { GENNOTIFY_DUNGEON, GENNOTIFY_TEMPLE, GENNOTIFY_CAVE_BEGIN, @@ -81,15 +79,13 @@ enum GenNotifyType NUM_GENNOTIFY_TYPES }; -struct GenNotifyEvent -{ +struct GenNotifyEvent { GenNotifyType type; v3s16 pos; u32 id; }; -class GenerateNotifier -{ +class GenerateNotifier { public: GenerateNotifier() = default; GenerateNotifier(u32 notify_on, const std::set<u32> *notify_on_deco_ids); @@ -97,8 +93,8 @@ public: void setNotifyOn(u32 notify_on); void setNotifyOnDecoIds(const std::set<u32> *notify_on_deco_ids); - bool addEvent(GenNotifyType type, v3s16 pos, u32 id = 0); - void getEvents(std::map<std::string, std::vector<v3s16>> &event_map); + bool addEvent(GenNotifyType type, v3s16 pos, u32 id=0); + void getEvents(std::map<std::string, std::vector<v3s16> > &event_map); void clearEvents(); private: @@ -108,8 +104,7 @@ private: }; // Order must match the order of 'static MapgenDesc g_reg_mapgens[]' in mapgen.cpp -enum MapgenType -{ +enum MapgenType { MAPGEN_V7, MAPGEN_VALLEYS, MAPGEN_CARPATHIAN, @@ -121,8 +116,7 @@ enum MapgenType MAPGEN_INVALID, }; -struct MapgenParams -{ +struct MapgenParams { MapgenParams() = default; virtual ~MapgenParams(); @@ -143,7 +137,7 @@ struct MapgenParams virtual void readParams(const Settings *settings); virtual void writeParams(Settings *settings) const; // Default settings for g_settings such as flags - virtual void setDefaultSettings(Settings *settings){}; + virtual void setDefaultSettings(Settings *settings) {}; s32 getSpawnRangeMax(); @@ -152,6 +146,7 @@ private: bool m_mapgen_edges_calculated = false; }; + /* Generic interface for map generators. All mapgens must inherit this class. If a feature exposed by a public member pointer is not supported by a @@ -161,8 +156,7 @@ private: methods can be used by constructing a Mapgen base class and setting the appropriate public members (e.g. vm, ndef, and so on). */ -class Mapgen -{ +class Mapgen { public: s32 seed = 0; int water_level = 0; @@ -195,16 +189,16 @@ public: s16 findGroundLevel(v2s16 p2d, s16 ymin, s16 ymax); s16 findLiquidSurface(v2s16 p2d, s16 ymin, s16 ymax); void updateHeightmap(v3s16 nmin, v3s16 nmax); - void getSurfaces(v2s16 p2d, s16 ymin, s16 ymax, std::vector<s16> &floors, - std::vector<s16> &ceilings); + void getSurfaces(v2s16 p2d, s16 ymin, s16 ymax, + std::vector<s16> &floors, std::vector<s16> &ceilings); void updateLiquid(UniqueQueue<v3s16> *trans_liquid, v3s16 nmin, v3s16 nmax); void setLighting(u8 light, v3s16 nmin, v3s16 nmax); void lightSpread(VoxelArea &a, std::queue<std::pair<v3s16, u8>> &queue, - const v3s16 &p, u8 light); + const v3s16 &p, u8 light); void calcLighting(v3s16 nmin, v3s16 nmax, v3s16 full_nmin, v3s16 full_nmax, - bool propagate_shadow = true); + bool propagate_shadow = true); void propagateSunlight(v3s16 nmin, v3s16 nmax, bool propagate_shadow); void spreadLight(const v3s16 &nmin, const v3s16 &nmax); @@ -221,11 +215,10 @@ public: // Mapgen management functions static MapgenType getMapgenType(const std::string &mgname); static const char *getMapgenName(MapgenType mgtype); - static Mapgen *createMapgen( - MapgenType mgtype, MapgenParams *params, EmergeParams *emerge); + static Mapgen *createMapgen(MapgenType mgtype, MapgenParams *params, + EmergeParams *emerge); static MapgenParams *createMapgenParams(MapgenType mgtype); - static void getMapgenNames( - std::vector<const char *> *mgnames, bool include_hidden); + static void getMapgenNames(std::vector<const char *> *mgnames, bool include_hidden); static void setDefaultSettings(Settings *settings); private: @@ -249,8 +242,7 @@ private: Note that you must still create your own generateTerrain implementation when inheriting MapgenBasic. */ -class MapgenBasic : public Mapgen -{ +class MapgenBasic : public Mapgen { public: MapgenBasic(int mapgenid, MapgenParams *params, EmergeParams *emerge); virtual ~MapgenBasic(); diff --git a/src/mapgen/mapgen_carpathian.cpp b/src/mapgen/mapgen_carpathian.cpp index 47e33bde9..feb9b428c 100644 --- a/src/mapgen/mapgen_carpathian.cpp +++ b/src/mapgen/mapgen_carpathian.cpp @@ -18,6 +18,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" @@ -37,64 +38,68 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mg_decoration.h" #include "mapgen_carpathian.h" -FlagDesc flagdesc_mapgen_carpathian[] = {{"caverns", MGCARPATHIAN_CAVERNS}, - {"rivers", MGCARPATHIAN_RIVERS}, {NULL, 0}}; + +FlagDesc flagdesc_mapgen_carpathian[] = { + {"caverns", MGCARPATHIAN_CAVERNS}, + {"rivers", MGCARPATHIAN_RIVERS}, + {NULL, 0} +}; + /////////////////////////////////////////////////////////////////////////////// -MapgenCarpathian::MapgenCarpathian(MapgenCarpathianParams *params, EmergeParams *emerge) : - MapgenBasic(MAPGEN_CARPATHIAN, params, emerge) + +MapgenCarpathian::MapgenCarpathian(MapgenCarpathianParams *params, EmergeParams *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; - large_cave_depth = params->large_cave_depth; + 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; + large_cave_depth = params->large_cave_depth; small_cave_num_min = params->small_cave_num_min; small_cave_num_max = params->small_cave_num_max; large_cave_num_min = params->large_cave_num_min; large_cave_num_max = params->large_cave_num_max; large_cave_flooded = params->large_cave_flooded; - cavern_limit = params->cavern_limit; - cavern_taper = params->cavern_taper; - cavern_threshold = params->cavern_threshold; - dungeon_ymin = params->dungeon_ymin; - dungeon_ymax = params->dungeon_ymax; + cavern_limit = params->cavern_limit; + cavern_taper = params->cavern_taper; + cavern_threshold = params->cavern_threshold; + dungeon_ymin = params->dungeon_ymin; + dungeon_ymax = params->dungeon_ymax; grad_wl = 1 - water_level; //// 2D Terrain noise - noise_filler_depth = new Noise(¶ms->np_filler_depth, seed, csize.X, csize.Z); - noise_height1 = new Noise(¶ms->np_height1, seed, csize.X, csize.Z); - noise_height2 = new Noise(¶ms->np_height2, seed, csize.X, csize.Z); - noise_height3 = new Noise(¶ms->np_height3, seed, csize.X, csize.Z); - noise_height4 = new Noise(¶ms->np_height4, seed, csize.X, csize.Z); - noise_hills_terrain = - new Noise(¶ms->np_hills_terrain, seed, csize.X, csize.Z); - noise_ridge_terrain = - new Noise(¶ms->np_ridge_terrain, seed, csize.X, csize.Z); - noise_step_terrain = new Noise(¶ms->np_step_terrain, seed, csize.X, csize.Z); - 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); + noise_filler_depth = new Noise(¶ms->np_filler_depth, seed, csize.X, csize.Z); + noise_height1 = new Noise(¶ms->np_height1, seed, csize.X, csize.Z); + noise_height2 = new Noise(¶ms->np_height2, seed, csize.X, csize.Z); + noise_height3 = new Noise(¶ms->np_height3, seed, csize.X, csize.Z); + noise_height4 = new Noise(¶ms->np_height4, seed, csize.X, csize.Z); + noise_hills_terrain = new Noise(¶ms->np_hills_terrain, seed, csize.X, csize.Z); + noise_ridge_terrain = new Noise(¶ms->np_ridge_terrain, seed, csize.X, csize.Z); + noise_step_terrain = new Noise(¶ms->np_step_terrain, seed, csize.X, csize.Z); + 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); + noise_rivers = new Noise(¶ms->np_rivers, seed, csize.X, csize.Z); //// 3D terrain noise // 1 up 1 down overgeneration - noise_mnt_var = new Noise( - ¶ms->np_mnt_var, seed, csize.X, csize.Y + 2, csize.Z); + noise_mnt_var = new Noise(¶ms->np_mnt_var, seed, csize.X, csize.Y + 2, csize.Z); //// Cave 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_cavern = params->np_cavern; MapgenBasic::np_dungeons = params->np_dungeons; } + MapgenCarpathian::~MapgenCarpathian() { delete noise_filler_depth; @@ -114,118 +119,122 @@ MapgenCarpathian::~MapgenCarpathian() 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_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) + +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_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) { } + void MapgenCarpathianParams::readParams(const Settings *settings) { - settings->getFlagStrNoEx( - "mgcarpathian_spflags", spflags, flagdesc_mapgen_carpathian); + settings->getFlagStrNoEx("mgcarpathian_spflags", spflags, flagdesc_mapgen_carpathian); - settings->getFloatNoEx("mgcarpathian_base_level", base_level); - settings->getFloatNoEx("mgcarpathian_river_width", river_width); - settings->getFloatNoEx("mgcarpathian_river_depth", river_depth); + 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->getU16NoEx("mgcarpathian_small_cave_num_min", small_cave_num_min); - settings->getU16NoEx("mgcarpathian_small_cave_num_max", small_cave_num_max); - settings->getU16NoEx("mgcarpathian_large_cave_num_min", large_cave_num_min); - settings->getU16NoEx("mgcarpathian_large_cave_num_max", large_cave_num_max); + settings->getFloatNoEx("mgcarpathian_cave_width", cave_width); + settings->getS16NoEx("mgcarpathian_large_cave_depth", large_cave_depth); + settings->getU16NoEx("mgcarpathian_small_cave_num_min", small_cave_num_min); + settings->getU16NoEx("mgcarpathian_small_cave_num_max", small_cave_num_max); + settings->getU16NoEx("mgcarpathian_large_cave_num_min", large_cave_num_min); + settings->getU16NoEx("mgcarpathian_large_cave_num_max", large_cave_num_max); settings->getFloatNoEx("mgcarpathian_large_cave_flooded", large_cave_flooded); - settings->getS16NoEx("mgcarpathian_cavern_limit", cavern_limit); - settings->getS16NoEx("mgcarpathian_cavern_taper", cavern_taper); - settings->getFloatNoEx("mgcarpathian_cavern_threshold", cavern_threshold); - settings->getS16NoEx("mgcarpathian_dungeon_ymin", dungeon_ymin); - settings->getS16NoEx("mgcarpathian_dungeon_ymax", dungeon_ymax); - - settings->getNoiseParams("mgcarpathian_np_filler_depth", np_filler_depth); - settings->getNoiseParams("mgcarpathian_np_height1", np_height1); - settings->getNoiseParams("mgcarpathian_np_height2", np_height2); - settings->getNoiseParams("mgcarpathian_np_height3", np_height3); - settings->getNoiseParams("mgcarpathian_np_height4", np_height4); + settings->getS16NoEx("mgcarpathian_cavern_limit", cavern_limit); + settings->getS16NoEx("mgcarpathian_cavern_taper", cavern_taper); + settings->getFloatNoEx("mgcarpathian_cavern_threshold", cavern_threshold); + settings->getS16NoEx("mgcarpathian_dungeon_ymin", dungeon_ymin); + settings->getS16NoEx("mgcarpathian_dungeon_ymax", dungeon_ymax); + + settings->getNoiseParams("mgcarpathian_np_filler_depth", np_filler_depth); + settings->getNoiseParams("mgcarpathian_np_height1", np_height1); + settings->getNoiseParams("mgcarpathian_np_height2", np_height2); + settings->getNoiseParams("mgcarpathian_np_height3", np_height3); + settings->getNoiseParams("mgcarpathian_np_height4", np_height4); settings->getNoiseParams("mgcarpathian_np_hills_terrain", np_hills_terrain); settings->getNoiseParams("mgcarpathian_np_ridge_terrain", np_ridge_terrain); - settings->getNoiseParams("mgcarpathian_np_step_terrain", np_step_terrain); - 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); + settings->getNoiseParams("mgcarpathian_np_step_terrain", np_step_terrain); + 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); - settings->setFloat("mgcarpathian_base_level", base_level); - settings->setFloat("mgcarpathian_river_width", river_width); - settings->setFloat("mgcarpathian_river_depth", river_depth); + 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->setU16("mgcarpathian_small_cave_num_min", small_cave_num_min); - settings->setU16("mgcarpathian_small_cave_num_max", small_cave_num_max); - settings->setU16("mgcarpathian_large_cave_num_min", large_cave_num_min); - settings->setU16("mgcarpathian_large_cave_num_max", large_cave_num_max); + settings->setFloat("mgcarpathian_cave_width", cave_width); + settings->setS16("mgcarpathian_large_cave_depth", large_cave_depth); + settings->setU16("mgcarpathian_small_cave_num_min", small_cave_num_min); + settings->setU16("mgcarpathian_small_cave_num_max", small_cave_num_max); + settings->setU16("mgcarpathian_large_cave_num_min", large_cave_num_min); + settings->setU16("mgcarpathian_large_cave_num_max", large_cave_num_max); settings->setFloat("mgcarpathian_large_cave_flooded", large_cave_flooded); - settings->setS16("mgcarpathian_cavern_limit", cavern_limit); - settings->setS16("mgcarpathian_cavern_taper", cavern_taper); - settings->setFloat("mgcarpathian_cavern_threshold", cavern_threshold); - settings->setS16("mgcarpathian_dungeon_ymin", dungeon_ymin); - settings->setS16("mgcarpathian_dungeon_ymax", dungeon_ymax); - - settings->setNoiseParams("mgcarpathian_np_filler_depth", np_filler_depth); - settings->setNoiseParams("mgcarpathian_np_height1", np_height1); - settings->setNoiseParams("mgcarpathian_np_height2", np_height2); - settings->setNoiseParams("mgcarpathian_np_height3", np_height3); - settings->setNoiseParams("mgcarpathian_np_height4", np_height4); + settings->setS16("mgcarpathian_cavern_limit", cavern_limit); + settings->setS16("mgcarpathian_cavern_taper", cavern_taper); + settings->setFloat("mgcarpathian_cavern_threshold", cavern_threshold); + settings->setS16("mgcarpathian_dungeon_ymin", dungeon_ymin); + settings->setS16("mgcarpathian_dungeon_ymax", dungeon_ymax); + + settings->setNoiseParams("mgcarpathian_np_filler_depth", np_filler_depth); + settings->setNoiseParams("mgcarpathian_np_height1", np_height1); + settings->setNoiseParams("mgcarpathian_np_height2", np_height2); + settings->setNoiseParams("mgcarpathian_np_height3", np_height3); + settings->setNoiseParams("mgcarpathian_np_height4", np_height4); settings->setNoiseParams("mgcarpathian_np_hills_terrain", np_hills_terrain); settings->setNoiseParams("mgcarpathian_np_ridge_terrain", np_ridge_terrain); - settings->setNoiseParams("mgcarpathian_np_step_terrain", np_step_terrain); - 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); + settings->setNoiseParams("mgcarpathian_np_step_terrain", np_step_terrain); + 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); } + void MapgenCarpathianParams::setDefaultSettings(Settings *settings) { settings->setDefault("mgcarpathian_spflags", flagdesc_mapgen_carpathian, - MGCARPATHIAN_CAVERNS); + MGCARPATHIAN_CAVERNS); } //////////////////////////////////////////////////////////////////////////////// + // Lerp function inline float MapgenCarpathian::getLerp(float noise1, float noise2, float mod) { @@ -242,8 +251,10 @@ float MapgenCarpathian::getSteps(float noise) return (k + s) * w; } + //////////////////////////////////////////////////////////////////////////////// + void MapgenCarpathian::makeChunk(BlockMakeData *data) { // Pre-conditions @@ -297,8 +308,8 @@ void MapgenCarpathian::makeChunk(BlockMakeData *data) // Disable large randomwalk caves in this mapchunk by setting // 'large cave depth' to world base. Avoids excessive liquid in // large caverns and floating blobs of overgenerated liquid. - generateCavesRandomWalk( - stone_surface_max_y, -MAX_MAP_GENERATION_LIMIT); + generateCavesRandomWalk(stone_surface_max_y, + -MAX_MAP_GENERATION_LIMIT); else generateCavesRandomWalk(stone_surface_max_y, large_cave_depth); } @@ -330,15 +341,16 @@ void MapgenCarpathian::makeChunk(BlockMakeData *data) this->generating = false; } + //////////////////////////////////////////////////////////////////////////////// + int MapgenCarpathian::getSpawnLevelAtPoint(v2s16 p) { // 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; + 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 } @@ -348,13 +360,11 @@ int MapgenCarpathian::getSpawnLevelAtPoint(v2s16 p) 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 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 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)); @@ -366,8 +376,7 @@ int MapgenCarpathian::getSpawnLevelAtPoint(v2s16 p) 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; + 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) { @@ -393,8 +402,7 @@ int MapgenCarpathian::getSpawnLevelAtPoint(v2s16 p) 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)); + 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; @@ -408,16 +416,14 @@ int MapgenCarpathian::getSpawnLevelAtPoint(v2s16 p) if (valley < 0.0f) { // River channel surface_level = std::fmin(surface_level, - water_level - std::sqrt(-valley) * - river_depth); + water_level - std::sqrt(-valley) * river_depth); } else if (surface_level > water_level) { // Valley slopes - surface_level = water_level + - (surface_level - water_level) * valley; + surface_level = water_level + (surface_level - water_level) * valley; } } - if (y < surface_level) { // TODO '<=' fix from generateTerrain() + if (y < surface_level) { //TODO '<=' fix from generateTerrain() // solid node solid_below = true; cons_non_solid = 0; @@ -432,8 +438,10 @@ int MapgenCarpathian::getSpawnLevelAtPoint(v2s16 p) return MAX_MAP_GENERATION_LIMIT; // No suitable spawn point found } + //////////////////////////////////////////////////////////////////////////////// + int MapgenCarpathian::generateTerrain() { MapNode mn_air(CONTENT_AIR); @@ -462,117 +470,108 @@ int MapgenCarpathian::generateTerrain() u32 index2d = 0; for (s16 z = node_min.Z; z <= node_max.Z; z++) - for (s16 x = node_min.X; x <= node_max.X; x++, index2d++) { - // Hill/Mountain height (hilliness) - float height1 = noise_height1->result[index2d]; - float height2 = noise_height2->result[index2d]; - float height3 = noise_height3->result[index2d]; - float height4 = noise_height4->result[index2d]; - - // Rolling hills - float hterabs = std::fabs(noise_hills_terrain->result[index2d]); - float n_hills = noise_hills->result[index2d]; - float hill_mnt = hterabs * hterabs * hterabs * n_hills * n_hills; - - // Ridged mountains - 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.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); - } + for (s16 x = node_min.X; x <= node_max.X; x++, index2d++) { + // Hill/Mountain height (hilliness) + float height1 = noise_height1->result[index2d]; + float height2 = noise_height2->result[index2d]; + float height3 = noise_height3->result[index2d]; + float height4 = noise_height4->result[index2d]; + + // Rolling hills + float hterabs = std::fabs(noise_hills_terrain->result[index2d]); + float n_hills = noise_hills->result[index2d]; + float hill_mnt = hterabs * hterabs * hterabs * n_hills * n_hills; + + // Ridged mountains + 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.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); - - for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++, - index3d += ystride, VoxelArea::add_y(em, vi, 1)) { - if (vm->m_data[vi].getContent() != CONTENT_IGNORE) - continue; - - // Combine height noises and apply 3D variation - float mnt_var = noise_mnt_var->result[index3d]; - 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); - - // 'hilliness' determines whether hills/mountains are - // small or large - 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; - - // Gradient & shallow seabed - s32 grad = (y < water_level) - ? grad_wl + (water_level - y) * 3 - : 1 - y; - - // Final terrain level - float mountains = - hills + ridged_mountains + step_mountains; - float surface_level = base_level + mountains + grad; - - // 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; - } - } + // 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); + + for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; + y++, + index3d += ystride, + VoxelArea::add_y(em, vi, 1)) { + if (vm->m_data[vi].getContent() != CONTENT_IGNORE) + continue; + + // Combine height noises and apply 3D variation + float mnt_var = noise_mnt_var->result[index3d]; + 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); + + // 'hilliness' determines whether hills/mountains are + // small or large + 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; + + // Gradient & shallow seabed + s32 grad = (y < water_level) ? grad_wl + (water_level - y) * 3 : + 1 - y; + + // Final terrain level + float mountains = hills + ridged_mountains + step_mountains; + float surface_level = base_level + mountains + grad; - if (y < surface_level) { // TODO '<=' - vm->m_data[vi] = mn_stone; // Stone - if (y > stone_surface_max_y) - stone_surface_max_y = y; - } else if (y <= water_level) { - vm->m_data[vi] = mn_water; // Sea water - } else { - vm->m_data[vi] = mn_air; // Air + // 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; + } else if (y <= water_level) { + vm->m_data[vi] = mn_water; // Sea water + } else { + vm->m_data[vi] = mn_air; // Air + } } + } return stone_surface_max_y; } diff --git a/src/mapgen/mapgen_carpathian.h b/src/mapgen/mapgen_carpathian.h index 5c44c16e3..31b2b91d8 100644 --- a/src/mapgen/mapgen_carpathian.h +++ b/src/mapgen/mapgen_carpathian.h @@ -23,31 +23,32 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mapgen.h" #define MGCARPATHIAN_CAVERNS 0x01 -#define MGCARPATHIAN_RIVERS 0x02 +#define MGCARPATHIAN_RIVERS 0x02 class BiomeManager; 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; - - float cave_width = 0.09f; - s16 large_cave_depth = -33; - u16 small_cave_num_min = 0; - u16 small_cave_num_max = 0; - u16 large_cave_num_min = 0; - u16 large_cave_num_max = 2; + float base_level = 12.0f; + float river_width = 0.05f; + float river_depth = 24.0f; + float valley_width = 0.25f; + + float cave_width = 0.09f; + s16 large_cave_depth = -33; + u16 small_cave_num_min = 0; + u16 small_cave_num_max = 0; + u16 large_cave_num_min = 0; + u16 large_cave_num_max = 2; float large_cave_flooded = 0.5f; - s16 cavern_limit = -256; - s16 cavern_taper = 256; - float cavern_threshold = 0.7f; - s16 dungeon_ymin = -31000; - s16 dungeon_ymax = 31000; + s16 cavern_limit = -256; + s16 cavern_taper = 256; + float cavern_threshold = 0.7f; + s16 dungeon_ymin = -31000; + s16 dungeon_ymax = 31000; NoiseParams np_filler_depth; NoiseParams np_height1; diff --git a/src/mapgen/mapgen_flat.cpp b/src/mapgen/mapgen_flat.cpp index e24f1e4a1..369777ad2 100644 --- a/src/mapgen/mapgen_flat.cpp +++ b/src/mapgen/mapgen_flat.cpp @@ -18,6 +18,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" @@ -36,29 +37,34 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mg_decoration.h" #include "mapgen_flat.h" + FlagDesc flagdesc_mapgen_flat[] = { - {"lakes", MGFLAT_LAKES}, {"hills", MGFLAT_HILLS}, {NULL, 0}}; + {"lakes", MGFLAT_LAKES}, + {"hills", MGFLAT_HILLS}, + {NULL, 0} +}; /////////////////////////////////////////////////////////////////////////////////////// -MapgenFlat::MapgenFlat(MapgenFlatParams *params, EmergeParams *emerge) : - MapgenBasic(MAPGEN_FLAT, params, emerge) + +MapgenFlat::MapgenFlat(MapgenFlatParams *params, EmergeParams *emerge) + : MapgenBasic(MAPGEN_FLAT, params, emerge) { - spflags = params->spflags; - ground_level = params->ground_level; - large_cave_depth = params->large_cave_depth; + spflags = params->spflags; + ground_level = params->ground_level; + large_cave_depth = params->large_cave_depth; small_cave_num_min = params->small_cave_num_min; small_cave_num_max = params->small_cave_num_max; large_cave_num_min = params->large_cave_num_min; large_cave_num_max = params->large_cave_num_max; large_cave_flooded = params->large_cave_flooded; - cave_width = params->cave_width; - lake_threshold = params->lake_threshold; - lake_steepness = params->lake_steepness; - hill_threshold = params->hill_threshold; - hill_steepness = params->hill_steepness; - dungeon_ymin = params->dungeon_ymin; - dungeon_ymax = params->dungeon_ymax; + cave_width = params->cave_width; + lake_threshold = params->lake_threshold; + lake_steepness = params->lake_steepness; + hill_threshold = params->hill_threshold; + hill_steepness = params->hill_steepness; + dungeon_ymin = params->dungeon_ymin; + dungeon_ymax = params->dungeon_ymax; // 2D noise noise_filler_depth = new Noise(¶ms->np_filler_depth, seed, csize.X, csize.Z); @@ -66,11 +72,12 @@ MapgenFlat::MapgenFlat(MapgenFlatParams *params, EmergeParams *emerge) : 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; } + MapgenFlat::~MapgenFlat() { delete noise_filler_depth; @@ -79,86 +86,92 @@ MapgenFlat::~MapgenFlat() delete noise_terrain; } -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_dungeons(0.9, 0.5, v3f(500, 500, 500), 0, 2, 0.8, 2.0) + +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_dungeons (0.9, 0.5, v3f(500, 500, 500), 0, 2, 0.8, 2.0) { } + void MapgenFlatParams::readParams(const Settings *settings) { settings->getFlagStrNoEx("mgflat_spflags", spflags, flagdesc_mapgen_flat); - settings->getS16NoEx("mgflat_ground_level", ground_level); - settings->getS16NoEx("mgflat_large_cave_depth", large_cave_depth); - settings->getU16NoEx("mgflat_small_cave_num_min", small_cave_num_min); - settings->getU16NoEx("mgflat_small_cave_num_max", small_cave_num_max); - settings->getU16NoEx("mgflat_large_cave_num_min", large_cave_num_min); - settings->getU16NoEx("mgflat_large_cave_num_max", large_cave_num_max); + settings->getS16NoEx("mgflat_ground_level", ground_level); + settings->getS16NoEx("mgflat_large_cave_depth", large_cave_depth); + settings->getU16NoEx("mgflat_small_cave_num_min", small_cave_num_min); + settings->getU16NoEx("mgflat_small_cave_num_max", small_cave_num_max); + settings->getU16NoEx("mgflat_large_cave_num_min", large_cave_num_min); + settings->getU16NoEx("mgflat_large_cave_num_max", large_cave_num_max); settings->getFloatNoEx("mgflat_large_cave_flooded", large_cave_flooded); - settings->getFloatNoEx("mgflat_cave_width", cave_width); - settings->getFloatNoEx("mgflat_lake_threshold", lake_threshold); - settings->getFloatNoEx("mgflat_lake_steepness", lake_steepness); - settings->getFloatNoEx("mgflat_hill_threshold", hill_threshold); - settings->getFloatNoEx("mgflat_hill_steepness", hill_steepness); - settings->getS16NoEx("mgflat_dungeon_ymin", dungeon_ymin); - settings->getS16NoEx("mgflat_dungeon_ymax", dungeon_ymax); - - settings->getNoiseParams("mgflat_np_terrain", np_terrain); + settings->getFloatNoEx("mgflat_cave_width", cave_width); + settings->getFloatNoEx("mgflat_lake_threshold", lake_threshold); + settings->getFloatNoEx("mgflat_lake_steepness", lake_steepness); + settings->getFloatNoEx("mgflat_hill_threshold", hill_threshold); + settings->getFloatNoEx("mgflat_hill_steepness", hill_steepness); + settings->getS16NoEx("mgflat_dungeon_ymin", dungeon_ymin); + settings->getS16NoEx("mgflat_dungeon_ymax", dungeon_ymax); + + settings->getNoiseParams("mgflat_np_terrain", np_terrain); 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); + settings->getNoiseParams("mgflat_np_cave1", np_cave1); + settings->getNoiseParams("mgflat_np_cave2", np_cave2); + settings->getNoiseParams("mgflat_np_dungeons", np_dungeons); } + void MapgenFlatParams::writeParams(Settings *settings) const { settings->setFlagStr("mgflat_spflags", spflags, flagdesc_mapgen_flat); - settings->setS16("mgflat_ground_level", ground_level); - settings->setS16("mgflat_large_cave_depth", large_cave_depth); - settings->setU16("mgflat_small_cave_num_min", small_cave_num_min); - settings->setU16("mgflat_small_cave_num_max", small_cave_num_max); - settings->setU16("mgflat_large_cave_num_min", large_cave_num_min); - settings->setU16("mgflat_large_cave_num_max", large_cave_num_max); + settings->setS16("mgflat_ground_level", ground_level); + settings->setS16("mgflat_large_cave_depth", large_cave_depth); + settings->setU16("mgflat_small_cave_num_min", small_cave_num_min); + settings->setU16("mgflat_small_cave_num_max", small_cave_num_max); + settings->setU16("mgflat_large_cave_num_min", large_cave_num_min); + settings->setU16("mgflat_large_cave_num_max", large_cave_num_max); settings->setFloat("mgflat_large_cave_flooded", large_cave_flooded); - settings->setFloat("mgflat_cave_width", cave_width); - settings->setFloat("mgflat_lake_threshold", lake_threshold); - settings->setFloat("mgflat_lake_steepness", lake_steepness); - settings->setFloat("mgflat_hill_threshold", hill_threshold); - settings->setFloat("mgflat_hill_steepness", hill_steepness); - settings->setS16("mgflat_dungeon_ymin", dungeon_ymin); - settings->setS16("mgflat_dungeon_ymax", dungeon_ymax); - - settings->setNoiseParams("mgflat_np_terrain", np_terrain); + settings->setFloat("mgflat_cave_width", cave_width); + settings->setFloat("mgflat_lake_threshold", lake_threshold); + settings->setFloat("mgflat_lake_steepness", lake_steepness); + settings->setFloat("mgflat_hill_threshold", hill_threshold); + settings->setFloat("mgflat_hill_steepness", hill_steepness); + settings->setS16("mgflat_dungeon_ymin", dungeon_ymin); + settings->setS16("mgflat_dungeon_ymax", dungeon_ymax); + + settings->setNoiseParams("mgflat_np_terrain", np_terrain); 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); + settings->setNoiseParams("mgflat_np_cave1", np_cave1); + settings->setNoiseParams("mgflat_np_cave2", np_cave2); + settings->setNoiseParams("mgflat_np_dungeons", np_dungeons); } + void MapgenFlatParams::setDefaultSettings(Settings *settings) { settings->setDefault("mgflat_spflags", flagdesc_mapgen_flat, 0); } + ///////////////////////////////////////////////////////////////// + int MapgenFlat::getSpawnLevelAtPoint(v2s16 p) { 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; + 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) { s16 depress = (lake_threshold - n_terrain) * lake_steepness; stone_level = ground_level - depress; } else if ((spflags & MGFLAT_HILLS) && n_terrain > hill_threshold) { s16 rise = (n_terrain - hill_threshold) * hill_steepness; - stone_level = ground_level + rise; + stone_level = ground_level + rise; } if (ground_level < water_level) @@ -174,22 +187,23 @@ int MapgenFlat::getSpawnLevelAtPoint(v2s16 p) return MAX_MAP_GENERATION_LIMIT; } + void MapgenFlat::makeChunk(BlockMakeData *data) { // Pre-conditions 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; + this->vm = data->vmanip; this->ndef = data->nodedef; - // TimeTaker t("makeChunk"); + //TimeTaker t("makeChunk"); v3s16 blockpos_min = data->blockpos_min; v3s16 blockpos_max = data->blockpos_max; @@ -233,20 +247,21 @@ void MapgenFlat::makeChunk(BlockMakeData *data) if (flags & MG_BIOMES) dustTopNodes(); - // printf("makeChunk: %dms\n", t.stop()); + //printf("makeChunk: %dms\n", t.stop()); updateLiquid(&data->transforming_liquid, full_node_min, full_node_max); if (flags & MG_LIGHT) calcLighting(node_min - v3s16(0, 1, 0), node_max + v3s16(0, 1, 0), - full_node_min, full_node_max); + full_node_min, full_node_max); - // setLighting(node_min - v3s16(1, 0, 1) * MAP_BLOCKSIZE, + //setLighting(node_min - v3s16(1, 0, 1) * MAP_BLOCKSIZE, // node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE, 0xFF); this->generating = false; } + s16 MapgenFlat::generateTerrain() { MapNode n_air(CONTENT_AIR); @@ -262,36 +277,34 @@ s16 MapgenFlat::generateTerrain() noise_terrain->perlinMap2D(node_min.X, node_min.Z); for (s16 z = node_min.Z; z <= node_max.Z; z++) - for (s16 x = node_min.X; x <= node_max.X; x++, ni2d++) { - s16 stone_level = ground_level; - float n_terrain = use_noise ? noise_terrain->result[ni2d] : 0.0f; - - if ((spflags & MGFLAT_LAKES) && n_terrain < lake_threshold) { - s16 depress = (lake_threshold - n_terrain) * - lake_steepness; - stone_level = ground_level - depress; - } else if ((spflags & MGFLAT_HILLS) && - n_terrain > hill_threshold) { - s16 rise = (n_terrain - hill_threshold) * hill_steepness; - stone_level = ground_level + rise; - } + for (s16 x = node_min.X; x <= node_max.X; x++, ni2d++) { + s16 stone_level = ground_level; + float n_terrain = use_noise ? noise_terrain->result[ni2d] : 0.0f; + + if ((spflags & MGFLAT_LAKES) && n_terrain < lake_threshold) { + s16 depress = (lake_threshold - n_terrain) * lake_steepness; + stone_level = ground_level - depress; + } else if ((spflags & MGFLAT_HILLS) && n_terrain > hill_threshold) { + s16 rise = (n_terrain - hill_threshold) * hill_steepness; + stone_level = ground_level + rise; + } - u32 vi = 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[vi].getContent() == CONTENT_IGNORE) { - if (y <= stone_level) { - 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; - } + u32 vi = 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[vi].getContent() == CONTENT_IGNORE) { + if (y <= stone_level) { + 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; } - VoxelArea::add_y(em, vi, 1); } + VoxelArea::add_y(em, vi, 1); } + } return stone_surface_max_y; } diff --git a/src/mapgen/mapgen_fractal.cpp b/src/mapgen/mapgen_fractal.cpp index fca8c9196..cb55bc288 100644 --- a/src/mapgen/mapgen_fractal.cpp +++ b/src/mapgen/mapgen_fractal.cpp @@ -18,6 +18,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 <cmath> #include "voxel.h" @@ -37,32 +38,37 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mg_decoration.h" #include "mapgen_fractal.h" -FlagDesc flagdesc_mapgen_fractal[] = {{"terrain", MGFRACTAL_TERRAIN}, {NULL, 0}}; + +FlagDesc flagdesc_mapgen_fractal[] = { + {"terrain", MGFRACTAL_TERRAIN}, + {NULL, 0} +}; /////////////////////////////////////////////////////////////////////////////////////// -MapgenFractal::MapgenFractal(MapgenFractalParams *params, EmergeParams *emerge) : - MapgenBasic(MAPGEN_FRACTAL, params, emerge) + +MapgenFractal::MapgenFractal(MapgenFractalParams *params, EmergeParams *emerge) + : MapgenBasic(MAPGEN_FRACTAL, params, emerge) { - spflags = params->spflags; - cave_width = params->cave_width; - large_cave_depth = params->large_cave_depth; + spflags = params->spflags; + cave_width = params->cave_width; + large_cave_depth = params->large_cave_depth; small_cave_num_min = params->small_cave_num_min; small_cave_num_max = params->small_cave_num_max; large_cave_num_min = params->large_cave_num_min; large_cave_num_max = params->large_cave_num_max; large_cave_flooded = params->large_cave_flooded; - dungeon_ymin = params->dungeon_ymin; - dungeon_ymax = params->dungeon_ymax; - fractal = params->fractal; - iterations = params->iterations; - scale = params->scale; - offset = params->offset; - slice_w = params->slice_w; - julia_x = params->julia_x; - julia_y = params->julia_y; - julia_z = params->julia_z; - julia_w = params->julia_w; + dungeon_ymin = params->dungeon_ymin; + dungeon_ymax = params->dungeon_ymax; + fractal = params->fractal; + iterations = params->iterations; + scale = params->scale; + offset = params->offset; + slice_w = params->slice_w; + julia_x = params->julia_x; + julia_y = params->julia_y; + julia_z = params->julia_z; + julia_w = params->julia_w; //// 2D noise if (spflags & MGFRACTAL_TERRAIN) @@ -73,99 +79,106 @@ MapgenFractal::MapgenFractal(MapgenFractalParams *params, EmergeParams *emerge) //// 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; + MapgenBasic::np_cave1 = params->np_cave1; + MapgenBasic::np_cave2 = params->np_cave2; formula = fractal / 2 + fractal % 2; - julia = fractal % 2 == 0; + julia = fractal % 2 == 0; } + MapgenFractal::~MapgenFractal() { delete noise_seabed; delete noise_filler_depth; } -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_dungeons(0.9, 0.5, v3f(500, 500, 500), 0, 2, 0.8, 2.0) + +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_dungeons (0.9, 0.5, v3f(500, 500, 500), 0, 2, 0.8, 2.0) { } + void MapgenFractalParams::readParams(const Settings *settings) { settings->getFlagStrNoEx("mgfractal_spflags", spflags, flagdesc_mapgen_fractal); - settings->getFloatNoEx("mgfractal_cave_width", cave_width); - settings->getS16NoEx("mgfractal_large_cave_depth", large_cave_depth); - settings->getU16NoEx("mgfractal_small_cave_num_min", small_cave_num_min); - settings->getU16NoEx("mgfractal_small_cave_num_max", small_cave_num_max); - settings->getU16NoEx("mgfractal_large_cave_num_min", large_cave_num_min); - settings->getU16NoEx("mgfractal_large_cave_num_max", large_cave_num_max); + settings->getFloatNoEx("mgfractal_cave_width", cave_width); + settings->getS16NoEx("mgfractal_large_cave_depth", large_cave_depth); + settings->getU16NoEx("mgfractal_small_cave_num_min", small_cave_num_min); + settings->getU16NoEx("mgfractal_small_cave_num_max", small_cave_num_max); + settings->getU16NoEx("mgfractal_large_cave_num_min", large_cave_num_min); + settings->getU16NoEx("mgfractal_large_cave_num_max", large_cave_num_max); settings->getFloatNoEx("mgfractal_large_cave_flooded", large_cave_flooded); - settings->getS16NoEx("mgfractal_dungeon_ymin", dungeon_ymin); - settings->getS16NoEx("mgfractal_dungeon_ymax", dungeon_ymax); - settings->getU16NoEx("mgfractal_fractal", fractal); - settings->getU16NoEx("mgfractal_iterations", iterations); - settings->getV3FNoEx("mgfractal_scale", scale); - settings->getV3FNoEx("mgfractal_offset", offset); - settings->getFloatNoEx("mgfractal_slice_w", slice_w); - settings->getFloatNoEx("mgfractal_julia_x", julia_x); - settings->getFloatNoEx("mgfractal_julia_y", julia_y); - settings->getFloatNoEx("mgfractal_julia_z", julia_z); - settings->getFloatNoEx("mgfractal_julia_w", julia_w); - - settings->getNoiseParams("mgfractal_np_seabed", np_seabed); + settings->getS16NoEx("mgfractal_dungeon_ymin", dungeon_ymin); + settings->getS16NoEx("mgfractal_dungeon_ymax", dungeon_ymax); + settings->getU16NoEx("mgfractal_fractal", fractal); + settings->getU16NoEx("mgfractal_iterations", iterations); + settings->getV3FNoEx("mgfractal_scale", scale); + settings->getV3FNoEx("mgfractal_offset", offset); + settings->getFloatNoEx("mgfractal_slice_w", slice_w); + settings->getFloatNoEx("mgfractal_julia_x", julia_x); + settings->getFloatNoEx("mgfractal_julia_y", julia_y); + settings->getFloatNoEx("mgfractal_julia_z", julia_z); + settings->getFloatNoEx("mgfractal_julia_w", julia_w); + + settings->getNoiseParams("mgfractal_np_seabed", np_seabed); 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); + settings->getNoiseParams("mgfractal_np_cave1", np_cave1); + settings->getNoiseParams("mgfractal_np_cave2", np_cave2); + settings->getNoiseParams("mgfractal_np_dungeons", np_dungeons); } + void MapgenFractalParams::writeParams(Settings *settings) const { settings->setFlagStr("mgfractal_spflags", spflags, flagdesc_mapgen_fractal); - settings->setFloat("mgfractal_cave_width", cave_width); - settings->setS16("mgfractal_large_cave_depth", large_cave_depth); - settings->setU16("mgfractal_small_cave_num_min", small_cave_num_min); - settings->setU16("mgfractal_small_cave_num_max", small_cave_num_max); - settings->setU16("mgfractal_large_cave_num_min", large_cave_num_min); - settings->setU16("mgfractal_large_cave_num_max", large_cave_num_max); + settings->setFloat("mgfractal_cave_width", cave_width); + settings->setS16("mgfractal_large_cave_depth", large_cave_depth); + settings->setU16("mgfractal_small_cave_num_min", small_cave_num_min); + settings->setU16("mgfractal_small_cave_num_max", small_cave_num_max); + settings->setU16("mgfractal_large_cave_num_min", large_cave_num_min); + settings->setU16("mgfractal_large_cave_num_max", large_cave_num_max); settings->setFloat("mgfractal_large_cave_flooded", large_cave_flooded); - settings->setS16("mgfractal_dungeon_ymin", dungeon_ymin); - settings->setS16("mgfractal_dungeon_ymax", dungeon_ymax); - settings->setU16("mgfractal_fractal", fractal); - settings->setU16("mgfractal_iterations", iterations); - settings->setV3F("mgfractal_scale", scale); - settings->setV3F("mgfractal_offset", offset); - settings->setFloat("mgfractal_slice_w", slice_w); - settings->setFloat("mgfractal_julia_x", julia_x); - settings->setFloat("mgfractal_julia_y", julia_y); - settings->setFloat("mgfractal_julia_z", julia_z); - settings->setFloat("mgfractal_julia_w", julia_w); - - settings->setNoiseParams("mgfractal_np_seabed", np_seabed); + settings->setS16("mgfractal_dungeon_ymin", dungeon_ymin); + settings->setS16("mgfractal_dungeon_ymax", dungeon_ymax); + settings->setU16("mgfractal_fractal", fractal); + settings->setU16("mgfractal_iterations", iterations); + settings->setV3F("mgfractal_scale", scale); + settings->setV3F("mgfractal_offset", offset); + settings->setFloat("mgfractal_slice_w", slice_w); + settings->setFloat("mgfractal_julia_x", julia_x); + settings->setFloat("mgfractal_julia_y", julia_y); + settings->setFloat("mgfractal_julia_z", julia_z); + settings->setFloat("mgfractal_julia_w", julia_w); + + settings->setNoiseParams("mgfractal_np_seabed", np_seabed); 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); + settings->setNoiseParams("mgfractal_np_cave1", np_cave1); + settings->setNoiseParams("mgfractal_np_cave2", np_cave2); + settings->setNoiseParams("mgfractal_np_dungeons", np_dungeons); } + void MapgenFractalParams::setDefaultSettings(Settings *settings) { - settings->setDefault( - "mgfractal_spflags", flagdesc_mapgen_fractal, MGFRACTAL_TERRAIN); + settings->setDefault("mgfractal_spflags", flagdesc_mapgen_fractal, + MGFRACTAL_TERRAIN); } + ///////////////////////////////////////////////////////////////// + int MapgenFractal::getSpawnLevelAtPoint(v2s16 p) { 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 + 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) { @@ -187,22 +200,23 @@ int MapgenFractal::getSpawnLevelAtPoint(v2s16 p) } } - return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point + return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point } + void MapgenFractal::makeChunk(BlockMakeData *data) { // Pre-conditions 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); - // TimeTaker t("makeChunk"); + //TimeTaker t("makeChunk"); this->generating = true; this->vm = data->vmanip; @@ -257,18 +271,19 @@ void MapgenFractal::makeChunk(BlockMakeData *data) // 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); + full_node_min, full_node_max); this->generating = false; - // printf("makeChunk: %lums\n", t.stop()); + //printf("makeChunk: %lums\n", t.stop()); } + bool MapgenFractal::getFractalAtPoint(s16 x, s16 y, s16 z) { float cx, cy, cz, cw, ox, oy, oz, ow; - if (julia) { // Julia set + if (julia) { // Julia set cx = julia_x; cy = julia_y; cz = julia_z; @@ -277,7 +292,7 @@ bool MapgenFractal::getFractalAtPoint(s16 x, s16 y, s16 z) oy = (float)y / scale.Y - offset.Y; oz = (float)z / scale.Z - offset.Z; ow = slice_w; - } else { // Mandelbrot set + } else { // Mandelbrot set cx = (float)x / scale.X - offset.X; cy = (float)y / scale.Y - offset.Y; cz = (float)z / scale.Z - offset.Z; @@ -326,8 +341,7 @@ bool MapgenFractal::getFractalAtPoint(s16 x, s16 y, s16 z) nz = -2.0f * ox * oz + cz; break; case 6: // 3D "Christmas Tree" - // Altering the formula here is necessary to avoid division by - // zero + // Altering the formula here is necessary to avoid division by zero if (std::fabs(oz) < 0.000000001f) { nx = ox * ox - oy * oy - oz * oz + cx; ny = 2.0f * oy * ox + cy; @@ -366,8 +380,7 @@ bool MapgenFractal::getFractalAtPoint(s16 x, s16 y, s16 z) case 9: // 4D "Mandelbulb" float rxy = std::sqrt(ox * ox + oy * oy); float rxyz = std::sqrt(ox * ox + oy * oy + oz * oz); - if (std::fabs(ow) < 0.000000001f && - std::fabs(oz) < 0.000000001f) { + if (std::fabs(ow) < 0.000000001f && std::fabs(oz) < 0.000000001f) { nx = (ox * ox - oy * oy) + cx; ny = 2.0f * ox * oy + cy; nz = -2.0f * rxy * oz + cz; @@ -395,6 +408,7 @@ bool MapgenFractal::getFractalAtPoint(s16 x, s16 y, s16 z) return true; } + s16 MapgenFractal::generateTerrain() { MapNode n_air(CONTENT_AIR); @@ -418,14 +432,12 @@ s16 MapgenFractal::generateTerrain() if (noise_seabed) seabed_height = noise_seabed->result[index2d]; - if (((spflags & MGFRACTAL_TERRAIN) && - y <= seabed_height) || + 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) { + } else if ((spflags & MGFRACTAL_TERRAIN) && y <= water_level) { vm->m_data[vi] = n_water; } else { vm->m_data[vi] = n_air; diff --git a/src/mapgen/mapgen_fractal.h b/src/mapgen/mapgen_fractal.h index a1d8b890c..23af925bc 100644 --- a/src/mapgen/mapgen_fractal.h +++ b/src/mapgen/mapgen_fractal.h @@ -26,12 +26,13 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mapgen.h" ///////////// Mapgen Fractal flags -#define MGFRACTAL_TERRAIN 0x01 +#define MGFRACTAL_TERRAIN 0x01 class BiomeManager; extern FlagDesc flagdesc_mapgen_fractal[]; + struct MapgenFractalParams : public MapgenParams { float cave_width = 0.09f; @@ -67,6 +68,7 @@ struct MapgenFractalParams : public MapgenParams void setDefaultSettings(Settings *settings); }; + class MapgenFractal : public MapgenBasic { public: diff --git a/src/mapgen/mapgen_singlenode.cpp b/src/mapgen/mapgen_singlenode.cpp index 6724e5fe7..cade9e7a8 100644 --- a/src/mapgen/mapgen_singlenode.cpp +++ b/src/mapgen/mapgen_singlenode.cpp @@ -28,8 +28,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "voxelalgorithms.h" #include "emerge.h" -MapgenSinglenode::MapgenSinglenode(MapgenParams *params, EmergeParams *emerge) : - Mapgen(MAPGEN_SINGLENODE, params, emerge) + +MapgenSinglenode::MapgenSinglenode(MapgenParams *params, EmergeParams *emerge) + : Mapgen(MAPGEN_SINGLENODE, params, emerge) { const NodeDefManager *ndef = emerge->ndef; @@ -41,6 +42,7 @@ MapgenSinglenode::MapgenSinglenode(MapgenParams *params, EmergeParams *emerge) : set_light = (ndef->get(n_node).sunlight_propagates) ? LIGHT_SUN : 0x00; } + //////////////////////// Map generator void MapgenSinglenode::makeChunk(BlockMakeData *data) @@ -49,14 +51,14 @@ void MapgenSinglenode::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; + this->vm = data->vmanip; this->ndef = data->nodedef; v3s16 blockpos_min = data->blockpos_min; @@ -71,14 +73,14 @@ void MapgenSinglenode::makeChunk(BlockMakeData *data) MapNode n_node(c_node); for (s16 z = node_min.Z; z <= node_max.Z; z++) - for (s16 y = node_min.Y; y <= node_max.Y; y++) { - u32 i = vm->m_area.index(node_min.X, y, z); - for (s16 x = node_min.X; x <= node_max.X; x++) { - if (vm->m_data[i].getContent() == CONTENT_IGNORE) - vm->m_data[i] = n_node; - i++; - } + for (s16 y = node_min.Y; y <= node_max.Y; y++) { + u32 i = vm->m_area.index(node_min.X, y, z); + for (s16 x = node_min.X; x <= node_max.X; x++) { + if (vm->m_data[i].getContent() == CONTENT_IGNORE) + vm->m_data[i] = n_node; + i++; } + } // Add top and bottom side of water to transforming_liquid queue updateLiquid(&data->transforming_liquid, node_min, node_max); @@ -90,6 +92,7 @@ void MapgenSinglenode::makeChunk(BlockMakeData *data) this->generating = false; } + int MapgenSinglenode::getSpawnLevelAtPoint(v2s16 p) { return 0; diff --git a/src/mapgen/mapgen_v5.cpp b/src/mapgen/mapgen_v5.cpp index 950e23f86..124667e5d 100644 --- a/src/mapgen/mapgen_v5.cpp +++ b/src/mapgen/mapgen_v5.cpp @@ -18,6 +18,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" @@ -36,40 +37,46 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mg_decoration.h" #include "mapgen_v5.h" -FlagDesc flagdesc_mapgen_v5[] = {{"caverns", MGV5_CAVERNS}, {NULL, 0}}; -MapgenV5::MapgenV5(MapgenV5Params *params, EmergeParams *emerge) : - MapgenBasic(MAPGEN_V5, params, emerge) +FlagDesc flagdesc_mapgen_v5[] = { + {"caverns", MGV5_CAVERNS}, + {NULL, 0} +}; + + +MapgenV5::MapgenV5(MapgenV5Params *params, EmergeParams *emerge) + : MapgenBasic(MAPGEN_V5, params, emerge) { - spflags = params->spflags; - cave_width = params->cave_width; - large_cave_depth = params->large_cave_depth; + spflags = params->spflags; + cave_width = params->cave_width; + large_cave_depth = params->large_cave_depth; small_cave_num_min = params->small_cave_num_min; small_cave_num_max = params->small_cave_num_max; large_cave_num_min = params->large_cave_num_min; large_cave_num_max = params->large_cave_num_max; large_cave_flooded = params->large_cave_flooded; - cavern_limit = params->cavern_limit; - cavern_taper = params->cavern_taper; - cavern_threshold = params->cavern_threshold; - dungeon_ymin = params->dungeon_ymin; - dungeon_ymax = params->dungeon_ymax; + cavern_limit = params->cavern_limit; + cavern_taper = params->cavern_taper; + cavern_threshold = params->cavern_threshold; + dungeon_ymin = params->dungeon_ymin; + dungeon_ymax = params->dungeon_ymax; // Terrain noise noise_filler_depth = new Noise(¶ms->np_filler_depth, seed, csize.X, csize.Z); - noise_factor = new Noise(¶ms->np_factor, seed, csize.X, csize.Z); - noise_height = new Noise(¶ms->np_height, seed, csize.X, csize.Z); + noise_factor = new Noise(¶ms->np_factor, seed, csize.X, csize.Z); + noise_height = new Noise(¶ms->np_height, seed, csize.X, csize.Z); // 3D terrain noise // 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; } + MapgenV5::~MapgenV5() { delete noise_filler_depth; @@ -78,77 +85,83 @@ MapgenV5::~MapgenV5() delete noise_ground; } -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_dungeons(0.9, 0.5, v3f(500, 500, 500), 0, 2, 0.8, 2.0) + +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_dungeons (0.9, 0.5, v3f(500, 500, 500), 0, 2, 0.8, 2.0) { } + void MapgenV5Params::readParams(const Settings *settings) { settings->getFlagStrNoEx("mgv5_spflags", spflags, flagdesc_mapgen_v5); - settings->getFloatNoEx("mgv5_cave_width", cave_width); - settings->getS16NoEx("mgv5_large_cave_depth", large_cave_depth); - settings->getU16NoEx("mgv5_small_cave_num_min", small_cave_num_min); - settings->getU16NoEx("mgv5_small_cave_num_max", small_cave_num_max); - settings->getU16NoEx("mgv5_large_cave_num_min", large_cave_num_min); - settings->getU16NoEx("mgv5_large_cave_num_max", large_cave_num_max); + settings->getFloatNoEx("mgv5_cave_width", cave_width); + settings->getS16NoEx("mgv5_large_cave_depth", large_cave_depth); + settings->getU16NoEx("mgv5_small_cave_num_min", small_cave_num_min); + settings->getU16NoEx("mgv5_small_cave_num_max", small_cave_num_max); + settings->getU16NoEx("mgv5_large_cave_num_min", large_cave_num_min); + settings->getU16NoEx("mgv5_large_cave_num_max", large_cave_num_max); settings->getFloatNoEx("mgv5_large_cave_flooded", large_cave_flooded); - settings->getS16NoEx("mgv5_cavern_limit", cavern_limit); - settings->getS16NoEx("mgv5_cavern_taper", cavern_taper); - settings->getFloatNoEx("mgv5_cavern_threshold", cavern_threshold); - settings->getS16NoEx("mgv5_dungeon_ymin", dungeon_ymin); - settings->getS16NoEx("mgv5_dungeon_ymax", dungeon_ymax); + settings->getS16NoEx("mgv5_cavern_limit", cavern_limit); + settings->getS16NoEx("mgv5_cavern_taper", cavern_taper); + settings->getFloatNoEx("mgv5_cavern_threshold", cavern_threshold); + settings->getS16NoEx("mgv5_dungeon_ymin", dungeon_ymin); + settings->getS16NoEx("mgv5_dungeon_ymax", dungeon_ymax); settings->getNoiseParams("mgv5_np_filler_depth", np_filler_depth); - settings->getNoiseParams("mgv5_np_factor", np_factor); - settings->getNoiseParams("mgv5_np_height", np_height); - settings->getNoiseParams("mgv5_np_ground", np_ground); - 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); + settings->getNoiseParams("mgv5_np_factor", np_factor); + settings->getNoiseParams("mgv5_np_height", np_height); + settings->getNoiseParams("mgv5_np_ground", np_ground); + 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); } + void MapgenV5Params::writeParams(Settings *settings) const { settings->setFlagStr("mgv5_spflags", spflags, flagdesc_mapgen_v5); - settings->setFloat("mgv5_cave_width", cave_width); - settings->setS16("mgv5_large_cave_depth", large_cave_depth); - settings->setU16("mgv5_small_cave_num_min", small_cave_num_min); - settings->setU16("mgv5_small_cave_num_max", small_cave_num_max); - settings->setU16("mgv5_large_cave_num_min", large_cave_num_min); - settings->setU16("mgv5_large_cave_num_max", large_cave_num_max); + settings->setFloat("mgv5_cave_width", cave_width); + settings->setS16("mgv5_large_cave_depth", large_cave_depth); + settings->setU16("mgv5_small_cave_num_min", small_cave_num_min); + settings->setU16("mgv5_small_cave_num_max", small_cave_num_max); + settings->setU16("mgv5_large_cave_num_min", large_cave_num_min); + settings->setU16("mgv5_large_cave_num_max", large_cave_num_max); settings->setFloat("mgv5_large_cave_flooded", large_cave_flooded); - settings->setS16("mgv5_cavern_limit", cavern_limit); - settings->setS16("mgv5_cavern_taper", cavern_taper); - settings->setFloat("mgv5_cavern_threshold", cavern_threshold); - settings->setS16("mgv5_dungeon_ymin", dungeon_ymin); - settings->setS16("mgv5_dungeon_ymax", dungeon_ymax); + settings->setS16("mgv5_cavern_limit", cavern_limit); + settings->setS16("mgv5_cavern_taper", cavern_taper); + settings->setFloat("mgv5_cavern_threshold", cavern_threshold); + settings->setS16("mgv5_dungeon_ymin", dungeon_ymin); + settings->setS16("mgv5_dungeon_ymax", dungeon_ymax); settings->setNoiseParams("mgv5_np_filler_depth", np_filler_depth); - settings->setNoiseParams("mgv5_np_factor", np_factor); - settings->setNoiseParams("mgv5_np_height", np_height); - settings->setNoiseParams("mgv5_np_ground", np_ground); - 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); + settings->setNoiseParams("mgv5_np_factor", np_factor); + settings->setNoiseParams("mgv5_np_height", np_height); + settings->setNoiseParams("mgv5_np_ground", np_ground); + 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); } + void MapgenV5Params::setDefaultSettings(Settings *settings) { settings->setDefault("mgv5_spflags", flagdesc_mapgen_v5, MGV5_CAVERNS); } + ///////////////////////////////////////////////////////////////// + int MapgenV5::getSpawnLevelAtPoint(v2s16 p) { @@ -170,9 +183,9 @@ int MapgenV5::getSpawnLevelAtPoint(v2s16 p) 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 (n_ground * f > y - h) { // If solid if (y < water_level || y > max_spawn_y) - return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point + return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point // y + 2 because y is surface and due to biome 'dust' nodes. return y + 2; @@ -182,22 +195,23 @@ int MapgenV5::getSpawnLevelAtPoint(v2s16 p) return MAX_MAP_GENERATION_LIMIT; } + void MapgenV5::makeChunk(BlockMakeData *data) { // Pre-conditions 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; + this->vm = data->vmanip; this->ndef = data->nodedef; - // TimeTaker t("makeChunk"); + //TimeTaker t("makeChunk"); v3s16 blockpos_min = data->blockpos_min; v3s16 blockpos_max = data->blockpos_max; @@ -236,8 +250,8 @@ void MapgenV5::makeChunk(BlockMakeData *data) // Disable large randomwalk caves in this mapchunk by setting // 'large cave depth' to world base. Avoids excessive liquid in // large caverns and floating blobs of overgenerated liquid. - generateCavesRandomWalk( - stone_surface_max_y, -MAX_MAP_GENERATION_LIMIT); + generateCavesRandomWalk(stone_surface_max_y, + -MAX_MAP_GENERATION_LIMIT); else generateCavesRandomWalk(stone_surface_max_y, large_cave_depth); } @@ -257,7 +271,7 @@ void MapgenV5::makeChunk(BlockMakeData *data) if (flags & MG_BIOMES) dustTopNodes(); - // printf("makeChunk: %dms\n", t.stop()); + //printf("makeChunk: %dms\n", t.stop()); // Add top and bottom side of water to transforming_liquid queue updateLiquid(&data->transforming_liquid, full_node_min, full_node_max); @@ -265,12 +279,13 @@ void MapgenV5::makeChunk(BlockMakeData *data) // 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); + full_node_min, full_node_max); } this->generating = false; } + int MapgenV5::generateBaseTerrain() { u32 index = 0; @@ -281,11 +296,10 @@ int MapgenV5::generateBaseTerrain() noise_height->perlinMap2D(node_min.X, node_min.Z); noise_ground->perlinMap3D(node_min.X, node_min.Y - 1, 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++) { + 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++, index++, index2d++) { + for (s16 x=node_min.X; x<=node_max.X; x++, vi++, index++, index2d++) { if (vm->m_data[vi].getContent() != CONTENT_IGNORE) continue; diff --git a/src/mapgen/mapgen_v6.cpp b/src/mapgen/mapgen_v6.cpp index 8a0f01409..e9692246c 100644 --- a/src/mapgen/mapgen_v6.cpp +++ b/src/mapgen/mapgen_v6.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" @@ -38,64 +39,70 @@ 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}}; + +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(MapgenV6Params *params, EmergeParams *emerge) : - Mapgen(MAPGEN_V6, params, emerge) + +MapgenV6::MapgenV6(MapgenV6Params *params, EmergeParams *emerge) + : Mapgen(MAPGEN_V6, params, emerge) { m_emerge = emerge; ystride = csize.X; heightmap = new s16[csize.X * csize.Z]; - spflags = params->spflags; - freq_desert = params->freq_desert; - freq_beach = params->freq_beach; + spflags = params->spflags; + freq_desert = params->freq_desert; + freq_beach = params->freq_beach; dungeon_ymin = params->dungeon_ymin; dungeon_ymax = params->dungeon_ymax; - np_cave = ¶ms->np_cave; - np_humidity = ¶ms->np_humidity; - np_trees = ¶ms->np_trees; + np_cave = ¶ms->np_cave; + np_humidity = ¶ms->np_humidity; + 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); - 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(¶ms->np_humidity, 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(¶ms->np_humidity, seed, csize.X + 2 * MAP_BLOCKSIZE, csize.Y + 2 * MAP_BLOCKSIZE); //// Resolve nodes to be used const NodeDefManager *ndef = emerge->ndef; - c_stone = ndef->getId("mapgen_stone"); - c_dirt = ndef->getId("mapgen_dirt"); + c_stone = ndef->getId("mapgen_stone"); + c_dirt = ndef->getId("mapgen_dirt"); c_dirt_with_grass = ndef->getId("mapgen_dirt_with_grass"); - c_sand = ndef->getId("mapgen_sand"); - c_water_source = ndef->getId("mapgen_water_source"); - c_lava_source = ndef->getId("mapgen_lava_source"); - c_gravel = ndef->getId("mapgen_gravel"); - c_desert_stone = ndef->getId("mapgen_desert_stone"); - c_desert_sand = ndef->getId("mapgen_desert_sand"); - c_dirt_with_snow = ndef->getId("mapgen_dirt_with_snow"); - c_snow = ndef->getId("mapgen_snow"); - c_snowblock = ndef->getId("mapgen_snowblock"); - c_ice = ndef->getId("mapgen_ice"); + c_sand = ndef->getId("mapgen_sand"); + c_water_source = ndef->getId("mapgen_water_source"); + c_lava_source = ndef->getId("mapgen_lava_source"); + c_gravel = ndef->getId("mapgen_gravel"); + c_desert_stone = ndef->getId("mapgen_desert_stone"); + c_desert_sand = ndef->getId("mapgen_desert_sand"); + c_dirt_with_snow = ndef->getId("mapgen_dirt_with_snow"); + c_snow = ndef->getId("mapgen_snow"); + c_snowblock = ndef->getId("mapgen_snowblock"); + c_ice = ndef->getId("mapgen_ice"); if (c_gravel == CONTENT_IGNORE) c_gravel = c_stone; @@ -112,9 +119,9 @@ MapgenV6::MapgenV6(MapgenV6Params *params, EmergeParams *emerge) : 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_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) @@ -125,29 +132,22 @@ MapgenV6::MapgenV6(MapgenV6Params *params, EmergeParams *emerge) : c_stair_desert_stone = c_desert_stone; if (c_stone == CONTENT_IGNORE) - errorstream << "Mapgen v6: Mapgen alias 'mapgen_stone' is invalid!" - << std::endl; + errorstream << "Mapgen v6: Mapgen alias 'mapgen_stone' is invalid!" << std::endl; if (c_dirt == CONTENT_IGNORE) - errorstream << "Mapgen v6: Mapgen alias 'mapgen_dirt' is invalid!" - << std::endl; + errorstream << "Mapgen v6: Mapgen alias 'mapgen_dirt' is invalid!" << std::endl; if (c_dirt_with_grass == CONTENT_IGNORE) - errorstream << "Mapgen v6: Mapgen alias 'mapgen_dirt_with_grass' is " - "invalid!" - << std::endl; + errorstream << "Mapgen v6: Mapgen alias 'mapgen_dirt_with_grass' is invalid!" << std::endl; if (c_sand == CONTENT_IGNORE) - errorstream << "Mapgen v6: Mapgen alias 'mapgen_sand' is invalid!" - << std::endl; + errorstream << "Mapgen v6: Mapgen alias 'mapgen_sand' is invalid!" << std::endl; if (c_water_source == CONTENT_IGNORE) - errorstream << "Mapgen v6: Mapgen alias 'mapgen_water_source' is invalid!" - << std::endl; + errorstream << "Mapgen v6: Mapgen alias 'mapgen_water_source' is invalid!" << std::endl; if (c_lava_source == CONTENT_IGNORE) - errorstream << "Mapgen v6: Mapgen alias 'mapgen_lava_source' is invalid!" - << std::endl; + errorstream << "Mapgen v6: Mapgen alias 'mapgen_lava_source' is invalid!" << std::endl; if (c_cobble == CONTENT_IGNORE) - errorstream << "Mapgen v6: Mapgen alias 'mapgen_cobble' is invalid!" - << std::endl; + errorstream << "Mapgen v6: Mapgen alias 'mapgen_cobble' is invalid!" << std::endl; } + MapgenV6::~MapgenV6() { delete noise_terrain_base; @@ -164,72 +164,77 @@ MapgenV6::~MapgenV6() delete m_emerge; // our responsibility } -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) + +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) { } + void MapgenV6Params::readParams(const Settings *settings) { settings->getFlagStrNoEx("mgv6_spflags", spflags, flagdesc_mapgen_v6); settings->getFloatNoEx("mgv6_freq_desert", freq_desert); - settings->getFloatNoEx("mgv6_freq_beach", freq_beach); - settings->getS16NoEx("mgv6_dungeon_ymin", dungeon_ymin); - settings->getS16NoEx("mgv6_dungeon_ymax", dungeon_ymax); + settings->getFloatNoEx("mgv6_freq_beach", freq_beach); + settings->getS16NoEx("mgv6_dungeon_ymin", dungeon_ymin); + settings->getS16NoEx("mgv6_dungeon_ymax", dungeon_ymax); - settings->getNoiseParams("mgv6_np_terrain_base", np_terrain_base); + settings->getNoiseParams("mgv6_np_terrain_base", np_terrain_base); settings->getNoiseParams("mgv6_np_terrain_higher", np_terrain_higher); - settings->getNoiseParams("mgv6_np_steepness", np_steepness); - settings->getNoiseParams("mgv6_np_height_select", np_height_select); - settings->getNoiseParams("mgv6_np_mud", np_mud); - settings->getNoiseParams("mgv6_np_beach", np_beach); - settings->getNoiseParams("mgv6_np_biome", np_biome); - settings->getNoiseParams("mgv6_np_cave", np_cave); - settings->getNoiseParams("mgv6_np_humidity", np_humidity); - settings->getNoiseParams("mgv6_np_trees", np_trees); - settings->getNoiseParams("mgv6_np_apple_trees", np_apple_trees); + settings->getNoiseParams("mgv6_np_steepness", np_steepness); + settings->getNoiseParams("mgv6_np_height_select", np_height_select); + settings->getNoiseParams("mgv6_np_mud", np_mud); + settings->getNoiseParams("mgv6_np_beach", np_beach); + settings->getNoiseParams("mgv6_np_biome", np_biome); + settings->getNoiseParams("mgv6_np_cave", np_cave); + settings->getNoiseParams("mgv6_np_humidity", np_humidity); + settings->getNoiseParams("mgv6_np_trees", np_trees); + settings->getNoiseParams("mgv6_np_apple_trees", np_apple_trees); } + void MapgenV6Params::writeParams(Settings *settings) const { settings->setFlagStr("mgv6_spflags", spflags, flagdesc_mapgen_v6); settings->setFloat("mgv6_freq_desert", freq_desert); - settings->setFloat("mgv6_freq_beach", freq_beach); - settings->setS16("mgv6_dungeon_ymin", dungeon_ymin); - settings->setS16("mgv6_dungeon_ymax", dungeon_ymax); + settings->setFloat("mgv6_freq_beach", freq_beach); + settings->setS16("mgv6_dungeon_ymin", dungeon_ymin); + settings->setS16("mgv6_dungeon_ymax", dungeon_ymax); - settings->setNoiseParams("mgv6_np_terrain_base", np_terrain_base); + settings->setNoiseParams("mgv6_np_terrain_base", np_terrain_base); settings->setNoiseParams("mgv6_np_terrain_higher", np_terrain_higher); - settings->setNoiseParams("mgv6_np_steepness", np_steepness); - settings->setNoiseParams("mgv6_np_height_select", np_height_select); - settings->setNoiseParams("mgv6_np_mud", np_mud); - settings->setNoiseParams("mgv6_np_beach", np_beach); - settings->setNoiseParams("mgv6_np_biome", np_biome); - settings->setNoiseParams("mgv6_np_cave", np_cave); - settings->setNoiseParams("mgv6_np_humidity", np_humidity); - settings->setNoiseParams("mgv6_np_trees", np_trees); - settings->setNoiseParams("mgv6_np_apple_trees", np_apple_trees); + settings->setNoiseParams("mgv6_np_steepness", np_steepness); + settings->setNoiseParams("mgv6_np_height_select", np_height_select); + settings->setNoiseParams("mgv6_np_mud", np_mud); + settings->setNoiseParams("mgv6_np_beach", np_beach); + settings->setNoiseParams("mgv6_np_biome", np_biome); + settings->setNoiseParams("mgv6_np_cave", np_cave); + settings->setNoiseParams("mgv6_np_humidity", np_humidity); + settings->setNoiseParams("mgv6_np_trees", np_trees); + settings->setNoiseParams("mgv6_np_apple_trees", np_apple_trees); } + void MapgenV6Params::setDefaultSettings(Settings *settings) { - settings->setDefault("mgv6_spflags", flagdesc_mapgen_v6, - MGV6_JUNGLES | MGV6_SNOWBIOMES | MGV6_TREES | MGV6_BIOMEBLEND | - MGV6_MUDFLOW); + settings->setDefault("mgv6_spflags", flagdesc_mapgen_v6, MGV6_JUNGLES | + MGV6_SNOWBIOMES | MGV6_TREES | MGV6_BIOMEBLEND | MGV6_MUDFLOW); } + //////////////////////// Some helper functions for the map generator + // Returns Y one under area minimum if not found s16 MapgenV6::find_stone_level(v2s16 p2d) { @@ -249,6 +254,7 @@ s16 MapgenV6::find_stone_level(v2s16 p2d) return (y >= y_nodes_min) ? y : y_nodes_min - 1; } + // Required by mapgen.h bool MapgenV6::block_is_underground(u64 seed, v3s16 blockpos) { @@ -257,22 +263,23 @@ bool MapgenV6::block_is_underground(u64 seed, v3s16 blockpos) // Nah, this is just a heuristic, just return something s16 minimum_groundlevel = water_level; - if (blockpos.Y * MAP_BLOCKSIZE + MAP_BLOCKSIZE <= minimum_groundlevel) + if(blockpos.Y * MAP_BLOCKSIZE + MAP_BLOCKSIZE <= minimum_groundlevel) return true; return false; } + //////////////////////// Base terrain height functions float MapgenV6::baseTerrainLevel(float terrain_base, float terrain_higher, - float steepness, float height_select) + float steepness, float height_select) { - float base = 1 + terrain_base; + float base = 1 + terrain_base; float higher = 1 + terrain_higher; // Limit higher ground level to at least base - if (higher < base) + if(higher < base) higher = base; // Steepness factor of cliffs @@ -292,61 +299,71 @@ float MapgenV6::baseTerrainLevel(float terrain_base, float terrain_higher, return base * (1.0 - a) + higher * a; } + float MapgenV6::baseTerrainLevelFromNoise(v2s16 p) { if (spflags & MGV6_FLAT) return water_level; - float terrain_base = NoisePerlin2D_PO( - &noise_terrain_base->np, p.X, 0.5, p.Y, 0.5, seed); - float terrain_higher = NoisePerlin2D_PO( - &noise_terrain_higher->np, p.X, 0.5, p.Y, 0.5, seed); - float steepness = - NoisePerlin2D_PO(&noise_steepness->np, p.X, 0.5, p.Y, 0.5, seed); - float height_select = NoisePerlin2D_PO( - &noise_height_select->np, p.X, 0.5, p.Y, 0.5, seed); - - return baseTerrainLevel(terrain_base, terrain_higher, steepness, height_select); + float terrain_base = NoisePerlin2D_PO(&noise_terrain_base->np, + p.X, 0.5, p.Y, 0.5, seed); + float terrain_higher = NoisePerlin2D_PO(&noise_terrain_higher->np, + p.X, 0.5, p.Y, 0.5, seed); + float steepness = NoisePerlin2D_PO(&noise_steepness->np, + p.X, 0.5, p.Y, 0.5, seed); + float height_select = NoisePerlin2D_PO(&noise_height_select->np, + p.X, 0.5, p.Y, 0.5, seed); + + return baseTerrainLevel(terrain_base, terrain_higher, + steepness, height_select); } + float MapgenV6::baseTerrainLevelFromMap(v2s16 p) { int index = (p.Y - node_min.Z) * ystride + (p.X - node_min.X); return baseTerrainLevelFromMap(index); } + float MapgenV6::baseTerrainLevelFromMap(int index) { if (spflags & MGV6_FLAT) return water_level; - float terrain_base = noise_terrain_base->result[index]; + float terrain_base = noise_terrain_base->result[index]; float terrain_higher = noise_terrain_higher->result[index]; - float steepness = noise_steepness->result[index]; - float height_select = noise_height_select->result[index]; + float steepness = noise_steepness->result[index]; + float height_select = noise_height_select->result[index]; - return baseTerrainLevel(terrain_base, terrain_higher, steepness, height_select); + return baseTerrainLevel(terrain_base, terrain_higher, + steepness, height_select); } + s16 MapgenV6::find_ground_level_from_noise(u64 seed, v2s16 p2d, s16 precision) { return baseTerrainLevelFromNoise(p2d) + MGV6_AVERAGE_MUD_AMOUNT; } + int MapgenV6::getGroundLevelAtPoint(v2s16 p) { 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 + if (level_at_point <= water_level || + level_at_point > water_level + 16) + return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point return level_at_point; } + //////////////////////// Noise functions float MapgenV6::getMudAmount(v2s16 p) @@ -355,19 +372,22 @@ float MapgenV6::getMudAmount(v2s16 p) return getMudAmount(index); } + bool MapgenV6::getHaveBeach(v2s16 p) { int index = (p.Y - node_min.Z) * ystride + (p.X - node_min.X); return getHaveBeach(index); } + BiomeV6Type MapgenV6::getBiome(v2s16 p) { - int index = (p.Y - full_node_min.Z) * (ystride + 2 * MAP_BLOCKSIZE) + - (p.X - full_node_min.X); + int index = (p.Y - full_node_min.Z) * (ystride + 2 * MAP_BLOCKSIZE) + + (p.X - full_node_min.X); return getBiome(index, p); } + float MapgenV6::getHumidity(v2s16 p) { /*double noise = noise2d_perlin( @@ -375,8 +395,8 @@ float MapgenV6::getHumidity(v2s16 p) seed+72384, 4, 0.66); noise = (noise + 1.0)/2.0;*/ - int index = (p.Y - full_node_min.Z) * (ystride + 2 * MAP_BLOCKSIZE) + - (p.X - full_node_min.X); + int index = (p.Y - full_node_min.Z) * (ystride + 2 * MAP_BLOCKSIZE) + + (p.X - full_node_min.X); float noise = noise_humidity->result[index]; if (noise < 0.0) @@ -386,6 +406,7 @@ float MapgenV6::getHumidity(v2s16 p) return noise; } + float MapgenV6::getTreeAmount(v2s16 p) { /*double noise = noise2d_perlin( @@ -400,6 +421,7 @@ float MapgenV6::getTreeAmount(v2s16 p) return 0.04 * (noise - zeroval) / (1.0 - zeroval); } + bool MapgenV6::getHaveAppleTree(v2s16 p) { /*is_apple_tree = noise2d_perlin( @@ -411,6 +433,7 @@ bool MapgenV6::getHaveAppleTree(v2s16 p) return noise > 0.2; } + float MapgenV6::getMudAmount(int index) { if (spflags & MGV6_FLAT) @@ -423,6 +446,7 @@ float MapgenV6::getMudAmount(int index) return noise_mud->result[index]; } + bool MapgenV6::getHaveBeach(int index) { // Determine whether to have sand here @@ -434,6 +458,7 @@ bool MapgenV6::getHaveBeach(int index) return (sandnoise > freq_beach); } + BiomeV6Type MapgenV6::getBiome(int index, v2s16 p) { // Just do something very simple as for now @@ -445,8 +470,7 @@ BiomeV6Type MapgenV6::getBiome(int index, v2s16 p) float h = noise_humidity->result[index]; if (spflags & MGV6_SNOWBIOMES) { - float blend = (spflags & MGV6_BIOMEBLEND) ? noise2d(p.X, p.Y, seed) / 40 - : 0; + float blend = (spflags & MGV6_BIOMEBLEND) ? noise2d(p.X, p.Y, seed) / 40 : 0; if (d > MGV6_FREQ_HOT + blend) { if (h > MGV6_FREQ_JUNGLE + blend) @@ -476,14 +500,17 @@ BiomeV6Type MapgenV6::getBiome(int index, v2s16 p) return BT_JUNGLE; return BT_NORMAL; + } + u32 MapgenV6::get_blockseed(u64 seed, v3s16 p) { s32 x = p.X, y = p.Y, z = p.Z; return (u32)(seed % 0x100000000ULL) + z * 38134234 + y * 42123 + x * 23; } + //////////////////////// Map generator void MapgenV6::makeChunk(BlockMakeData *data) @@ -492,14 +519,14 @@ 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; + this->vm = data->vmanip; this->ndef = data->nodedef; // Hack: use minimum block coords for old code that assumes a single block @@ -551,6 +578,7 @@ void MapgenV6::makeChunk(BlockMakeData *data) // Flow mud away from steep edges if (spflags & MGV6_MUDFLOW) flowMud(mudflow_minpos, mudflow_maxpos); + } // Update heightmap after mudflow @@ -558,53 +586,50 @@ 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) { - u16 num_dungeons = std::fmax( - std::floor(NoisePerlin3D(&np_dungeons, node_min.X, - node_min.Y, node_min.Z, seed)), - 0.0f); + full_node_min.Y >= dungeon_ymin && full_node_max.Y <= dungeon_ymax) { + 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.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); + 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.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; + 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.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; + dp.notifytype = GENNOTIFY_DUNGEON; } DungeonGen dgen(ndef, &gennotify, &dp); @@ -632,12 +657,13 @@ void MapgenV6::makeChunk(BlockMakeData *data) // Calculate lighting if (flags & MG_LIGHT) calcLighting(node_min - v3s16(1, 1, 1) * MAP_BLOCKSIZE, - node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE, full_node_min, - full_node_max); + node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE, + full_node_min, full_node_max); this->generating = false; } + void MapgenV6::calculateNoise() { int x = node_min.X; @@ -661,9 +687,10 @@ void MapgenV6::calculateNoise() // only humidity at point does } + int MapgenV6::generateGround() { - // TimeTaker timer1("Generating ground level"); + //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); @@ -671,242 +698,218 @@ int MapgenV6::generateGround() 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; - - BiomeV6Type bt = getBiome(v2s16(x, z)); - - // Fill ground with stone - 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 >= MGV6_DESERT_STONE_BASE && - bt == BT_DESERT) - ? n_desert_stone - : n_stone; - } else if (y <= water_level) { - vm->m_data[i] = (y >= MGV6_ICE_BASE && - bt == BT_TUNDRA) - ? n_ice - : n_water_source; - } else { - vm->m_data[i] = n_air; - } + 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; + + BiomeV6Type bt = getBiome(v2s16(x, z)); + + // Fill ground with stone + 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 >= MGV6_DESERT_STONE_BASE + && bt == BT_DESERT) ? + n_desert_stone : n_stone; + } else if (y <= water_level) { + vm->m_data[i] = (y >= MGV6_ICE_BASE + && bt == BT_TUNDRA) ? + n_ice : n_water_source; + } else { + vm->m_data[i] = n_air; } - VoxelArea::add_y(em, i, 1); } + VoxelArea::add_y(em, i, 1); } + } return stone_surface_max_y; } + void MapgenV6::addMud() { // 15ms @cs=8 - // TimeTaker timer1("add mud"); + //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; + 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(v2s16(x, 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; + } - // Find ground level - s16 surface_y = find_stone_level( - v2s16(x, z)); /////////////////optimize this! + if ((bt == BT_DESERT || bt == BT_TUNDRA) && surface_y > 20) + mud_add_amount = MYMAX(0, mud_add_amount - (surface_y - 20) / 5); - // Handle area not found - if (surface_y == vm->m_area.MinEdge.Y - 1) - continue; + /* 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;*/ - BiomeV6Type bt = getBiome(v2s16(x, 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; - } + // Add mud on ground + s16 mudcount = 0; + 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++) { + if (mudcount >= mud_add_amount) + break; - 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; - 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++) { - if (mudcount >= mud_add_amount) - break; + vm->m_data[i] = addnode; + mudcount++; - vm->m_data[i] = addnode; - mudcount++; - - VoxelArea::add_y(em, i, 1); - } + VoxelArea::add_y(em, i, 1); } + } } + void MapgenV6::flowMud(s16 &mudflow_minpos, s16 &mudflow_maxpos) { 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 + 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++) { - // 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); - - 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; - - VoxelArea::add_y(em, i, -1); - } - if (y < node_min.Y) - // No mud found in mapchunk - // column, process the next column + for (s16 x = mudflow_minpos; x <= mudflow_maxpos; x++) { + // 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); + + 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; - 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); - MapNode *n2 = &vm->m_data[i2]; - if (n2->getContent() != c_dirt && - n2->getContent() != - c_dirt_with_grass) - // Find next mud node in - // column - continue; - } + VoxelArea::add_y(em, i, -1); + } + if (y < node_min.Y) + // No mud found in mapchunk column, process the next column + break; - // 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) + 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); + MapNode *n2 = &vm->m_data[i2]; + if (n2->getContent() != c_dirt && + n2->getContent() != c_dirt_with_grass) // Find next mud node in column continue; + } + + // 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 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 (ndef->get(*n2).walkable) + continue; - // 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 + // 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 (ndef->get(*n2).walkable) - continue; - - // 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); + // If out of area or in ungenerated world + if (y2 < full_node_min.Y || n2->getContent() == CONTENT_IGNORE) { + dropped_to_unknown = true; + break; } - // Done, find next mud node in - // column - 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; } } } + } } } -void MapgenV6::moveMud(u32 remove_index, u32 place_index, u32 above_remove_index, - v2s16 pos, v3s16 em) + +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 @@ -916,20 +919,17 @@ void MapgenV6::moveMud(u32 remove_index, u32 place_index, u32 above_remove_index // 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) { + 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].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; VoxelArea::add_y(em, above_remove_index, 1); } @@ -946,9 +946,10 @@ void MapgenV6::moveMud(u32 remove_index, u32 place_index, u32 above_remove_index } } + void MapgenV6::placeTreesAndJungleGrass() { - // TimeTaker t("placeTrees"); + //TimeTaker t("placeTrees"); if (node_max.Y < water_level) return; @@ -968,96 +969,98 @@ void MapgenV6::placeTreesAndJungleGrass() // N.B. We must add jungle grass first, since tree leaves will // obstruct the ground, giving us a false ground level for (s16 z0 = 0; z0 < div; z0++) - for (s16 x0 = 0; x0 < div; x0++) { - // Center position of part of division - v2s16 p2d_center(node_min.X + sidelen / 2 + sidelen * x0, - node_min.Z + sidelen / 2 + sidelen * z0); - // Minimum edge of part of division - v2s16 p2d_min(node_min.X + sidelen * x0, - node_min.Z + sidelen * z0); - // Maximum edge of part of division - v2s16 p2d_max(node_min.X + sidelen + sidelen * x0 - 1, - node_min.Z + sidelen + sidelen * z0 - 1); - - // Get biome at center position of part of division - BiomeV6Type bt = getBiome(p2d_center); - - // Amount of trees - u32 tree_count; - if (bt == BT_JUNGLE || bt == BT_TAIGA || bt == BT_NORMAL) { - tree_count = area * getTreeAmount(p2d_center); - if (bt == BT_JUNGLE) - tree_count *= 4; - } else { - tree_count = 0; - } + for (s16 x0 = 0; x0 < div; x0++) { + // Center position of part of division + v2s16 p2d_center( + node_min.X + sidelen / 2 + sidelen * x0, + node_min.Z + sidelen / 2 + sidelen * z0 + ); + // Minimum edge of part of division + v2s16 p2d_min( + node_min.X + sidelen * x0, + node_min.Z + sidelen * z0 + ); + // Maximum edge of part of division + v2s16 p2d_max( + node_min.X + sidelen + sidelen * x0 - 1, + node_min.Z + sidelen + sidelen * z0 - 1 + ); + + // Get biome at center position of part of division + BiomeV6Type bt = getBiome(p2d_center); + + // Amount of trees + u32 tree_count; + if (bt == BT_JUNGLE || bt == BT_TAIGA || bt == BT_NORMAL) { + tree_count = area * getTreeAmount(p2d_center); + if (bt == BT_JUNGLE) + tree_count *= 4; + } else { + tree_count = 0; + } - // Add jungle grass - if (bt == BT_JUNGLE) { - float humidity = getHumidity(p2d_center); - u32 grass_count = 5 * humidity * tree_count; - for (u32 i = 0; i < grass_count; i++) { - s16 x = grassrandom.range(p2d_min.X, p2d_max.X); - s16 z = grassrandom.range(p2d_min.Y, p2d_max.Y); - int mapindex = central_area_size.X * - (z - node_min.Z) + - (x - node_min.X); - s16 y = heightmap[mapindex]; - if (y < water_level) - continue; + // Add jungle grass + if (bt == BT_JUNGLE) { + float humidity = getHumidity(p2d_center); + u32 grass_count = 5 * humidity * tree_count; + for (u32 i = 0; i < grass_count; i++) { + s16 x = grassrandom.range(p2d_min.X, p2d_max.X); + s16 z = grassrandom.range(p2d_min.Y, p2d_max.Y); + int mapindex = central_area_size.X * (z - node_min.Z) + + (x - node_min.X); + s16 y = heightmap[mapindex]; + if (y < water_level) + continue; - u32 vi = vm->m_area.index(x, y, z); - // place on dirt_with_grass, since we know it is - // exposed to sunlight - if (vm->m_data[vi].getContent() == - c_dirt_with_grass) { - VoxelArea::add_y(em, vi, 1); - vm->m_data[vi] = n_junglegrass; - } + u32 vi = vm->m_area.index(x, y, z); + // place on dirt_with_grass, since we know it is exposed to sunlight + if (vm->m_data[vi].getContent() == c_dirt_with_grass) { + VoxelArea::add_y(em, vi, 1); + vm->m_data[vi] = n_junglegrass; } } + } - // Put trees in random places on part of division - for (u32 i = 0; i < tree_count; i++) { - s16 x = myrand_range(p2d_min.X, p2d_max.X); - s16 z = myrand_range(p2d_min.Y, p2d_max.Y); - int mapindex = central_area_size.X * (z - node_min.Z) + - (x - node_min.X); - s16 y = heightmap[mapindex]; - // Don't make a tree under water level - // Don't make a tree so high that it doesn't fit - if (y < water_level || y > node_max.Y - 6) + // Put trees in random places on part of division + for (u32 i = 0; i < tree_count; i++) { + s16 x = myrand_range(p2d_min.X, p2d_max.X); + s16 z = myrand_range(p2d_min.Y, p2d_max.Y); + int mapindex = central_area_size.X * (z - node_min.Z) + + (x - node_min.X); + s16 y = heightmap[mapindex]; + // Don't make a tree under water level + // Don't make a tree so high that it doesn't fit + if (y < water_level || y > node_max.Y - 6) + continue; + + v3s16 p(x, y, z); + // 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) continue; + } + p.Y++; - v3s16 p(x, y, z); - // 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) - continue; - } - p.Y++; - - // Make a tree - if (bt == BT_JUNGLE) { - treegen::make_jungletree(*vm, p, ndef, myrand()); - } else if (bt == BT_TAIGA) { - treegen::make_pine_tree(*vm, p - v3s16(0, 1, 0), - ndef, myrand()); - } else if (bt == BT_NORMAL) { - bool is_apple_tree = - (myrand_range(0, 3) == 0) && + // Make a tree + if (bt == BT_JUNGLE) { + treegen::make_jungletree(*vm, p, ndef, myrand()); + } else if (bt == BT_TAIGA) { + treegen::make_pine_tree(*vm, p - v3s16(0, 1, 0), ndef, myrand()); + } else if (bt == BT_NORMAL) { + bool is_apple_tree = (myrand_range(0, 3) == 0) && getHaveAppleTree(v2s16(x, z)); - treegen::make_tree(*vm, p, is_apple_tree, ndef, - myrand()); - } + treegen::make_tree(*vm, p, is_apple_tree, ndef, myrand()); } } - // printf("placeTreesAndJungleGrass: %dms\n", t.stop()); + } + //printf("placeTreesAndJungleGrass: %dms\n", t.stop()); } + void MapgenV6::growGrass() // Add surface nodes { MapNode n_dirt_with_grass(c_dirt_with_grass); @@ -1068,54 +1071,53 @@ void MapgenV6::growGrass() // Add surface nodes 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; - VoxelArea::add_y(em, i, -1); - } - surface_y = (y >= full_node_min.Y) ? y : full_node_min.Y; + 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; + VoxelArea::add_y(em, i, -1); } + surface_y = (y >= full_node_min.Y) ? y : full_node_min.Y; + } - BiomeV6Type bt = getBiome(index, v2s16(x, z)); - u32 i = vm->m_area.index(x, surface_y, z); - content_t c = vm->m_data[i].getContent(); - if (surface_y >= water_level - 20) { - if (bt == BT_TAIGA && c == c_dirt) { + BiomeV6Type bt = getBiome(index, v2s16(x, z)); + u32 i = vm->m_area.index(x, surface_y, z); + 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_dirt_with_snow; + } else if (bt == BT_TUNDRA) { + if (c == c_dirt) { + vm->m_data[i] = n_snowblock; + VoxelArea::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; - VoxelArea::add_y(em, i, -1); - vm->m_data[i] = n_dirt_with_snow; - } else if (c == c_stone && - surface_y < node_max.Y) { - VoxelArea::add_y(em, i, 1); - vm->m_data[i] = n_snowblock; - } - } else if (c == c_dirt) { - vm->m_data[i] = n_dirt_with_grass; + } else if (c == c_stone && surface_y < node_max.Y) { + VoxelArea::add_y(em, i, 1); + vm->m_data[i] = n_snowblock; } + } else if (c == c_dirt) { + vm->m_data[i] = n_dirt_with_grass; } } + } } + void MapgenV6::generateCaves(int max_stone_y) { float cave_amount = NoisePerlin2D(np_cave, node_min.X, node_min.Y, seed); - int volume_nodes = (node_max.X - node_min.X + 1) * (node_max.Y - node_min.Y + 1) * - MAP_BLOCKSIZE; + int volume_nodes = (node_max.X - node_min.X + 1) * + (node_max.Y - node_min.Y + 1) * MAP_BLOCKSIZE; cave_amount = MYMAX(0.0, cave_amount); u32 caves_count = cave_amount * volume_nodes / 50000; u32 bruises_count = 1; @@ -1126,16 +1128,15 @@ void MapgenV6::generateCaves(int max_stone_y) bruises_count = ps.range(0, ps.range(0, 2)); if (getBiome(v2s16(node_min.X, node_min.Z)) == BT_DESERT) { - caves_count /= 3; + caves_count /= 3; bruises_count /= 3; } for (u32 i = 0; i < caves_count + bruises_count; i++) { - CavesV6 cave(ndef, &gennotify, water_level, c_water_source, - c_lava_source); + CavesV6 cave(ndef, &gennotify, water_level, c_water_source, c_lava_source); bool large_cave = (i >= caves_count); - cave.makeCave(vm, node_min, node_max, &ps, &ps2, large_cave, max_stone_y, - heightmap); + cave.makeCave(vm, node_min, node_max, &ps, &ps2, + large_cave, max_stone_y, heightmap); } } diff --git a/src/mapgen/mapgen_v6.h b/src/mapgen/mapgen_v6.h index a0abbb010..ff565edec 100644 --- a/src/mapgen/mapgen_v6.h +++ b/src/mapgen/mapgen_v6.h @@ -33,15 +33,17 @@ with this program; if not, write to the Free Software Foundation, Inc., #define MGV6_FREQ_JUNGLE 0.5 //////////// Mapgen V6 flags -#define MGV6_JUNGLES 0x01 +#define MGV6_JUNGLES 0x01 #define MGV6_BIOMEBLEND 0x02 -#define MGV6_MUDFLOW 0x04 +#define MGV6_MUDFLOW 0x04 #define MGV6_SNOWBIOMES 0x08 -#define MGV6_FLAT 0x10 -#define MGV6_TREES 0x20 +#define MGV6_FLAT 0x10 +#define MGV6_TREES 0x20 + extern FlagDesc flagdesc_mapgen_v6[]; + enum BiomeV6Type { BT_NORMAL, @@ -51,8 +53,8 @@ enum BiomeV6Type BT_TAIGA, }; -struct MapgenV6Params : public MapgenParams -{ + +struct MapgenV6Params : public MapgenParams { float freq_desert = 0.45f; float freq_beach = 0.15f; s16 dungeon_ymin = -31000; @@ -78,8 +80,8 @@ struct MapgenV6Params : public MapgenParams void setDefaultSettings(Settings *settings); }; -class MapgenV6 : public Mapgen -{ + +class MapgenV6 : public Mapgen { public: EmergeParams *m_emerge; @@ -140,8 +142,8 @@ public: int getGroundLevelAtPoint(v2s16 p); int getSpawnLevelAtPoint(v2s16 p); - float baseTerrainLevel(float terrain_base, float terrain_higher, float steepness, - float height_select); + float baseTerrainLevel(float terrain_base, float terrain_higher, + float steepness, float height_select); virtual float baseTerrainLevelFromNoise(v2s16 p); virtual float baseTerrainLevelFromMap(v2s16 p); virtual float baseTerrainLevelFromMap(int index); @@ -166,8 +168,8 @@ public: int generateGround(); void addMud(); void flowMud(s16 &mudflow_minpos, s16 &mudflow_maxpos); - void moveMud(u32 remove_index, u32 place_index, u32 above_remove_index, v2s16 pos, - v3s16 em); + void moveMud(u32 remove_index, u32 place_index, + u32 above_remove_index, v2s16 pos, v3s16 em); void growGrass(); void placeTreesAndJungleGrass(); virtual void generateCaves(int max_stone_y); diff --git a/src/mapgen/mapgen_v7.cpp b/src/mapgen/mapgen_v7.cpp index c1ce55348..e93dc9140 100644 --- a/src/mapgen/mapgen_v7.cpp +++ b/src/mapgen/mapgen_v7.cpp @@ -18,6 +18,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 <cmath> #include "voxel.h" @@ -37,80 +38,92 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mg_decoration.h" #include "mapgen_v7.h" -FlagDesc flagdesc_mapgen_v7[] = {{"mountains", MGV7_MOUNTAINS}, {"ridges", MGV7_RIDGES}, - {"floatlands", MGV7_FLOATLANDS}, {"caverns", MGV7_CAVERNS}, {NULL, 0}}; + +FlagDesc flagdesc_mapgen_v7[] = { + {"mountains", MGV7_MOUNTAINS}, + {"ridges", MGV7_RIDGES}, + {"floatlands", MGV7_FLOATLANDS}, + {"caverns", MGV7_CAVERNS}, + {NULL, 0} +}; + //////////////////////////////////////////////////////////////////////////////// -MapgenV7::MapgenV7(MapgenV7Params *params, EmergeParams *emerge) : - MapgenBasic(MAPGEN_V7, params, emerge) + +MapgenV7::MapgenV7(MapgenV7Params *params, EmergeParams *emerge) + : MapgenBasic(MAPGEN_V7, params, emerge) { - spflags = params->spflags; - mount_zero_level = params->mount_zero_level; - floatland_ymin = params->floatland_ymin; - floatland_ymax = params->floatland_ymax; - floatland_taper = params->floatland_taper; - float_taper_exp = params->float_taper_exp; - floatland_density = params->floatland_density; - floatland_ywater = params->floatland_ywater; - - cave_width = params->cave_width; - large_cave_depth = params->large_cave_depth; + spflags = params->spflags; + mount_zero_level = params->mount_zero_level; + floatland_ymin = params->floatland_ymin; + floatland_ymax = params->floatland_ymax; + floatland_taper = params->floatland_taper; + float_taper_exp = params->float_taper_exp; + floatland_density = params->floatland_density; + floatland_ywater = params->floatland_ywater; + + cave_width = params->cave_width; + large_cave_depth = params->large_cave_depth; small_cave_num_min = params->small_cave_num_min; small_cave_num_max = params->small_cave_num_max; large_cave_num_min = params->large_cave_num_min; large_cave_num_max = params->large_cave_num_max; large_cave_flooded = params->large_cave_flooded; - cavern_limit = params->cavern_limit; - cavern_taper = params->cavern_taper; - cavern_threshold = params->cavern_threshold; - dungeon_ymin = params->dungeon_ymin; - dungeon_ymax = params->dungeon_ymax; + cavern_limit = params->cavern_limit; + cavern_taper = params->cavern_taper; + cavern_threshold = params->cavern_threshold; + dungeon_ymin = params->dungeon_ymin; + dungeon_ymax = params->dungeon_ymax; // Allocate floatland noise offset cache this->float_offset_cache = new float[csize.Y + 2]; // 2D noise - noise_terrain_base = new Noise(¶ms->np_terrain_base, seed, csize.X, csize.Z); - noise_terrain_alt = new Noise(¶ms->np_terrain_alt, seed, csize.X, csize.Z); + noise_terrain_base = + new Noise(¶ms->np_terrain_base, seed, csize.X, csize.Z); + noise_terrain_alt = + new Noise(¶ms->np_terrain_alt, seed, csize.X, csize.Z); noise_terrain_persist = - new Noise(¶ms->np_terrain_persist, seed, csize.X, csize.Z); + new Noise(¶ms->np_terrain_persist, seed, csize.X, csize.Z); noise_height_select = - new Noise(¶ms->np_height_select, seed, csize.X, csize.Z); - noise_filler_depth = new Noise(¶ms->np_filler_depth, seed, csize.X, csize.Z); + new Noise(¶ms->np_height_select, seed, csize.X, csize.Z); + noise_filler_depth = + new Noise(¶ms->np_filler_depth, seed, csize.X, csize.Z); if (spflags & MGV7_MOUNTAINS) { // 2D noise - noise_mount_height = new Noise( - ¶ms->np_mount_height, seed, csize.X, csize.Z); + noise_mount_height = + new Noise(¶ms->np_mount_height, seed, csize.X, csize.Z); // 3D noise, 1 up, 1 down overgeneration - noise_mountain = new Noise(¶ms->np_mountain, seed, csize.X, - csize.Y + 2, csize.Z); + noise_mountain = + new Noise(¶ms->np_mountain, seed, csize.X, csize.Y + 2, csize.Z); } if (spflags & MGV7_RIDGES) { // 2D noise - noise_ridge_uwater = new Noise( - ¶ms->np_ridge_uwater, seed, csize.X, csize.Z); + noise_ridge_uwater = + new Noise(¶ms->np_ridge_uwater, seed, csize.X, csize.Z); // 3D noise, 1 up, 1 down overgeneration - noise_ridge = new Noise( - ¶ms->np_ridge, seed, csize.X, csize.Y + 2, csize.Z); + noise_ridge = + new Noise(¶ms->np_ridge, seed, csize.X, csize.Y + 2, csize.Z); } if (spflags & MGV7_FLOATLANDS) { // 3D noise, 1 up, 1 down overgeneration - noise_floatland = new Noise(¶ms->np_floatland, seed, csize.X, - csize.Y + 2, csize.Z); + noise_floatland = + new Noise(¶ms->np_floatland, 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; // 3D noise MapgenBasic::np_dungeons = params->np_dungeons; } + MapgenV7::~MapgenV7() { delete noise_terrain_base; @@ -133,122 +146,128 @@ MapgenV7::~MapgenV7() delete noise_floatland; } - delete[] float_offset_cache; + delete []float_offset_cache; } -MapgenV7Params::MapgenV7Params() : - np_terrain_base(4.0, 70.0, v3f(600, 600, 600), 82341, 5, 0.6, 2.0), - np_terrain_alt(4.0, 25.0, 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.0, 16.0, v3f(500, 500, 500), 4213, 6, 0.7, 2.0), - np_filler_depth(0.0, 1.2, v3f(150, 150, 150), 261, 3, 0.7, 2.0), - np_mount_height(256.0, 112.0, v3f(1000, 1000, 1000), 72449, 3, 0.6, 2.0), - np_ridge_uwater(0.0, 1.0, v3f(1000, 1000, 1000), 85039, 5, 0.6, 2.0), - np_mountain(-0.6, 1.0, v3f(250, 350, 250), 5333, 5, 0.63, 2.0), - np_ridge(0.0, 1.0, v3f(100, 100, 100), 6467, 4, 0.75, 2.0), - np_floatland(0.0, 0.7, v3f(384, 96, 384), 1009, 4, 0.75, 1.618), - 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_dungeons(0.9, 0.5, v3f(500, 500, 500), 0, 2, 0.8, 2.0) + +MapgenV7Params::MapgenV7Params(): + np_terrain_base (4.0, 70.0, v3f(600, 600, 600), 82341, 5, 0.6, 2.0), + np_terrain_alt (4.0, 25.0, 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.0, 16.0, v3f(500, 500, 500), 4213, 6, 0.7, 2.0), + np_filler_depth (0.0, 1.2, v3f(150, 150, 150), 261, 3, 0.7, 2.0), + np_mount_height (256.0, 112.0, v3f(1000, 1000, 1000), 72449, 3, 0.6, 2.0), + np_ridge_uwater (0.0, 1.0, v3f(1000, 1000, 1000), 85039, 5, 0.6, 2.0), + np_mountain (-0.6, 1.0, v3f(250, 350, 250), 5333, 5, 0.63, 2.0), + np_ridge (0.0, 1.0, v3f(100, 100, 100), 6467, 4, 0.75, 2.0), + np_floatland (0.0, 0.7, v3f(384, 96, 384), 1009, 4, 0.75, 1.618), + 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_dungeons (0.9, 0.5, v3f(500, 500, 500), 0, 2, 0.8, 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->getS16NoEx("mgv7_floatland_ymin", floatland_ymin); - settings->getS16NoEx("mgv7_floatland_ymax", floatland_ymax); - settings->getS16NoEx("mgv7_floatland_taper", floatland_taper); - settings->getFloatNoEx("mgv7_float_taper_exp", float_taper_exp); - settings->getFloatNoEx("mgv7_floatland_density", floatland_density); - settings->getS16NoEx("mgv7_floatland_ywater", floatland_ywater); - - settings->getFloatNoEx("mgv7_cave_width", cave_width); - settings->getS16NoEx("mgv7_large_cave_depth", large_cave_depth); - settings->getU16NoEx("mgv7_small_cave_num_min", small_cave_num_min); - settings->getU16NoEx("mgv7_small_cave_num_max", small_cave_num_max); - settings->getU16NoEx("mgv7_large_cave_num_min", large_cave_num_min); - settings->getU16NoEx("mgv7_large_cave_num_max", large_cave_num_max); - settings->getFloatNoEx("mgv7_large_cave_flooded", large_cave_flooded); - settings->getS16NoEx("mgv7_cavern_limit", cavern_limit); - settings->getS16NoEx("mgv7_cavern_taper", cavern_taper); - settings->getFloatNoEx("mgv7_cavern_threshold", cavern_threshold); - settings->getS16NoEx("mgv7_dungeon_ymin", dungeon_ymin); - settings->getS16NoEx("mgv7_dungeon_ymax", dungeon_ymax); - - settings->getNoiseParams("mgv7_np_terrain_base", np_terrain_base); - settings->getNoiseParams("mgv7_np_terrain_alt", np_terrain_alt); + settings->getS16NoEx("mgv7_mount_zero_level", mount_zero_level); + settings->getS16NoEx("mgv7_floatland_ymin", floatland_ymin); + settings->getS16NoEx("mgv7_floatland_ymax", floatland_ymax); + settings->getS16NoEx("mgv7_floatland_taper", floatland_taper); + settings->getFloatNoEx("mgv7_float_taper_exp", float_taper_exp); + settings->getFloatNoEx("mgv7_floatland_density", floatland_density); + settings->getS16NoEx("mgv7_floatland_ywater", floatland_ywater); + + settings->getFloatNoEx("mgv7_cave_width", cave_width); + settings->getS16NoEx("mgv7_large_cave_depth", large_cave_depth); + settings->getU16NoEx("mgv7_small_cave_num_min", small_cave_num_min); + settings->getU16NoEx("mgv7_small_cave_num_max", small_cave_num_max); + settings->getU16NoEx("mgv7_large_cave_num_min", large_cave_num_min); + settings->getU16NoEx("mgv7_large_cave_num_max", large_cave_num_max); + settings->getFloatNoEx("mgv7_large_cave_flooded", large_cave_flooded); + settings->getS16NoEx("mgv7_cavern_limit", cavern_limit); + settings->getS16NoEx("mgv7_cavern_taper", cavern_taper); + settings->getFloatNoEx("mgv7_cavern_threshold", cavern_threshold); + settings->getS16NoEx("mgv7_dungeon_ymin", dungeon_ymin); + settings->getS16NoEx("mgv7_dungeon_ymax", dungeon_ymax); + + settings->getNoiseParams("mgv7_np_terrain_base", np_terrain_base); + settings->getNoiseParams("mgv7_np_terrain_alt", np_terrain_alt); settings->getNoiseParams("mgv7_np_terrain_persist", np_terrain_persist); - settings->getNoiseParams("mgv7_np_height_select", np_height_select); - settings->getNoiseParams("mgv7_np_filler_depth", np_filler_depth); - settings->getNoiseParams("mgv7_np_mount_height", np_mount_height); - settings->getNoiseParams("mgv7_np_ridge_uwater", np_ridge_uwater); - settings->getNoiseParams("mgv7_np_mountain", np_mountain); - settings->getNoiseParams("mgv7_np_ridge", np_ridge); - settings->getNoiseParams("mgv7_np_floatland", np_floatland); - 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); + settings->getNoiseParams("mgv7_np_height_select", np_height_select); + settings->getNoiseParams("mgv7_np_filler_depth", np_filler_depth); + settings->getNoiseParams("mgv7_np_mount_height", np_mount_height); + settings->getNoiseParams("mgv7_np_ridge_uwater", np_ridge_uwater); + settings->getNoiseParams("mgv7_np_mountain", np_mountain); + settings->getNoiseParams("mgv7_np_ridge", np_ridge); + settings->getNoiseParams("mgv7_np_floatland", np_floatland); + 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); } + void MapgenV7Params::writeParams(Settings *settings) const { settings->setFlagStr("mgv7_spflags", spflags, flagdesc_mapgen_v7); - settings->setS16("mgv7_mount_zero_level", mount_zero_level); - settings->setS16("mgv7_floatland_ymin", floatland_ymin); - settings->setS16("mgv7_floatland_ymax", floatland_ymax); - settings->setS16("mgv7_floatland_taper", floatland_taper); - settings->setFloat("mgv7_float_taper_exp", float_taper_exp); - settings->setFloat("mgv7_floatland_density", floatland_density); - settings->setS16("mgv7_floatland_ywater", floatland_ywater); - - settings->setFloat("mgv7_cave_width", cave_width); - settings->setS16("mgv7_large_cave_depth", large_cave_depth); - settings->setU16("mgv7_small_cave_num_min", small_cave_num_min); - settings->setU16("mgv7_small_cave_num_max", small_cave_num_max); - settings->setU16("mgv7_large_cave_num_min", large_cave_num_min); - settings->setU16("mgv7_large_cave_num_max", large_cave_num_max); - settings->setFloat("mgv7_large_cave_flooded", large_cave_flooded); - settings->setS16("mgv7_cavern_limit", cavern_limit); - settings->setS16("mgv7_cavern_taper", cavern_taper); - settings->setFloat("mgv7_cavern_threshold", cavern_threshold); - settings->setS16("mgv7_dungeon_ymin", dungeon_ymin); - settings->setS16("mgv7_dungeon_ymax", dungeon_ymax); - - settings->setNoiseParams("mgv7_np_terrain_base", np_terrain_base); - settings->setNoiseParams("mgv7_np_terrain_alt", np_terrain_alt); + settings->setS16("mgv7_mount_zero_level", mount_zero_level); + settings->setS16("mgv7_floatland_ymin", floatland_ymin); + settings->setS16("mgv7_floatland_ymax", floatland_ymax); + settings->setS16("mgv7_floatland_taper", floatland_taper); + settings->setFloat("mgv7_float_taper_exp", float_taper_exp); + settings->setFloat("mgv7_floatland_density", floatland_density); + settings->setS16("mgv7_floatland_ywater", floatland_ywater); + + settings->setFloat("mgv7_cave_width", cave_width); + settings->setS16("mgv7_large_cave_depth", large_cave_depth); + settings->setU16("mgv7_small_cave_num_min", small_cave_num_min); + settings->setU16("mgv7_small_cave_num_max", small_cave_num_max); + settings->setU16("mgv7_large_cave_num_min", large_cave_num_min); + settings->setU16("mgv7_large_cave_num_max", large_cave_num_max); + settings->setFloat("mgv7_large_cave_flooded", large_cave_flooded); + settings->setS16("mgv7_cavern_limit", cavern_limit); + settings->setS16("mgv7_cavern_taper", cavern_taper); + settings->setFloat("mgv7_cavern_threshold", cavern_threshold); + settings->setS16("mgv7_dungeon_ymin", dungeon_ymin); + settings->setS16("mgv7_dungeon_ymax", dungeon_ymax); + + settings->setNoiseParams("mgv7_np_terrain_base", np_terrain_base); + settings->setNoiseParams("mgv7_np_terrain_alt", np_terrain_alt); settings->setNoiseParams("mgv7_np_terrain_persist", np_terrain_persist); - settings->setNoiseParams("mgv7_np_height_select", np_height_select); - settings->setNoiseParams("mgv7_np_filler_depth", np_filler_depth); - settings->setNoiseParams("mgv7_np_mount_height", np_mount_height); - settings->setNoiseParams("mgv7_np_ridge_uwater", np_ridge_uwater); - settings->setNoiseParams("mgv7_np_mountain", np_mountain); - settings->setNoiseParams("mgv7_np_ridge", np_ridge); - settings->setNoiseParams("mgv7_np_floatland", np_floatland); - 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); + settings->setNoiseParams("mgv7_np_height_select", np_height_select); + settings->setNoiseParams("mgv7_np_filler_depth", np_filler_depth); + settings->setNoiseParams("mgv7_np_mount_height", np_mount_height); + settings->setNoiseParams("mgv7_np_ridge_uwater", np_ridge_uwater); + settings->setNoiseParams("mgv7_np_mountain", np_mountain); + settings->setNoiseParams("mgv7_np_ridge", np_ridge); + settings->setNoiseParams("mgv7_np_floatland", np_floatland); + 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); } + void MapgenV7Params::setDefaultSettings(Settings *settings) { settings->setDefault("mgv7_spflags", flagdesc_mapgen_v7, - MGV7_MOUNTAINS | MGV7_RIDGES | MGV7_CAVERNS); + MGV7_MOUNTAINS | MGV7_RIDGES | MGV7_CAVERNS); } + //////////////////////////////////////////////////////////////////////////////// + int MapgenV7::getSpawnLevelAtPoint(v2s16 p) { // If rivers are enabled, first check if in a river if (spflags & MGV7_RIDGES) { float width = 0.2f; float uwatern = NoisePerlin2D(&noise_ridge_uwater->np, p.X, p.Y, seed) * - 2.0f; + 2.0f; if (std::fabs(uwatern) <= width) return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point } @@ -259,7 +278,7 @@ int MapgenV7::getSpawnLevelAtPoint(v2s16 p) // 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 = std::fmax(std::fmax(noise_terrain_alt->np.offset, - noise_terrain_base->np.offset), + noise_terrain_base->np.offset), water_level + 16); // Base terrain calculation s16 y = baseTerrainLevelAtPoint(p.X, p.Y); @@ -292,19 +311,20 @@ int MapgenV7::getSpawnLevelAtPoint(v2s16 p) return MAX_MAP_GENERATION_LIMIT; } + void MapgenV7::makeChunk(BlockMakeData *data) { // Pre-conditions 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); - // TimeTaker t("makeChunk"); + //TimeTaker t("makeChunk"); this->generating = true; this->vm = data->vmanip; @@ -350,8 +370,8 @@ void MapgenV7::makeChunk(BlockMakeData *data) // Disable large randomwalk caves in this mapchunk by setting // 'large cave depth' to world base. Avoids excessive liquid in // large caverns and floating blobs of overgenerated liquid. - generateCavesRandomWalk( - stone_surface_max_y, -MAX_MAP_GENERATION_LIMIT); + generateCavesRandomWalk(stone_surface_max_y, + -MAX_MAP_GENERATION_LIMIT); else generateCavesRandomWalk(stone_surface_max_y, large_cave_depth); } @@ -377,20 +397,21 @@ void MapgenV7::makeChunk(BlockMakeData *data) // Calculate lighting // Limit floatland shadows bool propagate_shadow = !((spflags & MGV7_FLOATLANDS) && - node_max.Y >= floatland_ymin - csize.Y * 2 && - node_min.Y <= floatland_ymax); + node_max.Y >= floatland_ymin - csize.Y * 2 && node_min.Y <= floatland_ymax); if (flags & MG_LIGHT) calcLighting(node_min - v3s16(0, 1, 0), node_max + v3s16(0, 1, 0), - full_node_min, full_node_max, propagate_shadow); + full_node_min, full_node_max, propagate_shadow); this->generating = false; - // printf("makeChunk: %lums\n", t.stop()); + //printf("makeChunk: %lums\n", t.stop()); } + //////////////////////////////////////////////////////////////////////////////// + float MapgenV7::baseTerrainLevelAtPoint(s16 x, s16 z) { float hselect = NoisePerlin2D(&noise_height_select->np, x, z, seed); @@ -410,6 +431,7 @@ float MapgenV7::baseTerrainLevelAtPoint(s16 x, s16 z) return (height_base * hselect) + (height_alt * (1.0f - hselect)); } + float MapgenV7::baseTerrainLevelFromMap(int index) { float hselect = rangelim(noise_height_select->result[index], 0.0f, 1.0f); @@ -422,16 +444,18 @@ float MapgenV7::baseTerrainLevelFromMap(int index) return (height_base * hselect) + (height_alt * (1.0f - hselect)); } + bool MapgenV7::getMountainTerrainAtPoint(s16 x, s16 y, s16 z) { - float mnt_h_n = std::fmax( - NoisePerlin2D(&noise_mount_height->np, x, z, seed), 1.0f); + float mnt_h_n = + std::fmax(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.0f; } + bool MapgenV7::getMountainTerrainFromMap(int idx_xyz, int idx_xz, s16 y) { float mounthn = std::fmax(noise_mount_height->result[idx_xz], 1.0f); @@ -441,12 +465,13 @@ bool MapgenV7::getMountainTerrainFromMap(int idx_xyz, int idx_xz, s16 y) return mountn + density_gradient >= 0.0f; } + bool MapgenV7::getFloatlandTerrainFromMap(int idx_xyz, float float_offset) { - return noise_floatland->result[idx_xyz] + floatland_density - float_offset >= - 0.0f; + return noise_floatland->result[idx_xyz] + floatland_density - float_offset >= 0.0f; } + int MapgenV7::generateTerrain() { MapNode n_air(CONTENT_AIR); @@ -475,8 +500,8 @@ int MapgenV7::generateTerrain() s16 float_taper_ymax = floatland_ymax - floatland_taper; s16 float_taper_ymin = floatland_ymin + floatland_taper; - if ((spflags & MGV7_FLOATLANDS) && node_max.Y >= floatland_ymin && - node_min.Y <= floatland_ymax) { + if ((spflags & MGV7_FLOATLANDS) && + node_max.Y >= floatland_ymin && node_min.Y <= floatland_ymax) { gen_floatlands = true; // Calculate noise for floatland generation noise_floatland->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z); @@ -485,15 +510,11 @@ int MapgenV7::generateTerrain() for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++, cache_index++) { float float_offset = 0.0f; if (y > float_taper_ymax) { - float_offset = std::pow((y - float_taper_ymax) / - (float)floatland_taper, - float_taper_exp) * - 4.0f; + float_offset = std::pow((y - float_taper_ymax) / (float)floatland_taper, + float_taper_exp) * 4.0f; } else if (y < float_taper_ymin) { - float_offset = std::pow((float_taper_ymin - - y) / (float)floatland_taper, - float_taper_exp) * - 4.0f; + float_offset = std::pow((float_taper_ymin - y) / (float)floatland_taper, + float_taper_exp) * 4.0f; } float_offset_cache[cache_index] = float_offset; } @@ -505,51 +526,50 @@ int MapgenV7::generateTerrain() u32 index2d = 0; for (s16 z = node_min.Z; z <= node_max.Z; z++) - for (s16 x = node_min.X; x <= node_max.X; x++, index2d++) { - s16 surface_y = baseTerrainLevelFromMap(index2d); - if (surface_y > stone_surface_max_y) - stone_surface_max_y = surface_y; - - cache_index = 0; - u32 vi = vm->m_area.index(x, node_min.Y - 1, z); - u32 index3d = (z - node_min.Z) * zstride_1u1d + (x - node_min.X); - - for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++, - index3d += ystride, VoxelArea::add_y(em, vi, 1), - cache_index++) { - if (vm->m_data[vi].getContent() != CONTENT_IGNORE) - continue; - - if (y <= surface_y) { - vm->m_data[vi] = n_stone; // Base terrain - } else if ((spflags & MGV7_MOUNTAINS) && - getMountainTerrainFromMap( - index3d, index2d, y)) { - vm->m_data[vi] = n_stone; // Mountain terrain - if (y > stone_surface_max_y) - stone_surface_max_y = y; - } else if (gen_floatlands && - getFloatlandTerrainFromMap(index3d, - float_offset_cache - [cache_index])) { - vm->m_data[vi] = n_stone; // Floatland terrain - if (y > stone_surface_max_y) - stone_surface_max_y = y; - } else if (y <= water_level) { // Surface water - vm->m_data[vi] = n_water; - } else if (gen_floatlands && y >= float_taper_ymax && - y <= floatland_ywater) { - vm->m_data[vi] = n_water; // Water for solid - // floatland layer only - } else { - vm->m_data[vi] = n_air; // Air - } + for (s16 x = node_min.X; x <= node_max.X; x++, index2d++) { + s16 surface_y = baseTerrainLevelFromMap(index2d); + if (surface_y > stone_surface_max_y) + stone_surface_max_y = surface_y; + + cache_index = 0; + u32 vi = vm->m_area.index(x, node_min.Y - 1, z); + u32 index3d = (z - node_min.Z) * zstride_1u1d + (x - node_min.X); + + for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; + y++, + index3d += ystride, + VoxelArea::add_y(em, vi, 1), + cache_index++) { + if (vm->m_data[vi].getContent() != CONTENT_IGNORE) + continue; + + if (y <= surface_y) { + vm->m_data[vi] = n_stone; // Base terrain + } else if ((spflags & MGV7_MOUNTAINS) && + getMountainTerrainFromMap(index3d, index2d, y)) { + vm->m_data[vi] = n_stone; // Mountain terrain + if (y > stone_surface_max_y) + stone_surface_max_y = y; + } else if (gen_floatlands && + getFloatlandTerrainFromMap(index3d, + float_offset_cache[cache_index])) { + vm->m_data[vi] = n_stone; // Floatland terrain + if (y > stone_surface_max_y) + stone_surface_max_y = y; + } else if (y <= water_level) { // Surface water + vm->m_data[vi] = n_water; + } else if (gen_floatlands && y >= float_taper_ymax && y <= floatland_ywater) { + vm->m_data[vi] = n_water; // Water for solid floatland layer only + } else { + vm->m_data[vi] = n_air; // Air } } + } return stone_surface_max_y; } + void MapgenV7::generateRidgeTerrain() { if (node_max.Y < water_level - 16 || @@ -565,31 +585,28 @@ void MapgenV7::generateRidgeTerrain() float width = 0.2f; 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++, index3d++, vi++) { - u32 index2d = (z - node_min.Z) * csize.X + - (x - node_min.X); - float uwatern = noise_ridge_uwater->result[index2d] * - 2.0f; - if (std::fabs(uwatern) > width) - continue; - // Optimises, but also avoids removing nodes placed by - // mods in 'on-generated', when generating outside - // mapchunk. - content_t c = vm->m_data[vi].getContent(); - if (c != c_stone) - continue; - - float altitude = y - water_level; - float height_mod = (altitude + 17.0f) / 2.5f; - float width_mod = width - std::fabs(uwatern); - float nridge = noise_ridge->result[index3d] * - std::fmax(altitude, 0.0f) / 7.0f; - if (nridge + width_mod * height_mod < 0.6f) - continue; - - vm->m_data[vi] = (y > water_level) ? n_air : n_water; - } + 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++, index3d++, vi++) { + u32 index2d = (z - node_min.Z) * csize.X + (x - node_min.X); + float uwatern = noise_ridge_uwater->result[index2d] * 2.0f; + if (std::fabs(uwatern) > width) + continue; + // Optimises, but also avoids removing nodes placed by mods in + // 'on-generated', when generating outside mapchunk. + content_t c = vm->m_data[vi].getContent(); + if (c != c_stone) + continue; + + float altitude = y - water_level; + float height_mod = (altitude + 17.0f) / 2.5f; + float width_mod = width - std::fabs(uwatern); + float nridge = noise_ridge->result[index3d] * + std::fmax(altitude, 0.0f) / 7.0f; + if (nridge + width_mod * height_mod < 0.6f) + continue; + + vm->m_data[vi] = (y > water_level) ? n_air : n_water; } + } } diff --git a/src/mapgen/mapgen_v7.h b/src/mapgen/mapgen_v7.h index b51ff10ce..4020cd935 100644 --- a/src/mapgen/mapgen_v7.h +++ b/src/mapgen/mapgen_v7.h @@ -23,18 +23,18 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mapgen.h" ///////////// Mapgen V7 flags -#define MGV7_MOUNTAINS 0x01 -#define MGV7_RIDGES 0x02 -#define MGV7_FLOATLANDS 0x04 -#define MGV7_CAVERNS 0x08 +#define MGV7_MOUNTAINS 0x01 +#define MGV7_RIDGES 0x02 +#define MGV7_FLOATLANDS 0x04 +#define MGV7_CAVERNS 0x08 #define MGV7_BIOMEREPEAT 0x10 // Now unused class BiomeManager; extern FlagDesc flagdesc_mapgen_v7[]; -struct MapgenV7Params : public MapgenParams -{ + +struct MapgenV7Params : public MapgenParams { s16 mount_zero_level = 0; s16 floatland_ymin = 1024; s16 floatland_ymax = 4096; @@ -79,8 +79,8 @@ struct MapgenV7Params : public MapgenParams void setDefaultSettings(Settings *settings); }; -class MapgenV7 : public MapgenBasic -{ + +class MapgenV7 : public MapgenBasic { public: MapgenV7(MapgenV7Params *params, EmergeParams *emerge); ~MapgenV7(); diff --git a/src/mapgen/mapgen_valleys.cpp b/src/mapgen/mapgen_valleys.cpp index d06b05990..efcc8ee85 100644 --- a/src/mapgen/mapgen_valleys.cpp +++ b/src/mapgen/mapgen_valleys.cpp @@ -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" @@ -43,57 +44,60 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "cavegen.h" #include <cmath> -FlagDesc flagdesc_mapgen_valleys[] = {{"altitude_chill", MGVALLEYS_ALT_CHILL}, - {"humid_rivers", MGVALLEYS_HUMID_RIVERS}, - {"vary_river_depth", MGVALLEYS_VARY_RIVER_DEPTH}, - {"altitude_dry", MGVALLEYS_ALT_DRY}, {NULL, 0}}; -MapgenValleys::MapgenValleys(MapgenValleysParams *params, EmergeParams *emerge) : - MapgenBasic(MAPGEN_VALLEYS, params, emerge) +FlagDesc flagdesc_mapgen_valleys[] = { + {"altitude_chill", MGVALLEYS_ALT_CHILL}, + {"humid_rivers", MGVALLEYS_HUMID_RIVERS}, + {"vary_river_depth", MGVALLEYS_VARY_RIVER_DEPTH}, + {"altitude_dry", MGVALLEYS_ALT_DRY}, + {NULL, 0} +}; + + +MapgenValleys::MapgenValleys(MapgenValleysParams *params, EmergeParams *emerge) + : MapgenBasic(MAPGEN_VALLEYS, params, emerge) { // NOTE: MapgenValleys has a hard dependency on BiomeGenOriginal m_bgen = (BiomeGenOriginal *)biomegen; - spflags = params->spflags; - altitude_chill = params->altitude_chill; - river_depth_bed = params->river_depth + 1.0f; - river_size_factor = params->river_size / 100.0f; + spflags = params->spflags; + altitude_chill = params->altitude_chill; + river_depth_bed = params->river_depth + 1.0f; + river_size_factor = params->river_size / 100.0f; - cave_width = params->cave_width; - large_cave_depth = params->large_cave_depth; + cave_width = params->cave_width; + large_cave_depth = params->large_cave_depth; small_cave_num_min = params->small_cave_num_min; small_cave_num_max = params->small_cave_num_max; large_cave_num_min = params->large_cave_num_min; large_cave_num_max = params->large_cave_num_max; large_cave_flooded = params->large_cave_flooded; - cavern_limit = params->cavern_limit; - cavern_taper = params->cavern_taper; - cavern_threshold = params->cavern_threshold; - dungeon_ymin = params->dungeon_ymin; - dungeon_ymax = params->dungeon_ymax; + cavern_limit = params->cavern_limit; + cavern_taper = params->cavern_taper; + cavern_threshold = params->cavern_threshold; + dungeon_ymin = params->dungeon_ymin; + dungeon_ymax = params->dungeon_ymax; //// 2D Terrain noise - noise_filler_depth = new Noise(¶ms->np_filler_depth, seed, csize.X, csize.Z); - noise_inter_valley_slope = - new Noise(¶ms->np_inter_valley_slope, seed, csize.X, csize.Z); - noise_rivers = new Noise(¶ms->np_rivers, seed, csize.X, csize.Z); - noise_terrain_height = - new Noise(¶ms->np_terrain_height, seed, csize.X, csize.Z); - noise_valley_depth = new Noise(¶ms->np_valley_depth, seed, csize.X, csize.Z); - noise_valley_profile = - new Noise(¶ms->np_valley_profile, seed, csize.X, csize.Z); + noise_filler_depth = new Noise(¶ms->np_filler_depth, seed, csize.X, csize.Z); + noise_inter_valley_slope = new Noise(¶ms->np_inter_valley_slope, seed, csize.X, csize.Z); + noise_rivers = new Noise(¶ms->np_rivers, seed, csize.X, csize.Z); + noise_terrain_height = new Noise(¶ms->np_terrain_height, seed, csize.X, csize.Z); + noise_valley_depth = new Noise(¶ms->np_valley_depth, seed, csize.X, csize.Z); + noise_valley_profile = new Noise(¶ms->np_valley_profile, seed, csize.X, csize.Z); //// 3D Terrain noise // 1-up 1-down overgeneration - noise_inter_valley_fill = new Noise(¶ms->np_inter_valley_fill, seed, csize.X, - csize.Y + 2, csize.Z); + 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; + MapgenBasic::np_cave1 = params->np_cave1; + MapgenBasic::np_cave2 = params->np_cave2; + MapgenBasic::np_cavern = params->np_cavern; MapgenBasic::np_dungeons = params->np_dungeons; } + MapgenValleys::~MapgenValleys() { delete noise_filler_depth; @@ -105,111 +109,115 @@ MapgenValleys::~MapgenValleys() delete noise_valley_profile; } -MapgenValleysParams::MapgenValleysParams() : - np_filler_depth(0.0, 1.2, v3f(256, 256, 256), 1605, 3, 0.5, 2.0), - np_inter_valley_fill(0.0, 1.0, v3f(256, 512, 256), 1993, 6, 0.8, 2.0), - np_inter_valley_slope(0.5, 0.5, v3f(128, 128, 128), 746, 1, 1.0, 2.0), - np_rivers(0.0, 1.0, v3f(256, 256, 256), -6050, 5, 0.6, 2.0), - np_terrain_height(-10.0, 50.0, v3f(1024, 1024, 1024), 5202, 6, 0.4, 2.0), - np_valley_depth(5.0, 4.0, v3f(512, 512, 512), -1914, 1, 1.0, 2.0), - 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_dungeons(0.9, 0.5, v3f(500, 500, 500), 0, 2, 0.8, 2.0) + +MapgenValleysParams::MapgenValleysParams(): + np_filler_depth (0.0, 1.2, v3f(256, 256, 256), 1605, 3, 0.5, 2.0), + np_inter_valley_fill (0.0, 1.0, v3f(256, 512, 256), 1993, 6, 0.8, 2.0), + np_inter_valley_slope (0.5, 0.5, v3f(128, 128, 128), 746, 1, 1.0, 2.0), + np_rivers (0.0, 1.0, v3f(256, 256, 256), -6050, 5, 0.6, 2.0), + np_terrain_height (-10.0, 50.0, v3f(1024, 1024, 1024), 5202, 6, 0.4, 2.0), + np_valley_depth (5.0, 4.0, v3f(512, 512, 512), -1914, 1, 1.0, 2.0), + 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_dungeons (0.9, 0.5, v3f(500, 500, 500), 0, 2, 0.8, 2.0) { } + void MapgenValleysParams::readParams(const Settings *settings) { settings->getFlagStrNoEx("mgvalleys_spflags", spflags, flagdesc_mapgen_valleys); - settings->getU16NoEx("mgvalleys_altitude_chill", altitude_chill); - settings->getS16NoEx("mgvalleys_large_cave_depth", large_cave_depth); - settings->getU16NoEx("mgvalleys_small_cave_num_min", small_cave_num_min); - settings->getU16NoEx("mgvalleys_small_cave_num_max", small_cave_num_max); - settings->getU16NoEx("mgvalleys_large_cave_num_min", large_cave_num_min); - settings->getU16NoEx("mgvalleys_large_cave_num_max", large_cave_num_max); + settings->getU16NoEx("mgvalleys_altitude_chill", altitude_chill); + settings->getS16NoEx("mgvalleys_large_cave_depth", large_cave_depth); + settings->getU16NoEx("mgvalleys_small_cave_num_min", small_cave_num_min); + settings->getU16NoEx("mgvalleys_small_cave_num_max", small_cave_num_max); + settings->getU16NoEx("mgvalleys_large_cave_num_min", large_cave_num_min); + settings->getU16NoEx("mgvalleys_large_cave_num_max", large_cave_num_max); settings->getFloatNoEx("mgvalleys_large_cave_flooded", large_cave_flooded); - settings->getU16NoEx("mgvalleys_river_depth", river_depth); - settings->getU16NoEx("mgvalleys_river_size", river_size); - settings->getFloatNoEx("mgvalleys_cave_width", cave_width); - settings->getS16NoEx("mgvalleys_cavern_limit", cavern_limit); - settings->getS16NoEx("mgvalleys_cavern_taper", cavern_taper); - settings->getFloatNoEx("mgvalleys_cavern_threshold", cavern_threshold); - settings->getS16NoEx("mgvalleys_dungeon_ymin", dungeon_ymin); - settings->getS16NoEx("mgvalleys_dungeon_ymax", dungeon_ymax); - - settings->getNoiseParams("mgvalleys_np_filler_depth", np_filler_depth); - settings->getNoiseParams("mgvalleys_np_inter_valley_fill", np_inter_valley_fill); - settings->getNoiseParams( - "mgvalleys_np_inter_valley_slope", np_inter_valley_slope); - settings->getNoiseParams("mgvalleys_np_rivers", np_rivers); - settings->getNoiseParams("mgvalleys_np_terrain_height", np_terrain_height); - settings->getNoiseParams("mgvalleys_np_valley_depth", np_valley_depth); - settings->getNoiseParams("mgvalleys_np_valley_profile", np_valley_profile); - - 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); + settings->getU16NoEx("mgvalleys_river_depth", river_depth); + settings->getU16NoEx("mgvalleys_river_size", river_size); + settings->getFloatNoEx("mgvalleys_cave_width", cave_width); + settings->getS16NoEx("mgvalleys_cavern_limit", cavern_limit); + settings->getS16NoEx("mgvalleys_cavern_taper", cavern_taper); + settings->getFloatNoEx("mgvalleys_cavern_threshold", cavern_threshold); + settings->getS16NoEx("mgvalleys_dungeon_ymin", dungeon_ymin); + settings->getS16NoEx("mgvalleys_dungeon_ymax", dungeon_ymax); + + settings->getNoiseParams("mgvalleys_np_filler_depth", np_filler_depth); + settings->getNoiseParams("mgvalleys_np_inter_valley_fill", np_inter_valley_fill); + settings->getNoiseParams("mgvalleys_np_inter_valley_slope", np_inter_valley_slope); + settings->getNoiseParams("mgvalleys_np_rivers", np_rivers); + settings->getNoiseParams("mgvalleys_np_terrain_height", np_terrain_height); + settings->getNoiseParams("mgvalleys_np_valley_depth", np_valley_depth); + settings->getNoiseParams("mgvalleys_np_valley_profile", np_valley_profile); + + 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); } + void MapgenValleysParams::writeParams(Settings *settings) const { settings->setFlagStr("mgvalleys_spflags", spflags, flagdesc_mapgen_valleys); - settings->setU16("mgvalleys_altitude_chill", altitude_chill); - settings->setS16("mgvalleys_large_cave_depth", large_cave_depth); - settings->setU16("mgvalleys_small_cave_num_min", small_cave_num_min); - settings->setU16("mgvalleys_small_cave_num_max", small_cave_num_max); - settings->setU16("mgvalleys_large_cave_num_min", large_cave_num_min); - settings->setU16("mgvalleys_large_cave_num_max", large_cave_num_max); + settings->setU16("mgvalleys_altitude_chill", altitude_chill); + settings->setS16("mgvalleys_large_cave_depth", large_cave_depth); + settings->setU16("mgvalleys_small_cave_num_min", small_cave_num_min); + settings->setU16("mgvalleys_small_cave_num_max", small_cave_num_max); + settings->setU16("mgvalleys_large_cave_num_min", large_cave_num_min); + settings->setU16("mgvalleys_large_cave_num_max", large_cave_num_max); settings->setFloat("mgvalleys_large_cave_flooded", large_cave_flooded); - settings->setU16("mgvalleys_river_depth", river_depth); - settings->setU16("mgvalleys_river_size", river_size); - settings->setFloat("mgvalleys_cave_width", cave_width); - settings->setS16("mgvalleys_cavern_limit", cavern_limit); - settings->setS16("mgvalleys_cavern_taper", cavern_taper); - settings->setFloat("mgvalleys_cavern_threshold", cavern_threshold); - settings->setS16("mgvalleys_dungeon_ymin", dungeon_ymin); - settings->setS16("mgvalleys_dungeon_ymax", dungeon_ymax); - - settings->setNoiseParams("mgvalleys_np_filler_depth", np_filler_depth); - settings->setNoiseParams("mgvalleys_np_inter_valley_fill", np_inter_valley_fill); - settings->setNoiseParams( - "mgvalleys_np_inter_valley_slope", np_inter_valley_slope); - settings->setNoiseParams("mgvalleys_np_rivers", np_rivers); - settings->setNoiseParams("mgvalleys_np_terrain_height", np_terrain_height); - settings->setNoiseParams("mgvalleys_np_valley_depth", np_valley_depth); - settings->setNoiseParams("mgvalleys_np_valley_profile", np_valley_profile); - - 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); + settings->setU16("mgvalleys_river_depth", river_depth); + settings->setU16("mgvalleys_river_size", river_size); + settings->setFloat("mgvalleys_cave_width", cave_width); + settings->setS16("mgvalleys_cavern_limit", cavern_limit); + settings->setS16("mgvalleys_cavern_taper", cavern_taper); + settings->setFloat("mgvalleys_cavern_threshold", cavern_threshold); + settings->setS16("mgvalleys_dungeon_ymin", dungeon_ymin); + settings->setS16("mgvalleys_dungeon_ymax", dungeon_ymax); + + settings->setNoiseParams("mgvalleys_np_filler_depth", np_filler_depth); + settings->setNoiseParams("mgvalleys_np_inter_valley_fill", np_inter_valley_fill); + settings->setNoiseParams("mgvalleys_np_inter_valley_slope", np_inter_valley_slope); + settings->setNoiseParams("mgvalleys_np_rivers", np_rivers); + settings->setNoiseParams("mgvalleys_np_terrain_height", np_terrain_height); + settings->setNoiseParams("mgvalleys_np_valley_depth", np_valley_depth); + settings->setNoiseParams("mgvalleys_np_valley_profile", np_valley_profile); + + 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 MapgenValleysParams::setDefaultSettings(Settings *settings) { settings->setDefault("mgvalleys_spflags", flagdesc_mapgen_valleys, - MGVALLEYS_ALT_CHILL | MGVALLEYS_HUMID_RIVERS | - MGVALLEYS_VARY_RIVER_DEPTH | MGVALLEYS_ALT_DRY); + MGVALLEYS_ALT_CHILL | MGVALLEYS_HUMID_RIVERS | + MGVALLEYS_VARY_RIVER_DEPTH | MGVALLEYS_ALT_DRY); } + ///////////////////////////////////////////////////////////////// + void MapgenValleys::makeChunk(BlockMakeData *data) { // Pre-conditions 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); - // TimeTaker t("makeChunk"); + //TimeTaker t("makeChunk"); this->generating = true; this->vm = data->vmanip; @@ -253,8 +261,8 @@ void MapgenValleys::makeChunk(BlockMakeData *data) // Disable large randomwalk caves in this mapchunk by setting // 'large cave depth' to world base. Avoids excessive liquid in // large caverns and floating blobs of overgenerated liquid. - generateCavesRandomWalk( - stone_surface_max_y, -MAX_MAP_GENERATION_LIMIT); + generateCavesRandomWalk(stone_surface_max_y, + -MAX_MAP_GENERATION_LIMIT); else generateCavesRandomWalk(stone_surface_max_y, large_cave_depth); } @@ -278,13 +286,14 @@ void MapgenValleys::makeChunk(BlockMakeData *data) if (flags & MG_LIGHT) calcLighting(node_min - v3s16(0, 1, 0), node_max + v3s16(0, 1, 0), - full_node_min, full_node_max); + full_node_min, full_node_max); this->generating = false; - // printf("makeChunk: %lums\n", t.stop()); + //printf("makeChunk: %lums\n", t.stop()); } + int MapgenValleys::getSpawnLevelAtPoint(v2s16 p) { // Check if in a river channel @@ -293,9 +302,9 @@ int MapgenValleys::getSpawnLevelAtPoint(v2s16 p) // Unsuitable spawn point return MAX_MAP_GENERATION_LIMIT; - float n_slope = NoisePerlin2D(&noise_inter_valley_slope->np, p.X, p.Y, seed); + 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 = 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; @@ -307,25 +316,23 @@ int MapgenValleys::getSpawnLevelAtPoint(v2s16 p) 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. + // 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); + 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 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 (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; @@ -338,6 +345,7 @@ int MapgenValleys::getSpawnLevelAtPoint(v2s16 p) return MAX_MAP_GENERATION_LIMIT; } + int MapgenValleys::generateTerrain() { MapNode n_air(CONTENT_AIR); @@ -358,142 +366,122 @@ int MapgenValleys::generateTerrain() 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 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 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; - } + for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) { + 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 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 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) / 300.0f; - river_y += delta * std::fmax(t_evap, 0.08f); - } + // Optionally vary river depth according to heat and humidity + if (spflags & MGVALLEYS_VARY_RIVER_DEPTH) { + 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) / 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 n_fill = noise_inter_valley_fill - ->result[index_3d]; - float surface_delta = (float)y - surface_y; - // Density = density noise + density gradient - float density = slope * n_fill - surface_delta; - - if (density > 0.0f) { - vm->m_data[index_data] = n_stone; // Stone - 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 (y <= (s16)river_y) { - vm->m_data[index_data] = - n_river_water; // River - // water - } else { - vm->m_data[index_data] = n_air; // Air - } + // 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 n_fill = noise_inter_valley_fill->result[index_3d]; + float surface_delta = (float)y - surface_y; + // Density = density noise + density gradient + float density = slope * n_fill - surface_delta; + + if (density > 0.0f) { + vm->m_data[index_data] = n_stone; // Stone + 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 (y <= (s16)river_y) { + vm->m_data[index_data] = n_river_water; // River water + } else { + vm->m_data[index_data] = n_air; // Air } - - VoxelArea::add_y(em, index_data, 1); - index_3d += ystride; } - // 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(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)); - } + VoxelArea::add_y(em, index_data, 1); + index_3d += ystride; + } - // Optionally decrease humidity with altitude - if (spflags & MGVALLEYS_ALT_DRY) { - // Ground height ignoring riverbeds - 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] -= - (t_alt - water_level) * 10.0f / - altitude_chill; - } + // 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(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)); + } - // 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(base, (float)column_max_y); - // Only decrease above water_level - if (t_alt > water_level) - m_bgen->heatmap[index_2d] -= - (t_alt - water_level) * 20.0f / - altitude_chill; - } + // Optionally decrease humidity with altitude + if (spflags & MGVALLEYS_ALT_DRY) { + // Ground height ignoring riverbeds + 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] -= + (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(base, (float)column_max_y); + // Only decrease above water_level + if (t_alt > water_level) + m_bgen->heatmap[index_2d] -= + (t_alt - water_level) * 20.0f / altitude_chill; + } + } + return surface_max_y; } diff --git a/src/mapgen/mapgen_valleys.h b/src/mapgen/mapgen_valleys.h index fb544e51b..34a923dfa 100644 --- a/src/mapgen/mapgen_valleys.h +++ b/src/mapgen/mapgen_valleys.h @@ -24,22 +24,23 @@ 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" -#define MGVALLEYS_ALT_CHILL 0x01 -#define MGVALLEYS_HUMID_RIVERS 0x02 +#define MGVALLEYS_ALT_CHILL 0x01 +#define MGVALLEYS_HUMID_RIVERS 0x02 #define MGVALLEYS_VARY_RIVER_DEPTH 0x04 -#define MGVALLEYS_ALT_DRY 0x08 +#define MGVALLEYS_ALT_DRY 0x08 class BiomeManager; class BiomeGenOriginal; extern FlagDesc flagdesc_mapgen_valleys[]; -struct MapgenValleysParams : public MapgenParams -{ + +struct MapgenValleysParams : public MapgenParams { u16 altitude_chill = 90; u16 river_depth = 4; u16 river_size = 5; @@ -78,10 +79,12 @@ struct MapgenValleysParams : public MapgenParams void setDefaultSettings(Settings *settings); }; -class MapgenValleys : public MapgenBasic -{ + +class MapgenValleys : public MapgenBasic { public: - MapgenValleys(MapgenValleysParams *params, EmergeParams *emerge); + + MapgenValleys(MapgenValleysParams *params, + EmergeParams *emerge); ~MapgenValleys(); virtual MapgenType getType() const { return MAPGEN_VALLEYS; } diff --git a/src/mapgen/mg_biome.cpp b/src/mapgen/mg_biome.cpp index ea7c24721..610c38594 100644 --- a/src/mapgen/mg_biome.cpp +++ b/src/mapgen/mg_biome.cpp @@ -28,28 +28,31 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "porting.h" #include "settings.h" + /////////////////////////////////////////////////////////////////////////////// -BiomeManager::BiomeManager(Server *server) : ObjDefManager(server, OBJDEF_BIOME) + +BiomeManager::BiomeManager(Server *server) : + ObjDefManager(server, OBJDEF_BIOME) { m_server = server; // Create default biome to be used in case none exist Biome *b = new Biome; - b->name = "default"; - b->flags = 0; - b->depth_top = 0; - b->depth_filler = -MAX_MAP_GENERATION_LIMIT; + b->name = "default"; + b->flags = 0; + b->depth_top = 0; + b->depth_filler = -MAX_MAP_GENERATION_LIMIT; b->depth_water_top = 0; - b->depth_riverbed = 0; - b->min_pos = v3s16(-MAX_MAP_GENERATION_LIMIT, -MAX_MAP_GENERATION_LIMIT, - -MAX_MAP_GENERATION_LIMIT); - b->max_pos = v3s16(MAX_MAP_GENERATION_LIMIT, MAX_MAP_GENERATION_LIMIT, - MAX_MAP_GENERATION_LIMIT); - b->heat_point = 0.0; - b->humidity_point = 0.0; - b->vertical_blend = 0; + b->depth_riverbed = 0; + b->min_pos = v3s16(-MAX_MAP_GENERATION_LIMIT, + -MAX_MAP_GENERATION_LIMIT, -MAX_MAP_GENERATION_LIMIT); + b->max_pos = v3s16(MAX_MAP_GENERATION_LIMIT, + MAX_MAP_GENERATION_LIMIT, MAX_MAP_GENERATION_LIMIT); + b->heat_point = 0.0; + b->humidity_point = 0.0; + b->vertical_blend = 0; b->m_nodenames.emplace_back("mapgen_stone"); b->m_nodenames.emplace_back("mapgen_stone"); @@ -69,6 +72,7 @@ BiomeManager::BiomeManager(Server *server) : ObjDefManager(server, OBJDEF_BIOME) add(b); } + void BiomeManager::clear() { EmergeManager *emerge = m_server->getEmergeManager(); @@ -87,6 +91,7 @@ void BiomeManager::clear() m_objects.resize(1); } + BiomeManager *BiomeManager::clone() const { auto mgr = new BiomeManager(); @@ -96,25 +101,30 @@ BiomeManager *BiomeManager::clone() const return mgr; } + // For BiomeGen type 'BiomeGenOriginal' float BiomeManager::getHeatAtPosOriginal(v3s16 pos, NoiseParams &np_heat, - NoiseParams &np_heat_blend, u64 seed) const + NoiseParams &np_heat_blend, u64 seed) const { - return NoisePerlin2D(&np_heat, pos.X, pos.Z, seed) + - NoisePerlin2D(&np_heat_blend, pos.X, pos.Z, seed); + return + NoisePerlin2D(&np_heat, pos.X, pos.Z, seed) + + NoisePerlin2D(&np_heat_blend, pos.X, pos.Z, seed); } + // For BiomeGen type 'BiomeGenOriginal' float BiomeManager::getHumidityAtPosOriginal(v3s16 pos, NoiseParams &np_humidity, - NoiseParams &np_humidity_blend, u64 seed) const + NoiseParams &np_humidity_blend, u64 seed) const { - return NoisePerlin2D(&np_humidity, pos.X, pos.Z, seed) + - NoisePerlin2D(&np_humidity_blend, pos.X, pos.Z, seed); + return + NoisePerlin2D(&np_humidity, pos.X, pos.Z, seed) + + NoisePerlin2D(&np_humidity_blend, pos.X, pos.Z, seed); } + // For BiomeGen type 'BiomeGenOriginal' -const Biome *BiomeManager::getBiomeFromNoiseOriginal( - float heat, float humidity, v3s16 pos) const +const Biome *BiomeManager::getBiomeFromNoiseOriginal(float heat, + float humidity, v3s16 pos) const { Biome *biome_closest = nullptr; Biome *biome_closest_blend = nullptr; @@ -123,8 +133,8 @@ const Biome *BiomeManager::getBiomeFromNoiseOriginal( for (size_t i = 1; i < getNumObjects(); i++) { Biome *b = (Biome *)getRaw(i); - if (!b || pos.Y < b->min_pos.Y || - pos.Y > b->max_pos.Y + b->vertical_blend || + if (!b || + pos.Y < b->min_pos.Y || pos.Y > b->max_pos.Y + b->vertical_blend || pos.X < b->min_pos.X || pos.X > b->max_pos.X || pos.Z < b->min_pos.Z || pos.Z > b->max_pos.Z) continue; @@ -149,48 +159,52 @@ const Biome *BiomeManager::getBiomeFromNoiseOriginal( if (biome_closest_blend && dist_min_blend <= dist_min && rng.range(0, biome_closest_blend->vertical_blend) >= - pos.Y - biome_closest_blend->max_pos.Y) + pos.Y - biome_closest_blend->max_pos.Y) return biome_closest_blend; return (biome_closest) ? biome_closest : (Biome *)getRaw(BIOME_NONE); } + //////////////////////////////////////////////////////////////////////////////// void BiomeParamsOriginal::readParams(const Settings *settings) { - settings->getNoiseParams("mg_biome_np_heat", np_heat); - settings->getNoiseParams("mg_biome_np_heat_blend", np_heat_blend); - settings->getNoiseParams("mg_biome_np_humidity", np_humidity); + settings->getNoiseParams("mg_biome_np_heat", np_heat); + settings->getNoiseParams("mg_biome_np_heat_blend", np_heat_blend); + settings->getNoiseParams("mg_biome_np_humidity", np_humidity); settings->getNoiseParams("mg_biome_np_humidity_blend", np_humidity_blend); } + void BiomeParamsOriginal::writeParams(Settings *settings) const { - settings->setNoiseParams("mg_biome_np_heat", np_heat); - settings->setNoiseParams("mg_biome_np_heat_blend", np_heat_blend); - settings->setNoiseParams("mg_biome_np_humidity", np_humidity); + settings->setNoiseParams("mg_biome_np_heat", np_heat); + settings->setNoiseParams("mg_biome_np_heat_blend", np_heat_blend); + settings->setNoiseParams("mg_biome_np_humidity", np_humidity); settings->setNoiseParams("mg_biome_np_humidity_blend", np_humidity_blend); } + //////////////////////////////////////////////////////////////////////////////// -BiomeGenOriginal::BiomeGenOriginal( - BiomeManager *biomemgr, BiomeParamsOriginal *params, v3s16 chunksize) +BiomeGenOriginal::BiomeGenOriginal(BiomeManager *biomemgr, + BiomeParamsOriginal *params, v3s16 chunksize) { - m_bmgr = biomemgr; + m_bmgr = biomemgr; m_params = params; - m_csize = chunksize; - - noise_heat = new Noise(¶ms->np_heat, params->seed, m_csize.X, m_csize.Z); - noise_humidity = new Noise( - ¶ms->np_humidity, params->seed, m_csize.X, m_csize.Z); - noise_heat_blend = new Noise( - ¶ms->np_heat_blend, params->seed, m_csize.X, m_csize.Z); - noise_humidity_blend = new Noise( - ¶ms->np_humidity_blend, params->seed, m_csize.X, m_csize.Z); - - heatmap = noise_heat->result; + m_csize = chunksize; + + noise_heat = new Noise(¶ms->np_heat, + params->seed, m_csize.X, m_csize.Z); + noise_humidity = new Noise(¶ms->np_humidity, + params->seed, m_csize.X, m_csize.Z); + noise_heat_blend = new Noise(¶ms->np_heat_blend, + params->seed, m_csize.X, m_csize.Z); + noise_humidity_blend = new Noise(¶ms->np_humidity_blend, + params->seed, m_csize.X, m_csize.Z); + + heatmap = noise_heat->result; humidmap = noise_humidity->result; biomemap = new biome_t[m_csize.X * m_csize.Z]; @@ -202,7 +216,7 @@ BiomeGenOriginal::BiomeGenOriginal( BiomeGenOriginal::~BiomeGenOriginal() { - delete[] biomemap; + delete []biomemap; delete noise_heat; delete noise_humidity; @@ -213,17 +227,17 @@ BiomeGenOriginal::~BiomeGenOriginal() // Only usable in a mapgen thread Biome *BiomeGenOriginal::calcBiomeAtPoint(v3s16 pos) const { - float heat = NoisePerlin2D(&m_params->np_heat, pos.X, pos.Z, m_params->seed) + - NoisePerlin2D(&m_params->np_heat_blend, pos.X, pos.Z, - m_params->seed); - float humidity = NoisePerlin2D(&m_params->np_humidity, pos.X, pos.Z, - m_params->seed) + - NoisePerlin2D(&m_params->np_humidity_blend, pos.X, pos.Z, - m_params->seed); + float heat = + NoisePerlin2D(&m_params->np_heat, pos.X, pos.Z, m_params->seed) + + NoisePerlin2D(&m_params->np_heat_blend, pos.X, pos.Z, m_params->seed); + float humidity = + NoisePerlin2D(&m_params->np_humidity, pos.X, pos.Z, m_params->seed) + + NoisePerlin2D(&m_params->np_humidity_blend, pos.X, pos.Z, m_params->seed); return calcBiomeFromNoise(heat, humidity, pos); } + void BiomeGenOriginal::calcBiomeNoise(v3s16 pmin) { m_pmin = pmin; @@ -234,37 +248,46 @@ void BiomeGenOriginal::calcBiomeNoise(v3s16 pmin) noise_humidity_blend->perlinMap2D(pmin.X, pmin.Z); for (s32 i = 0; i < m_csize.X * m_csize.Z; i++) { - noise_heat->result[i] += noise_heat_blend->result[i]; + noise_heat->result[i] += noise_heat_blend->result[i]; noise_humidity->result[i] += noise_humidity_blend->result[i]; } } + biome_t *BiomeGenOriginal::getBiomes(s16 *heightmap, v3s16 pmin) { for (s16 zr = 0; zr < m_csize.Z; zr++) - for (s16 xr = 0; xr < m_csize.X; xr++) { - s32 i = zr * m_csize.X + xr; - Biome *biome = calcBiomeFromNoise(noise_heat->result[i], - noise_humidity->result[i], - v3s16(pmin.X + xr, heightmap[i], pmin.Z + zr)); - - biomemap[i] = biome->index; - } + for (s16 xr = 0; xr < m_csize.X; xr++) { + s32 i = zr * m_csize.X + xr; + Biome *biome = calcBiomeFromNoise( + noise_heat->result[i], + noise_humidity->result[i], + v3s16(pmin.X + xr, heightmap[i], pmin.Z + zr)); + + biomemap[i] = biome->index; + } return biomemap; } + Biome *BiomeGenOriginal::getBiomeAtPoint(v3s16 pos) const { - return getBiomeAtIndex((pos.Z - m_pmin.Z) * m_csize.X + (pos.X - m_pmin.X), pos); + return getBiomeAtIndex( + (pos.Z - m_pmin.Z) * m_csize.X + (pos.X - m_pmin.X), + pos); } + Biome *BiomeGenOriginal::getBiomeAtIndex(size_t index, v3s16 pos) const { return calcBiomeFromNoise( - noise_heat->result[index], noise_humidity->result[index], pos); + noise_heat->result[index], + noise_humidity->result[index], + pos); } + Biome *BiomeGenOriginal::calcBiomeFromNoise(float heat, float humidity, v3s16 pos) const { Biome *biome_closest = nullptr; @@ -274,8 +297,8 @@ Biome *BiomeGenOriginal::calcBiomeFromNoise(float heat, float humidity, v3s16 po for (size_t i = 1; i < m_bmgr->getNumObjects(); i++) { Biome *b = (Biome *)m_bmgr->getRaw(i); - if (!b || pos.Y < b->min_pos.Y || - pos.Y > b->max_pos.Y + b->vertical_blend || + if (!b || + pos.Y < b->min_pos.Y || pos.Y > b->max_pos.Y + b->vertical_blend || pos.X < b->min_pos.X || pos.X > b->max_pos.X || pos.Z < b->min_pos.Z || pos.Z > b->max_pos.Z) continue; @@ -303,12 +326,13 @@ Biome *BiomeGenOriginal::calcBiomeFromNoise(float heat, float humidity, v3s16 po if (biome_closest_blend && dist_min_blend <= dist_min && rng.range(0, biome_closest_blend->vertical_blend) >= - pos.Y - biome_closest_blend->max_pos.Y) + pos.Y - biome_closest_blend->max_pos.Y) return biome_closest_blend; - return (biome_closest) ? biome_closest : (Biome *)m_bmgr->getRaw(BIOME_NONE); + return (biome_closest) ? biome_closest : (Biome *)m_bmgr->getRaw(BIOME_NONE); } + //////////////////////////////////////////////////////////////////////////////// ObjDef *Biome::clone() const @@ -348,17 +372,16 @@ ObjDef *Biome::clone() const void Biome::resolveNodeNames() { - getIdFromNrBacklog(&c_top, "mapgen_stone", CONTENT_AIR, false); - getIdFromNrBacklog(&c_filler, "mapgen_stone", CONTENT_AIR, false); - getIdFromNrBacklog(&c_stone, "mapgen_stone", CONTENT_AIR, false); - getIdFromNrBacklog(&c_water_top, "mapgen_water_source", CONTENT_AIR, false); - getIdFromNrBacklog(&c_water, "mapgen_water_source", CONTENT_AIR, false); - 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_top, "mapgen_stone", CONTENT_AIR, false); + getIdFromNrBacklog(&c_filler, "mapgen_stone", CONTENT_AIR, false); + getIdFromNrBacklog(&c_stone, "mapgen_stone", CONTENT_AIR, false); + getIdFromNrBacklog(&c_water_top, "mapgen_water_source", CONTENT_AIR, false); + getIdFromNrBacklog(&c_water, "mapgen_water_source", CONTENT_AIR, false); + 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); 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); + 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 ba3319976..be4cfea4d 100644 --- a/src/mapgen/mg_biome.h +++ b/src/mapgen/mg_biome.h @@ -36,13 +36,11 @@ typedef u16 biome_t; #define BIOME_NONE ((biome_t)0) -enum BiomeType -{ +enum BiomeType { BIOMETYPE_NORMAL, }; -class Biome : public ObjDef, public NodeResolver -{ +class Biome : public ObjDef, public NodeResolver { public: ObjDef *clone() const; @@ -75,17 +73,16 @@ public: virtual void resolveNodeNames(); }; + //// //// BiomeGen //// -enum BiomeGenType -{ +enum BiomeGenType { BIOMEGEN_ORIGINAL, }; -struct BiomeParams -{ +struct BiomeParams { virtual void readParams(const Settings *settings) = 0; virtual void writeParams(Settings *settings) const = 0; virtual ~BiomeParams() = default; @@ -94,8 +91,7 @@ struct BiomeParams }; // WARNING: this class is not thread-safe -class BiomeGen -{ +class BiomeGen { public: virtual ~BiomeGen() = default; @@ -132,6 +128,7 @@ protected: v3s16 m_csize; }; + //// //// BiomeGen implementations //// @@ -140,14 +137,12 @@ protected: // Original biome algorithm (Whittaker's classification + surface height) // -struct BiomeParamsOriginal : public BiomeParams -{ +struct BiomeParamsOriginal : public BiomeParams { BiomeParamsOriginal() : - np_heat(50, 50, v3f(1000.0, 1000.0, 1000.0), 5349, 3, 0.5, 2.0), - np_humidity(50, 50, v3f(1000.0, 1000.0, 1000.0), 842, 3, 0.5, - 2.0), - np_heat_blend(0, 1.5, v3f(8.0, 8.0, 8.0), 13, 2, 1.0, 2.0), - np_humidity_blend(0, 1.5, v3f(8.0, 8.0, 8.0), 90003, 2, 1.0, 2.0) + np_heat(50, 50, v3f(1000.0, 1000.0, 1000.0), 5349, 3, 0.5, 2.0), + np_humidity(50, 50, v3f(1000.0, 1000.0, 1000.0), 842, 3, 0.5, 2.0), + np_heat_blend(0, 1.5, v3f(8.0, 8.0, 8.0), 13, 2, 1.0, 2.0), + np_humidity_blend(0, 1.5, v3f(8.0, 8.0, 8.0), 90003, 2, 1.0, 2.0) { } @@ -160,11 +155,10 @@ struct BiomeParamsOriginal : public BiomeParams NoiseParams np_humidity_blend; }; -class BiomeGenOriginal : public BiomeGen -{ +class BiomeGenOriginal : public BiomeGen { public: - BiomeGenOriginal(BiomeManager *biomemgr, BiomeParamsOriginal *params, - v3s16 chunksize); + BiomeGenOriginal(BiomeManager *biomemgr, + BiomeParamsOriginal *params, v3s16 chunksize); virtual ~BiomeGenOriginal(); BiomeGenType getType() const { return BIOMEGEN_ORIGINAL; } @@ -190,28 +184,34 @@ private: Noise *noise_humidity_blend; }; + //// //// BiomeManager //// -class BiomeManager : public ObjDefManager -{ +class BiomeManager : public ObjDefManager { public: BiomeManager(Server *server); virtual ~BiomeManager() = default; BiomeManager *clone() const; - const char *getObjectTitle() const { return "biome"; } + const char *getObjectTitle() const + { + return "biome"; + } - static Biome *create(BiomeType type) { return new Biome; } + static Biome *create(BiomeType type) + { + return new Biome; + } BiomeGen *createBiomeGen(BiomeGenType type, BiomeParams *params, v3s16 chunksize) { switch (type) { case BIOMEGEN_ORIGINAL: - return new BiomeGenOriginal( - this, (BiomeParamsOriginal *)params, chunksize); + return new BiomeGenOriginal(this, + (BiomeParamsOriginal *)params, chunksize); default: return NULL; } @@ -231,14 +231,15 @@ public: // For BiomeGen type 'BiomeGenOriginal' float getHeatAtPosOriginal(v3s16 pos, NoiseParams &np_heat, - NoiseParams &np_heat_blend, u64 seed) const; + NoiseParams &np_heat_blend, u64 seed) const; float getHumidityAtPosOriginal(v3s16 pos, NoiseParams &np_humidity, - NoiseParams &np_humidity_blend, u64 seed) const; - const Biome *getBiomeFromNoiseOriginal( - float heat, float humidity, v3s16 pos) const; + NoiseParams &np_humidity_blend, u64 seed) const; + const Biome *getBiomeFromNoiseOriginal(float heat, float humidity, + v3s16 pos) const; private: - BiomeManager(){}; + BiomeManager() {}; Server *m_server; + }; diff --git a/src/mapgen/mg_decoration.cpp b/src/mapgen/mg_decoration.cpp index 6aa003a3f..a4cada396 100644 --- a/src/mapgen/mg_decoration.cpp +++ b/src/mapgen/mg_decoration.cpp @@ -28,21 +28,30 @@ with this program; if not, write to the Free Software Foundation, Inc., #include <algorithm> #include <vector> -FlagDesc flagdesc_deco[] = {{"place_center_x", DECO_PLACE_CENTER_X}, - {"place_center_y", DECO_PLACE_CENTER_Y}, - {"place_center_z", DECO_PLACE_CENTER_Z}, - {"force_placement", DECO_FORCE_PLACEMENT}, - {"liquid_surface", DECO_LIQUID_SURFACE}, {"all_floors", DECO_ALL_FLOORS}, - {"all_ceilings", DECO_ALL_CEILINGS}, {NULL, 0}}; + +FlagDesc flagdesc_deco[] = { + {"place_center_x", DECO_PLACE_CENTER_X}, + {"place_center_y", DECO_PLACE_CENTER_Y}, + {"place_center_z", DECO_PLACE_CENTER_Z}, + {"force_placement", DECO_FORCE_PLACEMENT}, + {"liquid_surface", DECO_LIQUID_SURFACE}, + {"all_floors", DECO_ALL_FLOORS}, + {"all_ceilings", DECO_ALL_CEILINGS}, + {NULL, 0} +}; + /////////////////////////////////////////////////////////////////////////////// + DecorationManager::DecorationManager(IGameDef *gamedef) : - ObjDefManager(gamedef, OBJDEF_DECORATION) + ObjDefManager(gamedef, OBJDEF_DECORATION) { } -size_t DecorationManager::placeAllDecos(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) + +size_t DecorationManager::placeAllDecos(Mapgen *mg, u32 blockseed, + v3s16 nmin, v3s16 nmax) { size_t nplaced = 0; @@ -65,14 +74,17 @@ DecorationManager *DecorationManager::clone() const return mgr; } + /////////////////////////////////////////////////////////////////////////////// + void Decoration::resolveNodeNames() { getIdsFromNrBacklog(&c_place_on); getIdsFromNrBacklog(&c_spawnby); } + bool Decoration::canPlaceDecoration(MMVManip *vm, v3s16 p) { // Check if the decoration can be placed on this node @@ -85,13 +97,25 @@ bool Decoration::canPlaceDecoration(MMVManip *vm, v3s16 p) return true; int nneighs = 0; - static const v3s16 dirs[16] = {v3s16(0, 0, 1), v3s16(0, 0, -1), v3s16(1, 0, 0), - v3s16(-1, 0, 0), v3s16(1, 0, 1), v3s16(-1, 0, 1), - v3s16(-1, 0, -1), v3s16(1, 0, -1), - - v3s16(0, 1, 1), v3s16(0, 1, -1), v3s16(1, 1, 0), v3s16(-1, 1, 0), - v3s16(1, 1, 1), v3s16(-1, 1, 1), v3s16(-1, 1, -1), - v3s16(1, 1, -1)}; + static const v3s16 dirs[16] = { + v3s16( 0, 0, 1), + v3s16( 0, 0, -1), + v3s16( 1, 0, 0), + v3s16(-1, 0, 0), + v3s16( 1, 0, 1), + v3s16(-1, 0, 1), + v3s16(-1, 0, -1), + v3s16( 1, 0, -1), + + v3s16( 0, 1, 1), + v3s16( 0, 1, -1), + v3s16( 1, 1, 0), + v3s16(-1, 1, 0), + v3s16( 1, 1, 1), + v3s16(-1, 1, 1), + v3s16(-1, 1, -1), + v3s16( 1, 1, -1) + }; // Check these 16 neighbouring nodes for enough spawnby nodes for (size_t i = 0; i != ARRLEN(dirs); i++) { @@ -109,6 +133,7 @@ bool Decoration::canPlaceDecoration(MMVManip *vm, v3s16 p) return true; } + size_t Decoration::placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) { PcgRandom ps(blockseed + 53); @@ -123,144 +148,132 @@ size_t Decoration::placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) int area = sidelen * sidelen; for (s16 z0 = 0; z0 < divlen; z0++) - for (s16 x0 = 0; x0 < divlen; x0++) { - v2s16 p2d_center( // Center position of part of division - nmin.X + sidelen / 2 + sidelen * x0, - nmin.Z + sidelen / 2 + sidelen * z0); - v2s16 p2d_min( // Minimum edge of part of division - nmin.X + sidelen * x0, nmin.Z + sidelen * z0); - v2s16 p2d_max( // Maximum edge of part of division - nmin.X + sidelen + sidelen * x0 - 1, - nmin.Z + sidelen + sidelen * z0 - 1); - - bool cover = false; - // Amount of decorations - float nval = (flags & DECO_USE_NOISE) - ? NoisePerlin2D(&np, p2d_center.X, - p2d_center.Y, - mapseed) - : fill_ratio; - u32 deco_count = 0; - - if (nval >= 10.0f) { - // Complete coverage. Disable random placement to avoid - // redundant multiple placements at one position. - cover = true; - deco_count = area; + for (s16 x0 = 0; x0 < divlen; x0++) { + v2s16 p2d_center( // Center position of part of division + nmin.X + sidelen / 2 + sidelen * x0, + nmin.Z + sidelen / 2 + sidelen * z0 + ); + v2s16 p2d_min( // Minimum edge of part of division + nmin.X + sidelen * x0, + nmin.Z + sidelen * z0 + ); + v2s16 p2d_max( // Maximum edge of part of division + nmin.X + sidelen + sidelen * x0 - 1, + nmin.Z + sidelen + sidelen * z0 - 1 + ); + + bool cover = false; + // Amount of decorations + float nval = (flags & DECO_USE_NOISE) ? + NoisePerlin2D(&np, p2d_center.X, p2d_center.Y, mapseed) : + fill_ratio; + u32 deco_count = 0; + + if (nval >= 10.0f) { + // Complete coverage. Disable random placement to avoid + // redundant multiple placements at one position. + cover = true; + deco_count = area; + } else { + float deco_count_f = (float)area * nval; + if (deco_count_f >= 1.0f) { + deco_count = deco_count_f; + } else if (deco_count_f > 0.0f) { + // For very low density calculate a chance for 1 decoration + if (ps.range(1000) <= deco_count_f * 1000.0f) + deco_count = 1; + } + } + + s16 x = p2d_min.X - 1; + s16 z = p2d_min.Y; + + for (u32 i = 0; i < deco_count; i++) { + if (!cover) { + x = ps.range(p2d_min.X, p2d_max.X); + z = ps.range(p2d_min.Y, p2d_max.Y); } else { - float deco_count_f = (float)area * nval; - if (deco_count_f >= 1.0f) { - deco_count = deco_count_f; - } else if (deco_count_f > 0.0f) { - // For very low density calculate a chance for 1 - // decoration - if (ps.range(1000) <= deco_count_f * 1000.0f) - deco_count = 1; + x++; + if (x == p2d_max.X + 1) { + z++; + x = p2d_min.X; } } - - s16 x = p2d_min.X - 1; - s16 z = p2d_min.Y; - - for (u32 i = 0; i < deco_count; i++) { - if (!cover) { - x = ps.range(p2d_min.X, p2d_max.X); - z = ps.range(p2d_min.Y, p2d_max.Y); - } else { - x++; - if (x == p2d_max.X + 1) { - z++; - x = p2d_min.X; - } + int mapindex = carea_size * (z - nmin.Z) + (x - nmin.X); + + if ((flags & DECO_ALL_FLOORS) || + (flags & DECO_ALL_CEILINGS)) { + // All-surfaces decorations + // Check biome of column + if (mg->biomemap && !biomes.empty()) { + auto iter = biomes.find(mg->biomemap[mapindex]); + if (iter == biomes.end()) + continue; } - int mapindex = carea_size * (z - nmin.Z) + (x - nmin.X); - - if ((flags & DECO_ALL_FLOORS) || - (flags & DECO_ALL_CEILINGS)) { - // All-surfaces decorations - // Check biome of column - if (mg->biomemap && !biomes.empty()) { - auto iter = biomes.find( - mg->biomemap[mapindex]); - if (iter == biomes.end()) - continue; - } - // Get all floors and ceilings in node column - u16 size = (nmax.Y - nmin.Y + 1) / 2; - std::vector<s16> floors; - std::vector<s16> ceilings; - floors.reserve(size); - ceilings.reserve(size); - - mg->getSurfaces(v2s16(x, z), nmin.Y, nmax.Y, - floors, ceilings); - - if (flags & DECO_ALL_FLOORS) { - // Floor decorations - for (const s16 y : floors) { - if (y < y_min || y > y_max) - continue; - - v3s16 pos(x, y, z); - if (generate(mg->vm, &ps, pos, - false)) - mg->gennotify.addEvent( - GENNOTIFY_DECORATION, - pos, - index); - } - } + // Get all floors and ceilings in node column + u16 size = (nmax.Y - nmin.Y + 1) / 2; + std::vector<s16> floors; + std::vector<s16> ceilings; + floors.reserve(size); + ceilings.reserve(size); - if (flags & DECO_ALL_CEILINGS) { - // Ceiling decorations - for (const s16 y : ceilings) { - if (y < y_min || y > y_max) - continue; - - v3s16 pos(x, y, z); - if (generate(mg->vm, &ps, pos, - true)) - mg->gennotify.addEvent( - GENNOTIFY_DECORATION, - pos, - index); - } - } - } else { // Heightmap decorations - s16 y = -MAX_MAP_GENERATION_LIMIT; - if (flags & DECO_LIQUID_SURFACE) - y = mg->findLiquidSurface(v2s16(x, z), - nmin.Y, nmax.Y); - else if (mg->heightmap) - y = mg->heightmap[mapindex]; - else - y = mg->findGroundLevel(v2s16(x, z), - nmin.Y, nmax.Y); - - if (y < y_min || y > y_max || y < nmin.Y || - y > nmax.Y) - continue; + mg->getSurfaces(v2s16(x, z), nmin.Y, nmax.Y, floors, ceilings); - if (mg->biomemap && !biomes.empty()) { - auto iter = biomes.find( - mg->biomemap[mapindex]); - if (iter == biomes.end()) + if (flags & DECO_ALL_FLOORS) { + // Floor decorations + for (const s16 y : floors) { + if (y < y_min || y > y_max) continue; + + v3s16 pos(x, y, z); + if (generate(mg->vm, &ps, pos, false)) + mg->gennotify.addEvent( + GENNOTIFY_DECORATION, pos, index); } + } + + if (flags & DECO_ALL_CEILINGS) { + // Ceiling decorations + for (const s16 y : ceilings) { + if (y < y_min || y > y_max) + continue; - v3s16 pos(x, y, z); - if (generate(mg->vm, &ps, pos, false)) - mg->gennotify.addEvent( - GENNOTIFY_DECORATION, pos, - index); + v3s16 pos(x, y, z); + if (generate(mg->vm, &ps, pos, true)) + mg->gennotify.addEvent( + GENNOTIFY_DECORATION, pos, index); + } + } + } else { // Heightmap decorations + s16 y = -MAX_MAP_GENERATION_LIMIT; + if (flags & DECO_LIQUID_SURFACE) + y = mg->findLiquidSurface(v2s16(x, z), nmin.Y, nmax.Y); + else if (mg->heightmap) + y = mg->heightmap[mapindex]; + else + y = mg->findGroundLevel(v2s16(x, z), nmin.Y, nmax.Y); + + if (y < y_min || y > y_max || y < nmin.Y || y > nmax.Y) + continue; + + if (mg->biomemap && !biomes.empty()) { + auto iter = biomes.find(mg->biomemap[mapindex]); + if (iter == biomes.end()) + continue; } + + v3s16 pos(x, y, z); + if (generate(mg->vm, &ps, pos, false)) + mg->gennotify.addEvent(GENNOTIFY_DECORATION, pos, index); } } + } return 0; } + void Decoration::cloneTo(Decoration *def) const { ObjDef::cloneTo(def); @@ -278,8 +291,10 @@ void Decoration::cloneTo(Decoration *def) const def->biomes = biomes; } + /////////////////////////////////////////////////////////////////////////////// + ObjDef *DecoSimple::clone() const { auto def = new DecoSimple(); @@ -294,12 +309,14 @@ ObjDef *DecoSimple::clone() const return def; } + void DecoSimple::resolveNodeNames() { Decoration::resolveNodeNames(); getIdsFromNrBacklog(&c_decos); } + size_t DecoSimple::generate(MMVManip *vm, PcgRandom *pr, v3s16 p, bool ceiling) { // Don't bother if there aren't any decorations to place @@ -330,10 +347,10 @@ size_t DecoSimple::generate(MMVManip *vm, PcgRandom *pr, v3s16 p, bool ceiling) } content_t c_place = c_decos[pr->range(0, c_decos.size() - 1)]; - s16 height = (deco_height_max > 0) ? pr->range(deco_height, deco_height_max) - : deco_height; - u8 param2 = (deco_param2_max > 0) ? pr->range(deco_param2, deco_param2_max) - : deco_param2; + s16 height = (deco_height_max > 0) ? + pr->range(deco_height, deco_height_max) : deco_height; + u8 param2 = (deco_param2_max > 0) ? + pr->range(deco_param2, deco_param2_max) : deco_param2; bool force_placement = (flags & DECO_FORCE_PLACEMENT); const v3s16 &em = vm->m_area.getExtent(); @@ -368,14 +385,17 @@ size_t DecoSimple::generate(MMVManip *vm, PcgRandom *pr, v3s16 p, bool ceiling) return 1; } + /////////////////////////////////////////////////////////////////////////////// + DecoSchematic::~DecoSchematic() { if (was_cloned) delete schematic; } + ObjDef *DecoSchematic::clone() const { auto def = new DecoSchematic(); @@ -387,12 +407,13 @@ ObjDef *DecoSchematic::clone() const * and not a handle. We are left with no option but to clone it ourselves. * This is a waste of memory and should be replaced with an alternative * approach sometime. */ - def->schematic = dynamic_cast<Schematic *>(schematic->clone()); + def->schematic = dynamic_cast<Schematic*>(schematic->clone()); def->was_cloned = true; return def; } + size_t DecoSchematic::generate(MMVManip *vm, PcgRandom *pr, v3s16 p, bool ceiling) { // Schematic could have been unloaded but not the decoration @@ -422,9 +443,8 @@ size_t DecoSchematic::generate(MMVManip *vm, PcgRandom *pr, v3s16 p, bool ceilin if (p.Y < vm->m_area.MinEdge.Y) return 0; - Rotation rot = (rotation == ROTATE_RAND) - ? (Rotation)pr->range(ROTATE_0, ROTATE_270) - : rotation; + Rotation rot = (rotation == ROTATE_RAND) ? + (Rotation)pr->range(ROTATE_0, ROTATE_270) : rotation; if (flags & DECO_PLACE_CENTER_X) { if (rot == ROTATE_0 || rot == ROTATE_180) diff --git a/src/mapgen/mg_decoration.h b/src/mapgen/mg_decoration.h index c0cd4af9f..1ea02a527 100644 --- a/src/mapgen/mg_decoration.h +++ b/src/mapgen/mg_decoration.h @@ -25,33 +25,32 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "noise.h" #include "nodedef.h" -typedef u16 biome_t; // copy from mg_biome.h to avoid an unnecessary include +typedef u16 biome_t; // copy from mg_biome.h to avoid an unnecessary include class Mapgen; class MMVManip; class PcgRandom; class Schematic; -enum DecorationType -{ +enum DecorationType { DECO_SIMPLE, DECO_SCHEMATIC, DECO_LSYSTEM }; -#define DECO_PLACE_CENTER_X 0x01 -#define DECO_PLACE_CENTER_Y 0x02 -#define DECO_PLACE_CENTER_Z 0x04 -#define DECO_USE_NOISE 0x08 +#define DECO_PLACE_CENTER_X 0x01 +#define DECO_PLACE_CENTER_Y 0x02 +#define DECO_PLACE_CENTER_Z 0x04 +#define DECO_USE_NOISE 0x08 #define DECO_FORCE_PLACEMENT 0x10 -#define DECO_LIQUID_SURFACE 0x20 -#define DECO_ALL_FLOORS 0x40 -#define DECO_ALL_CEILINGS 0x80 +#define DECO_LIQUID_SURFACE 0x20 +#define DECO_ALL_FLOORS 0x40 +#define DECO_ALL_CEILINGS 0x80 extern FlagDesc flagdesc_deco[]; -class Decoration : public ObjDef, public NodeResolver -{ + +class Decoration : public ObjDef, public NodeResolver { public: Decoration() = default; virtual ~Decoration() = default; @@ -81,8 +80,8 @@ protected: void cloneTo(Decoration *def) const; }; -class DecoSimple : public Decoration -{ + +class DecoSimple : public Decoration { public: ObjDef *clone() const; @@ -96,8 +95,8 @@ public: u8 deco_param2_max; }; -class DecoSchematic : public Decoration -{ + +class DecoSchematic : public Decoration { public: ObjDef *clone() const; @@ -111,6 +110,7 @@ public: bool was_cloned = false; // see FIXME inside DecoSchemtic::clone() }; + /* class DecoLSystem : public Decoration { public: @@ -118,15 +118,18 @@ public: }; */ -class DecorationManager : public ObjDefManager -{ + +class DecorationManager : public ObjDefManager { public: DecorationManager(IGameDef *gamedef); virtual ~DecorationManager() = default; DecorationManager *clone() const; - const char *getObjectTitle() const { return "decoration"; } + const char *getObjectTitle() const + { + return "decoration"; + } static Decoration *create(DecorationType type) { @@ -135,7 +138,7 @@ public: return new DecoSimple; case DECO_SCHEMATIC: return new DecoSchematic; - // case DECO_LSYSTEM: + //case DECO_LSYSTEM: // return new DecoLSystem; default: return NULL; @@ -145,5 +148,5 @@ public: size_t placeAllDecos(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax); private: - DecorationManager(){}; + DecorationManager() {}; }; diff --git a/src/mapgen/mg_ore.cpp b/src/mapgen/mg_ore.cpp index 5af8e31e4..b50ed6a32 100644 --- a/src/mapgen/mg_ore.cpp +++ b/src/mapgen/mg_ore.cpp @@ -27,16 +27,24 @@ with this program; if not, write to the Free Software Foundation, Inc., #include <cmath> #include <algorithm> -FlagDesc flagdesc_ore[] = {{"absheight", OREFLAG_ABSHEIGHT}, // Non-functional - {"puff_cliffs", OREFLAG_PUFF_CLIFFS}, - {"puff_additive_composition", OREFLAG_PUFF_ADDITIVE}, {NULL, 0}}; + +FlagDesc flagdesc_ore[] = { + {"absheight", OREFLAG_ABSHEIGHT}, // Non-functional + {"puff_cliffs", OREFLAG_PUFF_CLIFFS}, + {"puff_additive_composition", OREFLAG_PUFF_ADDITIVE}, + {NULL, 0} +}; + /////////////////////////////////////////////////////////////////////////////// -OreManager::OreManager(IGameDef *gamedef) : ObjDefManager(gamedef, OBJDEF_ORE) + +OreManager::OreManager(IGameDef *gamedef) : + ObjDefManager(gamedef, OBJDEF_ORE) { } + size_t OreManager::placeAllOres(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) { size_t nplaced = 0; @@ -53,15 +61,17 @@ size_t OreManager::placeAllOres(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nma return nplaced; } + void OreManager::clear() { for (ObjDef *object : m_objects) { - Ore *ore = (Ore *)object; + Ore *ore = (Ore *) object; delete ore; } m_objects.clear(); } + OreManager *OreManager::clone() const { auto mgr = new OreManager(); @@ -69,19 +79,23 @@ OreManager *OreManager::clone() const return mgr; } + /////////////////////////////////////////////////////////////////////////////// + Ore::~Ore() { delete noise; } + void Ore::resolveNodeNames() { getIdFromNrBacklog(&c_ore, "", CONTENT_AIR); getIdsFromNrBacklog(&c_wherein); } + size_t Ore::placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) { if (nmin.Y > y_max || nmax.Y < y_min) @@ -99,6 +113,7 @@ size_t Ore::placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) return 1; } + void Ore::cloneTo(Ore *def) const { ObjDef::cloneTo(def); @@ -118,8 +133,10 @@ void Ore::cloneTo(Ore *def) const def->biomes = biomes; } + /////////////////////////////////////////////////////////////////////////////// + ObjDef *OreScatter::clone() const { auto def = new OreScatter(); @@ -127,17 +144,19 @@ ObjDef *OreScatter::clone() const return def; } -void OreScatter::generate(MMVManip *vm, int mapseed, u32 blockseed, v3s16 nmin, - v3s16 nmax, biome_t *biomemap) + +void OreScatter::generate(MMVManip *vm, int mapseed, u32 blockseed, + v3s16 nmin, v3s16 nmax, biome_t *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 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; for (u32 i = 0; i != nclusters; i++) { @@ -146,7 +165,7 @@ void OreScatter::generate(MMVManip *vm, int mapseed, u32 blockseed, v3s16 nmin, int z0 = pr.range(nmin.Z, nmax.Z - csize + 1); if ((flags & OREFLAG_USE_NOISE) && - (NoisePerlin3D(&np, x0, y0, z0, mapseed) < nthresh)) + (NoisePerlin3D(&np, x0, y0, z0, mapseed) < nthresh)) continue; if (biomemap && !biomes.empty()) { @@ -157,24 +176,24 @@ void OreScatter::generate(MMVManip *vm, int mapseed, u32 blockseed, v3s16 nmin, } 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; - } + 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; + } } } + /////////////////////////////////////////////////////////////////////////////// + ObjDef *OreSheet::clone() const { auto def = new OreSheet(); @@ -187,8 +206,9 @@ ObjDef *OreSheet::clone() const return def; } -void OreSheet::generate(MMVManip *vm, int mapseed, u32 blockseed, v3s16 nmin, v3s16 nmax, - biome_t *biomemap) + +void OreSheet::generate(MMVManip *vm, int mapseed, u32 blockseed, + v3s16 nmin, v3s16 nmax, biome_t *biomemap) { PcgRandom pr(blockseed + 4234); MapNode n_ore(c_ore, 0, ore_param2); @@ -197,8 +217,9 @@ void OreSheet::generate(MMVManip *vm, int mapseed, u32 blockseed, v3s16 nmin, v3 int y_start_min = nmin.Y + max_height; int y_start_max = nmax.Y - max_height; - int y_start = y_start_min < y_start_max ? pr.range(y_start_min, y_start_max) - : (y_start_min + y_start_max) / 2; + int y_start = y_start_min < y_start_max ? + pr.range(y_start_min, y_start_max) : + (y_start_min + y_start_max) / 2; if (!noise) { int sx = nmax.X - nmin.X + 1; @@ -210,43 +231,45 @@ void OreSheet::generate(MMVManip *vm, int mapseed, u32 blockseed, v3s16 nmin, v3 size_t index = 0; for (int z = nmin.Z; z <= nmax.Z; z++) - for (int x = nmin.X; x <= nmax.X; x++, index++) { - float noiseval = noise->result[index]; - if (noiseval < nthresh) - continue; + for (int x = nmin.X; x <= nmax.X; x++, index++) { + float noiseval = noise->result[index]; + if (noiseval < nthresh) + continue; - if (biomemap && !biomes.empty()) { - auto it = biomes.find(biomemap[index]); - if (it == biomes.end()) - continue; - } + if (biomemap && !biomes.empty()) { + auto it = biomes.find(biomemap[index]); + if (it == biomes.end()) + continue; + } - u16 height = pr.range(column_height_min, column_height_max); - int ymidpoint = y_start + noiseval; - int y0 = MYMAX(nmin.Y, - ymidpoint - height * (1 - column_midpoint_factor)); - int y1 = MYMIN(nmax.Y, y0 + height - 1); + u16 height = pr.range(column_height_min, column_height_max); + int ymidpoint = y_start + noiseval; + int y0 = MYMAX(nmin.Y, ymidpoint - height * (1 - column_midpoint_factor)); + int y1 = MYMIN(nmax.Y, y0 + height - 1); - for (int y = y0; y <= y1; y++) { - u32 i = vm->m_area.index(x, y, z); - if (!vm->m_area.contains(i)) - continue; - if (!CONTAINS(c_wherein, vm->m_data[i].getContent())) - continue; + for (int y = y0; y <= y1; y++) { + u32 i = vm->m_area.index(x, y, z); + if (!vm->m_area.contains(i)) + continue; + if (!CONTAINS(c_wherein, vm->m_data[i].getContent())) + continue; - vm->m_data[i] = n_ore; - } + vm->m_data[i] = n_ore; } + } } + /////////////////////////////////////////////////////////////////////////////// + OrePuff::~OrePuff() { delete noise_puff_top; delete noise_puff_bottom; } + ObjDef *OrePuff::clone() const { auto def = new OrePuff(); @@ -260,8 +283,9 @@ ObjDef *OrePuff::clone() const return def; } -void OrePuff::generate(MMVManip *vm, int mapseed, u32 blockseed, v3s16 nmin, v3s16 nmax, - biome_t *biomemap) + +void OrePuff::generate(MMVManip *vm, int mapseed, u32 blockseed, + v3s16 nmin, v3s16 nmax, biome_t *biomemap) { PcgRandom pr(blockseed + 4234); MapNode n_ore(c_ore, 0, ore_param2); @@ -282,55 +306,57 @@ void OrePuff::generate(MMVManip *vm, int mapseed, u32 blockseed, v3s16 nmin, v3s size_t index = 0; for (int z = nmin.Z; z <= nmax.Z; z++) - for (int x = nmin.X; x <= nmax.X; x++, index++) { - float noiseval = noise->result[index]; - if (noiseval < nthresh) - continue; + for (int x = nmin.X; x <= nmax.X; x++, index++) { + float noiseval = noise->result[index]; + if (noiseval < nthresh) + continue; - if (biomemap && !biomes.empty()) { - auto it = biomes.find(biomemap[index]); - if (it == biomes.end()) - continue; - } + if (biomemap && !biomes.empty()) { + auto it = biomes.find(biomemap[index]); + if (it == biomes.end()) + continue; + } - if (!noise_generated) { - noise_generated = true; - noise_puff_top->perlinMap2D(nmin.X, nmin.Z); - noise_puff_bottom->perlinMap2D(nmin.X, nmin.Z); - } + if (!noise_generated) { + noise_generated = true; + noise_puff_top->perlinMap2D(nmin.X, nmin.Z); + noise_puff_bottom->perlinMap2D(nmin.X, nmin.Z); + } - float ntop = noise_puff_top->result[index]; - float nbottom = noise_puff_bottom->result[index]; + float ntop = noise_puff_top->result[index]; + float nbottom = noise_puff_bottom->result[index]; - if (!(flags & OREFLAG_PUFF_CLIFFS)) { - float ndiff = noiseval - nthresh; - if (ndiff < 1.0f) { - ntop *= ndiff; - nbottom *= ndiff; - } + if (!(flags & OREFLAG_PUFF_CLIFFS)) { + float ndiff = noiseval - nthresh; + if (ndiff < 1.0f) { + ntop *= ndiff; + nbottom *= ndiff; } + } - int ymid = y_start; - int y0 = ymid - nbottom; - int y1 = ymid + ntop; + int ymid = y_start; + int y0 = ymid - nbottom; + int y1 = ymid + ntop; - if ((flags & OREFLAG_PUFF_ADDITIVE) && (y0 > y1)) - SWAP(int, y0, y1); + if ((flags & OREFLAG_PUFF_ADDITIVE) && (y0 > y1)) + SWAP(int, y0, y1); - for (int y = y0; y <= y1; y++) { - u32 i = vm->m_area.index(x, y, z); - if (!vm->m_area.contains(i)) - continue; - if (!CONTAINS(c_wherein, vm->m_data[i].getContent())) - continue; + for (int y = y0; y <= y1; y++) { + u32 i = vm->m_area.index(x, y, z); + if (!vm->m_area.contains(i)) + continue; + if (!CONTAINS(c_wherein, vm->m_data[i].getContent())) + continue; - vm->m_data[i] = n_ore; - } + vm->m_data[i] = n_ore; } + } } + /////////////////////////////////////////////////////////////////////////////// + ObjDef *OreBlob::clone() const { auto def = new OreBlob(); @@ -338,16 +364,18 @@ ObjDef *OreBlob::clone() const return def; } -void OreBlob::generate(MMVManip *vm, int mapseed, u32 blockseed, v3s16 nmin, v3s16 nmax, - biome_t *biomemap) + +void OreBlob::generate(MMVManip *vm, int mapseed, u32 blockseed, + v3s16 nmin, v3s16 nmax, biome_t *biomemap) { PcgRandom pr(blockseed + 2404); 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 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 nblobs = volume / clust_scarcity; if (!noise) @@ -370,48 +398,45 @@ void OreBlob::generate(MMVManip *vm, int mapseed, u32 blockseed, v3s16 nmin, v3s size_t index = 0; for (u32 z1 = 0; z1 != csize; z1++) - for (u32 y1 = 0; y1 != csize; y1++) - for (u32 x1 = 0; x1 != csize; x1++, index++) { - u32 i = vm->m_area.index( - x0 + x1, y0 + y1, z0 + z1); - if (!CONTAINS(c_wherein, - vm->m_data[i].getContent())) - continue; - - // Lazily generate noise only if there's a chance - // of ore being placed This simple optimization - // makes calls 6x faster on average - if (!noise_generated) { - noise_generated = true; - noise->perlinMap3D(x0, y0, z0); - } - - float noiseval = noise->result[index]; - - float xdist = (s32)x1 - (s32)csize / 2; - float ydist = (s32)y1 - (s32)csize / 2; - float zdist = (s32)z1 - (s32)csize / 2; - - noiseval -= std::sqrt(xdist * xdist + - ydist * ydist + - zdist * zdist) / - csize; - - if (noiseval < nthresh) - continue; - - vm->m_data[i] = n_ore; - } + for (u32 y1 = 0; y1 != csize; y1++) + for (u32 x1 = 0; x1 != csize; x1++, index++) { + u32 i = vm->m_area.index(x0 + x1, y0 + y1, z0 + z1); + if (!CONTAINS(c_wherein, vm->m_data[i].getContent())) + continue; + + // Lazily generate noise only if there's a chance of ore being placed + // This simple optimization makes calls 6x faster on average + if (!noise_generated) { + noise_generated = true; + noise->perlinMap3D(x0, y0, z0); + } + + float noiseval = noise->result[index]; + + float xdist = (s32)x1 - (s32)csize / 2; + float ydist = (s32)y1 - (s32)csize / 2; + float zdist = (s32)z1 - (s32)csize / 2; + + noiseval -= std::sqrt(xdist * xdist + ydist * ydist + zdist * zdist) / csize; + + if (noiseval < nthresh) + continue; + + vm->m_data[i] = n_ore; + } } } + /////////////////////////////////////////////////////////////////////////////// + OreVein::~OreVein() { delete noise2; } + ObjDef *OreVein::clone() const { auto def = new OreVein(); @@ -424,8 +449,9 @@ ObjDef *OreVein::clone() const return def; } -void OreVein::generate(MMVManip *vm, int mapseed, u32 blockseed, v3s16 nmin, v3s16 nmax, - biome_t *biomemap) + +void OreVein::generate(MMVManip *vm, int mapseed, u32 blockseed, + v3s16 nmin, v3s16 nmax, biome_t *biomemap) { PcgRandom pr(blockseed + 520); MapNode n_ore(c_ore, 0, ore_param2); @@ -441,7 +467,7 @@ void OreVein::generate(MMVManip *vm, int mapseed, u32 blockseed, v3s16 nmin, v3s delete noise; delete noise2; int sizez = nmax.Z - nmin.Z + 1; - noise = new Noise(&np, mapseed, sizex, sizey, sizez); + noise = new Noise(&np, mapseed, sizex, sizey, sizez); noise2 = new Noise(&np, mapseed + 436, sizex, sizey, sizez); sizey_prev = sizey; } @@ -449,48 +475,49 @@ void OreVein::generate(MMVManip *vm, int mapseed, u32 blockseed, v3s16 nmin, v3s bool noise_generated = false; size_t index = 0; for (int z = nmin.Z; z <= nmax.Z; z++) - for (int y = nmin.Y; y <= nmax.Y; y++) - for (int x = nmin.X; x <= nmax.X; x++, index++) { - u32 i = vm->m_area.index(x, y, z); - if (!vm->m_area.contains(i)) - continue; - if (!CONTAINS(c_wherein, vm->m_data[i].getContent())) - continue; - - if (biomemap && !biomes.empty()) { - u32 bmapidx = sizex * (z - nmin.Z) + (x - nmin.X); - auto it = biomes.find(biomemap[bmapidx]); - if (it == biomes.end()) - continue; - } - - // Same lazy generation optimization as in OreBlob - if (!noise_generated) { - noise_generated = true; - noise->perlinMap3D(nmin.X, nmin.Y, nmin.Z); - noise2->perlinMap3D(nmin.X, nmin.Y, nmin.Z); - } - - // randval ranges from -1..1 - float randval = (float)pr.next() / (pr.RANDOM_RANGE / 2) - - 1.f; - float noiseval = contour(noise->result[index]); - float noiseval2 = contour(noise2->result[index]); - if (noiseval * noiseval2 + randval * random_factor < - nthresh) - continue; - - vm->m_data[i] = n_ore; - } + for (int y = nmin.Y; y <= nmax.Y; y++) + for (int x = nmin.X; x <= nmax.X; x++, index++) { + u32 i = vm->m_area.index(x, y, z); + if (!vm->m_area.contains(i)) + continue; + if (!CONTAINS(c_wherein, vm->m_data[i].getContent())) + continue; + + if (biomemap && !biomes.empty()) { + u32 bmapidx = sizex * (z - nmin.Z) + (x - nmin.X); + auto it = biomes.find(biomemap[bmapidx]); + if (it == biomes.end()) + continue; + } + + // Same lazy generation optimization as in OreBlob + if (!noise_generated) { + noise_generated = true; + noise->perlinMap3D(nmin.X, nmin.Y, nmin.Z); + noise2->perlinMap3D(nmin.X, nmin.Y, nmin.Z); + } + + // randval ranges from -1..1 + float randval = (float)pr.next() / (pr.RANDOM_RANGE / 2) - 1.f; + float noiseval = contour(noise->result[index]); + float noiseval2 = contour(noise2->result[index]); + if (noiseval * noiseval2 + randval * random_factor < nthresh) + continue; + + vm->m_data[i] = n_ore; + } } + /////////////////////////////////////////////////////////////////////////////// + OreStratum::~OreStratum() { delete noise_stratum_thickness; } + ObjDef *OreStratum::clone() const { auto def = new OreStratum(); @@ -503,8 +530,9 @@ ObjDef *OreStratum::clone() const return def; } -void OreStratum::generate(MMVManip *vm, int mapseed, u32 blockseed, v3s16 nmin, - v3s16 nmax, biome_t *biomemap) + +void OreStratum::generate(MMVManip *vm, int mapseed, u32 blockseed, + v3s16 nmin, v3s16 nmax, biome_t *biomemap) { PcgRandom pr(blockseed + 4234); MapNode n_ore(c_ore, 0, ore_param2); @@ -522,8 +550,7 @@ void OreStratum::generate(MMVManip *vm, int mapseed, u32 blockseed, v3s16 nmin, if (!noise_stratum_thickness) { int sx = nmax.X - nmin.X + 1; int sz = nmax.Z - nmin.Z + 1; - noise_stratum_thickness = - new Noise(&np_stratum_thickness, 0, sx, sz); + noise_stratum_thickness = new Noise(&np_stratum_thickness, 0, sx, sz); } noise_stratum_thickness->perlinMap2D(nmin.X, nmin.Z); } @@ -531,41 +558,39 @@ void OreStratum::generate(MMVManip *vm, int mapseed, u32 blockseed, v3s16 nmin, size_t index = 0; for (int z = nmin.Z; z <= nmax.Z; z++) - for (int x = nmin.X; x <= nmax.X; x++, index++) { - if (biomemap && !biomes.empty()) { - auto it = biomes.find(biomemap[index]); - if (it == biomes.end()) - continue; - } + for (int x = nmin.X; x <= nmax.X; x++, index++) { + if (biomemap && !biomes.empty()) { + auto it = biomes.find(biomemap[index]); + if (it == biomes.end()) + continue; + } - int y0; - int y1; - - if (flags & OREFLAG_USE_NOISE) { - float nhalfthick = - ((flags & OREFLAG_USE_NOISE2) ? noise_stratum_thickness - ->result[index] - : (float)stratum_thickness) / - 2.0f; - float nmid = noise->result[index]; - y0 = MYMAX(nmin.Y, std::ceil(nmid - nhalfthick)); - y1 = MYMIN(nmax.Y, nmid + nhalfthick); - } else { // Simple horizontal stratum - y0 = nmin.Y; - y1 = nmax.Y; - } + int y0; + int y1; + + if (flags & OREFLAG_USE_NOISE) { + float nhalfthick = ((flags & OREFLAG_USE_NOISE2) ? + noise_stratum_thickness->result[index] : (float)stratum_thickness) / + 2.0f; + float nmid = noise->result[index]; + y0 = MYMAX(nmin.Y, std::ceil(nmid - nhalfthick)); + y1 = MYMIN(nmax.Y, nmid + nhalfthick); + } else { // Simple horizontal stratum + y0 = nmin.Y; + y1 = nmax.Y; + } - for (int y = y0; y <= y1; y++) { - if (pr.range(1, clust_scarcity) != 1) - continue; + for (int y = y0; y <= y1; y++) { + if (pr.range(1, clust_scarcity) != 1) + continue; - u32 i = vm->m_area.index(x, y, z); - if (!vm->m_area.contains(i)) - continue; - if (!CONTAINS(c_wherein, vm->m_data[i].getContent())) - continue; + u32 i = vm->m_area.index(x, y, z); + if (!vm->m_area.contains(i)) + continue; + if (!CONTAINS(c_wherein, vm->m_data[i].getContent())) + continue; - vm->m_data[i] = n_ore; - } + vm->m_data[i] = n_ore; } + } } diff --git a/src/mapgen/mg_ore.h b/src/mapgen/mg_ore.h index e2053a274..76420fab4 100644 --- a/src/mapgen/mg_ore.h +++ b/src/mapgen/mg_ore.h @@ -25,7 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "noise.h" #include "nodedef.h" -typedef u16 biome_t; // copy from mg_biome.h to avoid an unnecessary include +typedef u16 biome_t; // copy from mg_biome.h to avoid an unnecessary include class Noise; class Mapgen; @@ -33,14 +33,13 @@ class MMVManip; /////////////////// Ore generation flags -#define OREFLAG_ABSHEIGHT 0x01 // Non-functional but kept to not break flags -#define OREFLAG_PUFF_CLIFFS 0x02 +#define OREFLAG_ABSHEIGHT 0x01 // Non-functional but kept to not break flags +#define OREFLAG_PUFF_CLIFFS 0x02 #define OREFLAG_PUFF_ADDITIVE 0x04 -#define OREFLAG_USE_NOISE 0x08 -#define OREFLAG_USE_NOISE2 0x10 +#define OREFLAG_USE_NOISE 0x08 +#define OREFLAG_USE_NOISE2 0x10 -enum OreType -{ +enum OreType { ORE_SCATTER, ORE_SHEET, ORE_PUFF, @@ -51,54 +50,48 @@ enum OreType extern FlagDesc flagdesc_ore[]; -class Ore : public ObjDef, public NodeResolver -{ +class Ore : public ObjDef, public NodeResolver { public: static const bool NEEDS_NOISE = false; - content_t c_ore; // the node to place + content_t c_ore; // the node to place std::vector<content_t> c_wherein; // the nodes to be placed in - u32 clust_scarcity; // ore cluster has a 1-in-clust_scarcity chance of appearing - // at a node + u32 clust_scarcity; // ore cluster has a 1-in-clust_scarcity chance of appearing at a node s16 clust_num_ores; // how many ore nodes are in a chunk - s16 clust_size; // how large (in nodes) a chunk of ore is + s16 clust_size; // how large (in nodes) a chunk of ore is s16 y_min; s16 y_max; - u8 ore_param2; // to set node-specific attributes - u32 flags = 0; // attributes for this ore - float nthresh; // threshold for noise at which an ore is placed - NoiseParams np; // noise for distribution of clusters (NULL for uniform - // scattering) + u8 ore_param2; // to set node-specific attributes + u32 flags = 0; // attributes for this ore + float nthresh; // threshold for noise at which an ore is placed + NoiseParams np; // noise for distribution of clusters (NULL for uniform scattering) Noise *noise = nullptr; std::unordered_set<biome_t> biomes; - Ore() = default; - ; + Ore() = default;; virtual ~Ore(); virtual void resolveNodeNames(); size_t placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax); - virtual void generate(MMVManip *vm, int mapseed, u32 blockseed, v3s16 nmin, - v3s16 nmax, biome_t *biomemap) = 0; + virtual void generate(MMVManip *vm, int mapseed, u32 blockseed, + v3s16 nmin, v3s16 nmax, biome_t *biomemap) = 0; protected: void cloneTo(Ore *def) const; }; -class OreScatter : public Ore -{ +class OreScatter : public Ore { public: static const bool NEEDS_NOISE = false; ObjDef *clone() const; - virtual void generate(MMVManip *vm, int mapseed, u32 blockseed, v3s16 nmin, - v3s16 nmax, biome_t *biomemap); + virtual void generate(MMVManip *vm, int mapseed, u32 blockseed, + v3s16 nmin, v3s16 nmax, biome_t *biomemap); }; -class OreSheet : public Ore -{ +class OreSheet : public Ore { public: static const bool NEEDS_NOISE = true; @@ -108,12 +101,11 @@ public: u16 column_height_max; float column_midpoint_factor; - virtual void generate(MMVManip *vm, int mapseed, u32 blockseed, v3s16 nmin, - v3s16 nmax, biome_t *biomemap); + virtual void generate(MMVManip *vm, int mapseed, u32 blockseed, + v3s16 nmin, v3s16 nmax, biome_t *biomemap); }; -class OrePuff : public Ore -{ +class OrePuff : public Ore { public: static const bool NEEDS_NOISE = true; @@ -127,23 +119,21 @@ public: OrePuff() = default; virtual ~OrePuff(); - virtual void generate(MMVManip *vm, int mapseed, u32 blockseed, v3s16 nmin, - v3s16 nmax, biome_t *biomemap); + virtual void generate(MMVManip *vm, int mapseed, u32 blockseed, + v3s16 nmin, v3s16 nmax, biome_t *biomemap); }; -class OreBlob : public Ore -{ +class OreBlob : public Ore { public: static const bool NEEDS_NOISE = true; ObjDef *clone() const; - virtual void generate(MMVManip *vm, int mapseed, u32 blockseed, v3s16 nmin, - v3s16 nmax, biome_t *biomemap); + virtual void generate(MMVManip *vm, int mapseed, u32 blockseed, + v3s16 nmin, v3s16 nmax, biome_t *biomemap); }; -class OreVein : public Ore -{ +class OreVein : public Ore { public: static const bool NEEDS_NOISE = true; @@ -156,12 +146,11 @@ public: OreVein() = default; virtual ~OreVein(); - virtual void generate(MMVManip *vm, int mapseed, u32 blockseed, v3s16 nmin, - v3s16 nmax, biome_t *biomemap); + virtual void generate(MMVManip *vm, int mapseed, u32 blockseed, + v3s16 nmin, v3s16 nmax, biome_t *biomemap); }; -class OreStratum : public Ore -{ +class OreStratum : public Ore { public: static const bool NEEDS_NOISE = false; @@ -174,19 +163,21 @@ public: OreStratum() = default; virtual ~OreStratum(); - virtual void generate(MMVManip *vm, int mapseed, u32 blockseed, v3s16 nmin, - v3s16 nmax, biome_t *biomemap); + virtual void generate(MMVManip *vm, int mapseed, u32 blockseed, + v3s16 nmin, v3s16 nmax, biome_t *biomemap); }; -class OreManager : public ObjDefManager -{ +class OreManager : public ObjDefManager { public: OreManager(IGameDef *gamedef); virtual ~OreManager() = default; OreManager *clone() const; - const char *getObjectTitle() const { return "ore"; } + const char *getObjectTitle() const + { + return "ore"; + } static Ore *create(OreType type) { @@ -213,5 +204,5 @@ public: size_t placeAllOres(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax); private: - OreManager(){}; + OreManager() {}; }; diff --git a/src/mapgen/mg_schematic.cpp b/src/mapgen/mg_schematic.cpp index 598c044d6..ba102d997 100644 --- a/src/mapgen/mg_schematic.cpp +++ b/src/mapgen/mg_schematic.cpp @@ -35,11 +35,14 @@ with this program; if not, write to the Free Software Foundation, Inc., /////////////////////////////////////////////////////////////////////////////// + SchematicManager::SchematicManager(Server *server) : - ObjDefManager(server, OBJDEF_SCHEMATIC), m_server(server) + ObjDefManager(server, OBJDEF_SCHEMATIC), + m_server(server) { } + SchematicManager *SchematicManager::clone() const { auto mgr = new SchematicManager(); @@ -48,6 +51,7 @@ SchematicManager *SchematicManager::clone() const return mgr; } + void SchematicManager::clear() { EmergeManager *emerge = m_server->getEmergeManager(); @@ -68,14 +72,18 @@ void SchematicManager::clear() ObjDefManager::clear(); } + /////////////////////////////////////////////////////////////////////////////// -Schematic::Schematic() = default; + +Schematic::Schematic() += default; + Schematic::~Schematic() { - delete[] schemdata; - delete[] slice_probs; + delete []schemdata; + delete []slice_probs; } ObjDef *Schematic::clone() const @@ -97,6 +105,7 @@ ObjDef *Schematic::clone() const return def; } + void Schematic::resolveNodeNames() { getIdsFromNrBacklog(&c_nodes, true, CONTENT_AIR); @@ -109,6 +118,7 @@ void Schematic::resolveNodeNames() } } + void Schematic::blitToVManip(MMVManip *vm, v3s16 p, Rotation rot, bool force_place) { assert(schemdata && slice_probs); @@ -124,33 +134,33 @@ void Schematic::blitToVManip(MMVManip *vm, v3s16 p, Rotation rot, bool force_pla int i_start, i_step_x, i_step_z; switch (rot) { - case ROTATE_90: - i_start = sx - 1; - i_step_x = zstride; - i_step_z = -xstride; - SWAP(s16, sx, sz); - break; - case ROTATE_180: - i_start = zstride * (sz - 1) + sx - 1; - i_step_x = -xstride; - i_step_z = -zstride; - break; - case ROTATE_270: - i_start = zstride * (sz - 1); - i_step_x = -zstride; - i_step_z = xstride; - SWAP(s16, sx, sz); - break; - default: - i_start = 0; - i_step_x = xstride; - i_step_z = zstride; + case ROTATE_90: + i_start = sx - 1; + i_step_x = zstride; + i_step_z = -xstride; + SWAP(s16, sx, sz); + break; + case ROTATE_180: + i_start = zstride * (sz - 1) + sx - 1; + i_step_x = -xstride; + i_step_z = -zstride; + break; + case ROTATE_270: + i_start = zstride * (sz - 1); + i_step_x = -zstride; + i_step_z = xstride; + SWAP(s16, sx, sz); + break; + default: + i_start = 0; + i_step_x = xstride; + i_step_z = zstride; } s16 y_map = p.Y; for (s16 y = 0; y != sy; y++) { if ((slice_probs[y] != MTSCHEM_PROB_ALWAYS) && - (slice_probs[y] <= myrand_range(1, MTSCHEM_PROB_ALWAYS))) + (slice_probs[y] <= myrand_range(1, MTSCHEM_PROB_ALWAYS))) continue; for (s16 z = 0; z != sz; z++) { @@ -163,10 +173,8 @@ void Schematic::blitToVManip(MMVManip *vm, v3s16 p, Rotation rot, bool force_pla if (schemdata[i].getContent() == CONTENT_IGNORE) continue; - u8 placement_prob = - schemdata[i].param1 & MTSCHEM_PROB_MASK; - bool force_place_node = - schemdata[i].param1 & MTSCHEM_FORCE_PLACE; + u8 placement_prob = schemdata[i].param1 & MTSCHEM_PROB_MASK; + bool force_place_node = schemdata[i].param1 & MTSCHEM_FORCE_PLACE; if (placement_prob == MTSCHEM_PROB_NEVER) continue; @@ -179,8 +187,7 @@ void Schematic::blitToVManip(MMVManip *vm, v3s16 p, Rotation rot, bool force_pla } if ((placement_prob != MTSCHEM_PROB_ALWAYS) && - (placement_prob <= - myrand_range(1, MTSCHEM_PROB_ALWAYS))) + (placement_prob <= myrand_range(1, MTSCHEM_PROB_ALWAYS))) continue; vm->m_data[vi] = schemdata[i]; @@ -194,8 +201,9 @@ void Schematic::blitToVManip(MMVManip *vm, v3s16 p, Rotation rot, bool force_pla } } -bool Schematic::placeOnVManip( - MMVManip *vm, v3s16 p, u32 flags, Rotation rot, bool force_place) + +bool Schematic::placeOnVManip(MMVManip *vm, v3s16 p, u32 flags, + Rotation rot, bool force_place) { assert(vm != NULL); assert(schemdata && slice_probs); @@ -205,8 +213,8 @@ bool Schematic::placeOnVManip( if (rot == ROTATE_RAND) rot = (Rotation)myrand_range(ROTATE_0, ROTATE_270); - v3s16 s = (rot == ROTATE_90 || rot == ROTATE_270) ? v3s16(size.Z, size.Y, size.X) - : size; + v3s16 s = (rot == ROTATE_90 || rot == ROTATE_270) ? + v3s16(size.Z, size.Y, size.X) : size; //// Adjust placement position if necessary if (flags & DECO_PLACE_CENTER_X) @@ -221,8 +229,8 @@ bool Schematic::placeOnVManip( return vm->m_area.contains(VoxelArea(p, p + s - v3s16(1, 1, 1))); } -void Schematic::placeOnMap( - ServerMap *map, v3s16 p, u32 flags, Rotation rot, bool force_place) +void Schematic::placeOnMap(ServerMap *map, v3s16 p, u32 flags, + Rotation rot, bool force_place) { std::map<v3s16, MapBlock *> lighting_modified_blocks; std::map<v3s16, MapBlock *> modified_blocks; @@ -236,8 +244,8 @@ void Schematic::placeOnMap( if (rot == ROTATE_RAND) rot = (Rotation)myrand_range(ROTATE_0, ROTATE_270); - v3s16 s = (rot == ROTATE_90 || rot == ROTATE_270) ? v3s16(size.Z, size.Y, size.X) - : size; + v3s16 s = (rot == ROTATE_90 || rot == ROTATE_270) ? + v3s16(size.Z, size.Y, size.X) : size; //// Adjust placement position if necessary if (flags & DECO_PLACE_CENTER_X) @@ -270,7 +278,9 @@ void Schematic::placeOnMap( map->dispatchEvent(event); } -bool Schematic::deserializeFromMts(std::istream *is, std::vector<std::string> *names) + +bool Schematic::deserializeFromMts(std::istream *is, + std::vector<std::string> *names) { std::istream &ss = *is; content_t cignore = CONTENT_IGNORE; @@ -279,20 +289,16 @@ bool Schematic::deserializeFromMts(std::istream *is, std::vector<std::string> *n //// Read signature u32 signature = readU32(ss); if (signature != MTSCHEM_FILE_SIGNATURE) { - errorstream << __FUNCTION__ - << ": invalid schematic " - "file" - << std::endl; + errorstream << __FUNCTION__ << ": invalid schematic " + "file" << std::endl; return false; } //// Read version u16 version = readU16(ss); if (version > MTSCHEM_FILE_VER_HIGHEST_READ) { - errorstream << __FUNCTION__ - << ": unsupported schematic " - "file version" - << std::endl; + errorstream << __FUNCTION__ << ": unsupported schematic " + "file version" << std::endl; return false; } @@ -300,7 +306,7 @@ bool Schematic::deserializeFromMts(std::istream *is, std::vector<std::string> *n size = readV3S16(ss); //// Read Y-slice probability values - delete[] slice_probs; + delete []slice_probs; slice_probs = new u8[size.Y]; for (int y = 0; y != size.Y; y++) slice_probs[y] = (version >= 3) ? readU8(ss) : MTSCHEM_PROB_ALWAYS_OLD; @@ -324,11 +330,11 @@ bool Schematic::deserializeFromMts(std::istream *is, std::vector<std::string> *n //// Read node data size_t nodecount = size.X * size.Y * size.Z; - delete[] schemdata; + delete []schemdata; schemdata = new MapNode[nodecount]; - MapNode::deSerializeBulk( - ss, SER_FMT_VER_HIGHEST_READ, schemdata, nodecount, 2, 2, true); + MapNode::deSerializeBulk(ss, SER_FMT_VER_HIGHEST_READ, schemdata, + nodecount, 2, 2, true); // Fix probability values for nodes that were ignore; removed in v2 if (version < 2) { @@ -351,16 +357,17 @@ bool Schematic::deserializeFromMts(std::istream *is, std::vector<std::string> *n return true; } -bool Schematic::serializeToMts( - std::ostream *os, const std::vector<std::string> &names) const + +bool Schematic::serializeToMts(std::ostream *os, + const std::vector<std::string> &names) const { std::ostream &ss = *os; - writeU32(ss, MTSCHEM_FILE_SIGNATURE); // signature + writeU32(ss, MTSCHEM_FILE_SIGNATURE); // signature writeU16(ss, MTSCHEM_FILE_VER_HIGHEST_WRITE); // version - writeV3S16(ss, size); // schematic size + writeV3S16(ss, size); // schematic size - for (int y = 0; y != size.Y; y++) // Y slice probabilities + for (int y = 0; y != size.Y; y++) // Y slice probabilities writeU8(ss, slice_probs[y]); writeU16(ss, names.size()); // name count @@ -368,14 +375,16 @@ bool Schematic::serializeToMts( ss << serializeString(names[i]); // node names // compressed bulk node data - MapNode::serializeBulk(ss, SER_FMT_VER_HIGHEST_WRITE, schemdata, - size.X * size.Y * size.Z, 2, 2, true); + MapNode::serializeBulk(ss, SER_FMT_VER_HIGHEST_WRITE, + schemdata, size.X * size.Y * size.Z, 2, 2, true); return true; } -bool Schematic::serializeToLua(std::ostream *os, const std::vector<std::string> &names, - bool use_comments, u32 indent_spaces) const + +bool Schematic::serializeToLua(std::ostream *os, + const std::vector<std::string> &names, bool use_comments, + u32 indent_spaces) const { std::ostream &ss = *os; @@ -387,8 +396,10 @@ bool Schematic::serializeToLua(std::ostream *os, const std::vector<std::string> { ss << "schematic = {" << std::endl; ss << indent << "size = " - << "{x=" << size.X << ", y=" << size.Y << ", z=" << size.Z << "}," - << std::endl; + << "{x=" << size.X + << ", y=" << size.Y + << ", z=" << size.Z + << "}," << std::endl; } //// Write y-slice probabilities @@ -399,8 +410,9 @@ bool Schematic::serializeToLua(std::ostream *os, const std::vector<std::string> u8 probability = slice_probs[y] & MTSCHEM_PROB_MASK; ss << indent << indent << "{" - << "ypos=" << y << ", prob=" << (u16)probability * 2 << "}," - << std::endl; + << "ypos=" << y + << ", prob=" << (u16)probability * 2 + << "}," << std::endl; } ss << indent << "}," << std::endl; @@ -412,31 +424,29 @@ bool Schematic::serializeToLua(std::ostream *os, const std::vector<std::string> u32 i = 0; for (u16 z = 0; z != size.Z; z++) - for (u16 y = 0; y != size.Y; y++) { - if (use_comments) { - ss << std::endl - << indent << indent << "-- z=" << z - << ", y=" << y << std::endl; - } + for (u16 y = 0; y != size.Y; y++) { + if (use_comments) { + ss << std::endl + << indent << indent + << "-- z=" << z + << ", y=" << y << std::endl; + } - for (u16 x = 0; x != size.X; x++, i++) { - u8 probability = schemdata[i].param1 & - MTSCHEM_PROB_MASK; - bool force_place = schemdata[i].param1 & - MTSCHEM_FORCE_PLACE; + for (u16 x = 0; x != size.X; x++, i++) { + u8 probability = schemdata[i].param1 & MTSCHEM_PROB_MASK; + bool force_place = schemdata[i].param1 & MTSCHEM_FORCE_PLACE; - ss << indent << indent << "{" - << "name=\"" - << names[schemdata[i].getContent()] - << "\", prob=" << (u16)probability * 2 - << ", param2=" << (u16)schemdata[i].param2; + ss << indent << indent << "{" + << "name=\"" << names[schemdata[i].getContent()] + << "\", prob=" << (u16)probability * 2 + << ", param2=" << (u16)schemdata[i].param2; - if (force_place) - ss << ", force_place=true"; + if (force_place) + ss << ", force_place=true"; - ss << "}," << std::endl; - } + ss << "}," << std::endl; } + } ss << indent << "}," << std::endl; } @@ -446,13 +456,14 @@ bool Schematic::serializeToLua(std::ostream *os, const std::vector<std::string> return true; } + bool Schematic::loadSchematicFromFile(const std::string &filename, - const NodeDefManager *ndef, StringMap *replace_names) + const NodeDefManager *ndef, StringMap *replace_names) { std::ifstream is(filename.c_str(), std::ios_base::binary); if (!is.good()) { - errorstream << __FUNCTION__ << ": unable to open file '" << filename - << "'" << std::endl; + errorstream << __FUNCTION__ << ": unable to open file '" + << filename << "'" << std::endl; return false; } @@ -479,8 +490,9 @@ bool Schematic::loadSchematicFromFile(const std::string &filename, return true; } -bool Schematic::saveSchematicToFile( - const std::string &filename, const NodeDefManager *ndef) + +bool Schematic::saveSchematicToFile(const std::string &filename, + const NodeDefManager *ndef) { MapNode *orig_schemdata = schemdata; std::vector<std::string> ndef_nodenames; @@ -506,7 +518,7 @@ bool Schematic::saveSchematicToFile( bool status = serializeToMts(&os, *names); if (ndef) { - delete[] schemdata; + delete []schemdata; schemdata = orig_schemdata; } @@ -516,6 +528,7 @@ bool Schematic::saveSchematicToFile( return fs::safeWriteToFile(filename, os.str()); } + bool Schematic::getSchematicFromMap(Map *map, v3s16 p1, v3s16 p2) { MMVManip *vm = new MMVManip(map); @@ -534,20 +547,22 @@ bool Schematic::getSchematicFromMap(Map *map, v3s16 p1, v3s16 p2) u32 i = 0; for (s16 z = p1.Z; z <= p2.Z; z++) - for (s16 y = p1.Y; y <= p2.Y; y++) { - u32 vi = vm->m_area.index(p1.X, y, z); - for (s16 x = p1.X; x <= p2.X; x++, i++, vi++) { - schemdata[i] = vm->m_data[vi]; - schemdata[i].param1 = MTSCHEM_PROB_ALWAYS; - } + for (s16 y = p1.Y; y <= p2.Y; y++) { + u32 vi = vm->m_area.index(p1.X, y, z); + for (s16 x = p1.X; x <= p2.X; x++, i++, vi++) { + schemdata[i] = vm->m_data[vi]; + schemdata[i].param1 = MTSCHEM_PROB_ALWAYS; } + } delete vm; return true; } -void Schematic::applyProbabilities(v3s16 p0, std::vector<std::pair<v3s16, u8>> *plist, - std::vector<std::pair<s16, u8>> *splist) + +void Schematic::applyProbabilities(v3s16 p0, + std::vector<std::pair<v3s16, u8> > *plist, + std::vector<std::pair<s16, u8> > *splist) { for (size_t i = 0; i != plist->size(); i++) { v3s16 p = (*plist)[i].first - p0; @@ -568,8 +583,9 @@ void Schematic::applyProbabilities(v3s16 p0, std::vector<std::pair<v3s16, u8>> * } } + void generate_nodelist_and_update_ids(MapNode *nodes, size_t nodecount, - std::vector<std::string> *usednodes, const NodeDefManager *ndef) + std::vector<std::string> *usednodes, const NodeDefManager *ndef) { std::unordered_map<content_t, content_t> nodeidmap; content_t numids = 0; @@ -578,8 +594,7 @@ void generate_nodelist_and_update_ids(MapNode *nodes, size_t nodecount, content_t id; content_t c = nodes[i].getContent(); - std::unordered_map<content_t, content_t>::const_iterator it = - nodeidmap.find(c); + std::unordered_map<content_t, content_t>::const_iterator it = nodeidmap.find(c); if (it == nodeidmap.end()) { id = numids; numids++; diff --git a/src/mapgen/mg_schematic.h b/src/mapgen/mg_schematic.h index 9ba96b4a1..6b31251b6 100644 --- a/src/mapgen/mg_schematic.h +++ b/src/mapgen/mg_schematic.h @@ -68,31 +68,29 @@ class Server; //// Schematic constants #define MTSCHEM_FILE_SIGNATURE 0x4d54534d // 'MTSM' -#define MTSCHEM_FILE_VER_HIGHEST_READ 4 +#define MTSCHEM_FILE_VER_HIGHEST_READ 4 #define MTSCHEM_FILE_VER_HIGHEST_WRITE 4 -#define MTSCHEM_PROB_MASK 0x7F +#define MTSCHEM_PROB_MASK 0x7F -#define MTSCHEM_PROB_NEVER 0x00 -#define MTSCHEM_PROB_ALWAYS 0x7F +#define MTSCHEM_PROB_NEVER 0x00 +#define MTSCHEM_PROB_ALWAYS 0x7F #define MTSCHEM_PROB_ALWAYS_OLD 0xFF -#define MTSCHEM_FORCE_PLACE 0x80 +#define MTSCHEM_FORCE_PLACE 0x80 enum SchematicType { SCHEMATIC_NORMAL, }; -enum SchematicFormatType -{ +enum SchematicFormatType { SCHEM_FMT_HANDLE, SCHEM_FMT_MTS, SCHEM_FMT_LUA, }; -class Schematic : public ObjDef, public NodeResolver -{ +class Schematic : public ObjDef, public NodeResolver { public: Schematic(); virtual ~Schematic(); @@ -102,24 +100,24 @@ public: virtual void resolveNodeNames(); bool loadSchematicFromFile(const std::string &filename, - const NodeDefManager *ndef, StringMap *replace_names = NULL); - bool saveSchematicToFile(const std::string &filename, const NodeDefManager *ndef); + const NodeDefManager *ndef, StringMap *replace_names = NULL); + bool saveSchematicToFile(const std::string &filename, + const NodeDefManager *ndef); bool getSchematicFromMap(Map *map, v3s16 p1, v3s16 p2); bool deserializeFromMts(std::istream *is, std::vector<std::string> *names); - bool serializeToMts( - std::ostream *os, const std::vector<std::string> &names) const; + bool serializeToMts(std::ostream *os, + const std::vector<std::string> &names) const; bool serializeToLua(std::ostream *os, const std::vector<std::string> &names, - bool use_comments, u32 indent_spaces) const; + bool use_comments, u32 indent_spaces) const; void blitToVManip(MMVManip *vm, v3s16 p, Rotation rot, bool force_place); - bool placeOnVManip( - MMVManip *vm, v3s16 p, u32 flags, Rotation rot, bool force_place); - void placeOnMap(ServerMap *map, v3s16 p, u32 flags, Rotation rot, - bool force_place); + bool placeOnVManip(MMVManip *vm, v3s16 p, u32 flags, Rotation rot, bool force_place); + void placeOnMap(ServerMap *map, v3s16 p, u32 flags, Rotation rot, bool force_place); - void applyProbabilities(v3s16 p0, std::vector<std::pair<v3s16, u8>> *plist, - std::vector<std::pair<s16, u8>> *splist); + void applyProbabilities(v3s16 p0, + std::vector<std::pair<v3s16, u8> > *plist, + std::vector<std::pair<s16, u8> > *splist); std::vector<content_t> c_nodes; u32 flags = 0; @@ -128,8 +126,7 @@ public: u8 *slice_probs = nullptr; }; -class SchematicManager : public ObjDefManager -{ +class SchematicManager : public ObjDefManager { public: SchematicManager(Server *server); virtual ~SchematicManager() = default; @@ -138,15 +135,21 @@ public: virtual void clear(); - const char *getObjectTitle() const { return "schematic"; } + const char *getObjectTitle() const + { + return "schematic"; + } - static Schematic *create(SchematicType type) { return new Schematic; } + static Schematic *create(SchematicType type) + { + return new Schematic; + } private: - SchematicManager(){}; + SchematicManager() {}; Server *m_server; }; void generate_nodelist_and_update_ids(MapNode *nodes, size_t nodecount, - std::vector<std::string> *usednodes, const NodeDefManager *ndef); + std::vector<std::string> *usednodes, const NodeDefManager *ndef); diff --git a/src/mapgen/treegen.cpp b/src/mapgen/treegen.cpp index ddf518290..e7e30c880 100644 --- a/src/mapgen/treegen.cpp +++ b/src/mapgen/treegen.cpp @@ -32,8 +32,8 @@ with this program; if not, write to the Free Software Foundation, Inc., namespace treegen { -void make_tree(MMVManip &vmanip, v3s16 p0, bool is_apple_tree, const NodeDefManager *ndef, - s32 seed) +void make_tree(MMVManip &vmanip, v3s16 p0, bool is_apple_tree, + const NodeDefManager *ndef, s32 seed) { /* NOTE: Tree-placing code is currently duplicated in the engine @@ -44,14 +44,11 @@ void make_tree(MMVManip &vmanip, v3s16 p0, bool is_apple_tree, const NodeDefMana MapNode leavesnode(ndef->getId("mapgen_leaves")); MapNode applenode(ndef->getId("mapgen_apple")); if (treenode == CONTENT_IGNORE) - errorstream << "Treegen: Mapgen alias 'mapgen_tree' is invalid!" - << std::endl; + errorstream << "Treegen: Mapgen alias 'mapgen_tree' is invalid!" << std::endl; if (leavesnode == CONTENT_IGNORE) - errorstream << "Treegen: Mapgen alias 'mapgen_leaves' is invalid!" - << std::endl; + errorstream << "Treegen: Mapgen alias 'mapgen_leaves' is invalid!" << std::endl; if (applenode == CONTENT_IGNORE) - errorstream << "Treegen: Mapgen alias 'mapgen_apple' is invalid!" - << std::endl; + errorstream << "Treegen: Mapgen alias 'mapgen_apple' is invalid!" << std::endl; PseudoRandom pr(seed); s16 trunk_h = pr.range(4, 5); @@ -75,56 +72,57 @@ void make_tree(MMVManip &vmanip, v3s16 p0, bool is_apple_tree, const NodeDefMana // Force leaves at near the end of the trunk s16 d = 1; for (s16 z = -d; z <= d; z++) - for (s16 y = -d; y <= d; y++) - for (s16 x = -d; x <= d; x++) { - leaves_d[leaves_a.index(v3s16(x, y, z))] = 1; - } + for (s16 y = -d; y <= d; y++) + for (s16 x = -d; x <= d; x++) { + leaves_d[leaves_a.index(v3s16(x, y, z))] = 1; + } // Add leaves randomly for (u32 iii = 0; iii < 7; iii++) { - v3s16 p(pr.range(leaves_a.MinEdge.X, leaves_a.MaxEdge.X - d), - pr.range(leaves_a.MinEdge.Y, leaves_a.MaxEdge.Y - d), - pr.range(leaves_a.MinEdge.Z, leaves_a.MaxEdge.Z - d)); + v3s16 p( + pr.range(leaves_a.MinEdge.X, leaves_a.MaxEdge.X - d), + pr.range(leaves_a.MinEdge.Y, leaves_a.MaxEdge.Y - d), + pr.range(leaves_a.MinEdge.Z, leaves_a.MaxEdge.Z - d) + ); for (s16 z = 0; z <= d; z++) - for (s16 y = 0; y <= d; y++) - for (s16 x = 0; x <= d; x++) { - leaves_d[leaves_a.index(p + v3s16(x, y, z))] = 1; - } + for (s16 y = 0; y <= d; y++) + for (s16 x = 0; x <= d; x++) { + leaves_d[leaves_a.index(p + v3s16(x, y, z))] = 1; + } } // Blit leaves to vmanip for (s16 z = leaves_a.MinEdge.Z; z <= leaves_a.MaxEdge.Z; z++) - for (s16 y = leaves_a.MinEdge.Y; y <= leaves_a.MaxEdge.Y; y++) { - v3s16 pmin(leaves_a.MinEdge.X, y, z); - u32 i = leaves_a.index(pmin); - u32 vi = vmanip.m_area.index(pmin + p1); - for (s16 x = leaves_a.MinEdge.X; x <= leaves_a.MaxEdge.X; x++) { - v3s16 p(x, y, z); - if (vmanip.m_area.contains(p + p1) && - (vmanip.m_data[vi].getContent() == - CONTENT_AIR || - vmanip.m_data[vi].getContent() == - CONTENT_IGNORE)) { - if (leaves_d[i] == 1) { - bool is_apple = pr.range(0, 99) < 10; - if (is_apple_tree && is_apple) - vmanip.m_data[vi] = applenode; - else - vmanip.m_data[vi] = leavesnode; - } + for (s16 y = leaves_a.MinEdge.Y; y <= leaves_a.MaxEdge.Y; y++) { + v3s16 pmin(leaves_a.MinEdge.X, y, z); + u32 i = leaves_a.index(pmin); + u32 vi = vmanip.m_area.index(pmin + p1); + for (s16 x = leaves_a.MinEdge.X; x <= leaves_a.MaxEdge.X; x++) { + v3s16 p(x, y, z); + if (vmanip.m_area.contains(p + p1) && + (vmanip.m_data[vi].getContent() == CONTENT_AIR || + vmanip.m_data[vi].getContent() == CONTENT_IGNORE)) { + if (leaves_d[i] == 1) { + bool is_apple = pr.range(0, 99) < 10; + if (is_apple_tree && is_apple) + vmanip.m_data[vi] = applenode; + else + vmanip.m_data[vi] = leavesnode; } - vi++; - i++; } + vi++; + i++; } + } } + // L-System tree LUA spawner -treegen::error spawn_ltree(ServerMap *map, v3s16 p0, const NodeDefManager *ndef, - const TreeDef &tree_definition) +treegen::error spawn_ltree(ServerMap *map, v3s16 p0, + const NodeDefManager *ndef, const TreeDef &tree_definition) { - std::map<v3s16, MapBlock *> modified_blocks; + std::map<v3s16, MapBlock*> modified_blocks; MMVManip vmanip(map); v3s16 tree_blockp = getNodeBlockPos(p0); treegen::error e; @@ -145,15 +143,16 @@ treegen::error spawn_ltree(ServerMap *map, v3s16 p0, const NodeDefManager *ndef, return SUCCESS; } -// L-System tree generator -treegen::error make_ltree(MMVManip &vmanip, v3s16 p0, const NodeDefManager *ndef, - TreeDef tree_definition) + +//L-System tree generator +treegen::error make_ltree(MMVManip &vmanip, v3s16 p0, + const NodeDefManager *ndef, TreeDef tree_definition) { s32 seed; if (tree_definition.explicit_seed) seed = tree_definition.seed + 14002; else - seed = p0.X * 2 + p0.Y * 4 + p0.Z; // use the tree position to seed PRNG + seed = p0.X * 2 + p0.Y * 4 + p0.Z; // use the tree position to seed PRNG PseudoRandom ps(seed); // chance of inserting abcd rules @@ -162,7 +161,7 @@ treegen::error make_ltree(MMVManip &vmanip, v3s16 p0, const NodeDefManager *ndef double prop_c = 7; double prop_d = 6; - // randomize tree growth level, minimum=2 + //randomize tree growth level, minimum=2 s16 iterations = tree_definition.iterations; if (tree_definition.iterations_random_level > 0) iterations -= ps.range(0, tree_definition.iterations_random_level); @@ -171,20 +170,19 @@ treegen::error make_ltree(MMVManip &vmanip, v3s16 p0, const NodeDefManager *ndef s16 MAX_ANGLE_OFFSET = 5; double angle_in_radians = (double)tree_definition.angle * M_PI / 180; - double angleOffset_in_radians = - (s16)(ps.range(0, 1) % MAX_ANGLE_OFFSET) * M_PI / 180; + double angleOffset_in_radians = (s16)(ps.range(0, 1) % MAX_ANGLE_OFFSET) * M_PI / 180; - // initialize rotation matrix, position and stacks for branches + //initialize rotation matrix, position and stacks for branches core::matrix4 rotation; rotation = setRotationAxisRadians(rotation, M_PI / 2, v3f(0, 0, 1)); v3f position; position.X = p0.X; position.Y = p0.Y; position.Z = p0.Z; - std::stack<core::matrix4> stack_orientation; - std::stack<v3f> stack_position; + std::stack <core::matrix4> stack_orientation; + std::stack <v3f> stack_position; - // generate axiom + //generate axiom std::string axiom = tree_definition.initial_axiom; for (s16 i = 0; i < iterations; i++) { std::string temp; @@ -229,28 +227,42 @@ treegen::error make_ltree(MMVManip &vmanip, v3s16 p0, const NodeDefManager *ndef // Add trunk nodes below a wide trunk to avoid gaps when tree is on sloping ground if (tree_definition.trunk_type == "double") { - tree_trunk_placement(vmanip, - v3f(position.X + 1, position.Y - 1, position.Z), - tree_definition); - tree_trunk_placement(vmanip, - v3f(position.X, position.Y - 1, position.Z + 1), - tree_definition); - tree_trunk_placement(vmanip, - v3f(position.X + 1, position.Y - 1, position.Z + 1), - tree_definition); + tree_trunk_placement( + vmanip, + v3f(position.X + 1, position.Y - 1, position.Z), + tree_definition + ); + tree_trunk_placement( + vmanip, + v3f(position.X, position.Y - 1, position.Z + 1), + tree_definition + ); + tree_trunk_placement( + vmanip, + v3f(position.X + 1, position.Y - 1, position.Z + 1), + tree_definition + ); } else if (tree_definition.trunk_type == "crossed") { - tree_trunk_placement(vmanip, - v3f(position.X + 1, position.Y - 1, position.Z), - tree_definition); - tree_trunk_placement(vmanip, - v3f(position.X - 1, position.Y - 1, position.Z), - tree_definition); - tree_trunk_placement(vmanip, - v3f(position.X, position.Y - 1, position.Z + 1), - tree_definition); - tree_trunk_placement(vmanip, - v3f(position.X, position.Y - 1, position.Z - 1), - tree_definition); + tree_trunk_placement( + vmanip, + v3f(position.X + 1, position.Y - 1, position.Z), + tree_definition + ); + tree_trunk_placement( + vmanip, + v3f(position.X - 1, position.Y - 1, position.Z), + tree_definition + ); + tree_trunk_placement( + vmanip, + v3f(position.X, position.Y - 1, position.Z + 1), + tree_definition + ); + tree_trunk_placement( + vmanip, + v3f(position.X, position.Y - 1, position.Z - 1), + tree_definition + ); } /* build tree out of generated axiom @@ -281,7 +293,7 @@ treegen::error make_ltree(MMVManip &vmanip, v3s16 p0, const NodeDefManager *ndef */ - s16 x, y, z; + s16 x,y,z; for (s16 i = 0; i < (s16)axiom.size(); i++) { char axiom_char = axiom.at(i); core::matrix4 temp_rotation; @@ -294,149 +306,164 @@ treegen::error make_ltree(MMVManip &vmanip, v3s16 p0, const NodeDefManager *ndef position += dir; break; case 'T': - tree_trunk_placement(vmanip, - v3f(position.X, position.Y, position.Z), - tree_definition); + tree_trunk_placement( + vmanip, + v3f(position.X, position.Y, position.Z), + tree_definition + ); if (tree_definition.trunk_type == "double" && !tree_definition.thin_branches) { - tree_trunk_placement(vmanip, - v3f(position.X + 1, position.Y, - position.Z), - tree_definition); - tree_trunk_placement(vmanip, - v3f(position.X, position.Y, - position.Z + 1), - tree_definition); - tree_trunk_placement(vmanip, - v3f(position.X + 1, position.Y, - position.Z + 1), - tree_definition); + tree_trunk_placement( + vmanip, + v3f(position.X + 1, position.Y, position.Z), + tree_definition + ); + tree_trunk_placement( + vmanip, + v3f(position.X, position.Y, position.Z + 1), + tree_definition + ); + tree_trunk_placement( + vmanip, + v3f(position.X + 1, position.Y, position.Z + 1), + tree_definition + ); } else if (tree_definition.trunk_type == "crossed" && !tree_definition.thin_branches) { - tree_trunk_placement(vmanip, - v3f(position.X + 1, position.Y, - position.Z), - tree_definition); - tree_trunk_placement(vmanip, - v3f(position.X - 1, position.Y, - position.Z), - tree_definition); - tree_trunk_placement(vmanip, - v3f(position.X, position.Y, - position.Z + 1), - tree_definition); - tree_trunk_placement(vmanip, - v3f(position.X, position.Y, - position.Z - 1), - tree_definition); + tree_trunk_placement( + vmanip, + v3f(position.X + 1, position.Y, position.Z), + tree_definition + ); + tree_trunk_placement( + vmanip, + v3f(position.X - 1, position.Y, position.Z), + tree_definition + ); + tree_trunk_placement( + vmanip, + v3f(position.X, position.Y, position.Z + 1), + tree_definition + ); + tree_trunk_placement( + vmanip, + v3f(position.X, position.Y, position.Z - 1), + tree_definition + ); } dir = v3f(1, 0, 0); dir = transposeMatrix(rotation, dir); position += dir; break; case 'F': - tree_trunk_placement(vmanip, - v3f(position.X, position.Y, position.Z), - tree_definition); + tree_trunk_placement( + vmanip, + v3f(position.X, position.Y, position.Z), + tree_definition + ); if ((stack_orientation.empty() && - tree_definition.trunk_type == "double") || + tree_definition.trunk_type == "double") || (!stack_orientation.empty() && - tree_definition.trunk_type == - "double" && - !tree_definition.thin_branches)) { - tree_trunk_placement(vmanip, - v3f(position.X + 1, position.Y, - position.Z), - tree_definition); - tree_trunk_placement(vmanip, - v3f(position.X, position.Y, - position.Z + 1), - tree_definition); - tree_trunk_placement(vmanip, - v3f(position.X + 1, position.Y, - position.Z + 1), - tree_definition); + tree_definition.trunk_type == "double" && + !tree_definition.thin_branches)) { + tree_trunk_placement( + vmanip, + v3f(position.X + 1, position.Y, position.Z), + tree_definition + ); + tree_trunk_placement( + vmanip, + v3f(position.X, position.Y, position.Z + 1), + tree_definition + ); + tree_trunk_placement( + vmanip, + v3f(position.X + 1, position.Y, position.Z + 1), + tree_definition + ); } else if ((stack_orientation.empty() && - tree_definition.trunk_type == - "crossed") || + tree_definition.trunk_type == "crossed") || (!stack_orientation.empty() && - tree_definition.trunk_type == - "crossed" && - !tree_definition.thin_branches)) { - tree_trunk_placement(vmanip, - v3f(position.X + 1, position.Y, - position.Z), - tree_definition); - tree_trunk_placement(vmanip, - v3f(position.X - 1, position.Y, - position.Z), - tree_definition); - tree_trunk_placement(vmanip, - v3f(position.X, position.Y, - position.Z + 1), - tree_definition); - tree_trunk_placement(vmanip, - v3f(position.X, position.Y, - position.Z - 1), - tree_definition); - } - if (!stack_orientation.empty()) { + tree_definition.trunk_type == "crossed" && + !tree_definition.thin_branches)) { + tree_trunk_placement( + vmanip, + v3f(position.X + 1, position.Y, position.Z), + tree_definition + ); + tree_trunk_placement( + vmanip, + v3f(position.X - 1, position.Y, position.Z), + tree_definition + ); + tree_trunk_placement( + vmanip, + v3f(position.X, position.Y, position.Z + 1), + tree_definition + ); + tree_trunk_placement( + vmanip, + v3f(position.X, position.Y, position.Z - 1), + tree_definition + ); + } if (!stack_orientation.empty()) { s16 size = 1; for (x = -size; x <= size; x++) - for (y = -size; y <= size; y++) - for (z = -size; z <= size; z++) { - if (abs(x) == size && - abs(y) == size && - abs(z) == size) { - tree_leaves_placement( - vmanip, - v3f(position.X + x + 1, - position.Y + y, - position.Z + z), - ps.next(), - tree_definition); - tree_leaves_placement( - vmanip, - v3f(position.X + x - 1, - position.Y + y, - position.Z + z), - ps.next(), - tree_definition); - tree_leaves_placement( - vmanip, - v3f(position.X + x, - position.Y + y, - position.Z + z + - 1), - ps.next(), - tree_definition); - tree_leaves_placement( - vmanip, - v3f(position.X + x, - position.Y + y, - position.Z + z - - 1), - ps.next(), - tree_definition); - } - } + for (y = -size; y <= size; y++) + for (z = -size; z <= size; z++) { + if (abs(x) == size && + abs(y) == size && + abs(z) == size) { + tree_leaves_placement( + vmanip, + v3f(position.X + x + 1, position.Y + y, + position.Z + z), + ps.next(), + tree_definition + ); + tree_leaves_placement( + vmanip, + v3f(position.X + x - 1, position.Y + y, + position.Z + z), + ps.next(), + tree_definition + ); + tree_leaves_placement( + vmanip,v3f(position.X + x, position.Y + y, + position.Z + z + 1), + ps.next(), + tree_definition + ); + tree_leaves_placement( + vmanip,v3f(position.X + x, position.Y + y, + position.Z + z - 1), + ps.next(), + tree_definition + ); + } + } } dir = v3f(1, 0, 0); dir = transposeMatrix(rotation, dir); position += dir; break; case 'f': - tree_single_leaves_placement(vmanip, - v3f(position.X, position.Y, position.Z), - ps.next(), tree_definition); + tree_single_leaves_placement( + vmanip, + v3f(position.X, position.Y, position.Z), + ps.next(), + tree_definition + ); dir = v3f(1, 0, 0); dir = transposeMatrix(rotation, dir); position += dir; break; case 'R': - tree_fruit_placement(vmanip, - v3f(position.X, position.Y, position.Z), - tree_definition); + tree_fruit_placement( + vmanip, + v3f(position.X, position.Y, position.Z), + tree_definition + ); dir = v3f(1, 0, 0); dir = transposeMatrix(rotation, dir); position += dir; @@ -458,41 +485,37 @@ treegen::error make_ltree(MMVManip &vmanip, v3s16 p0, const NodeDefManager *ndef case '+': temp_rotation.makeIdentity(); temp_rotation = setRotationAxisRadians(temp_rotation, - angle_in_radians + angleOffset_in_radians, - v3f(0, 0, 1)); + angle_in_radians + angleOffset_in_radians, v3f(0, 0, 1)); rotation *= temp_rotation; break; case '-': temp_rotation.makeIdentity(); temp_rotation = setRotationAxisRadians(temp_rotation, - angle_in_radians + angleOffset_in_radians, - v3f(0, 0, -1)); + angle_in_radians + angleOffset_in_radians, v3f(0, 0, -1)); rotation *= temp_rotation; break; case '&': temp_rotation.makeIdentity(); temp_rotation = setRotationAxisRadians(temp_rotation, - angle_in_radians + angleOffset_in_radians, - v3f(0, 1, 0)); + angle_in_radians + angleOffset_in_radians, v3f(0, 1, 0)); rotation *= temp_rotation; break; case '^': temp_rotation.makeIdentity(); temp_rotation = setRotationAxisRadians(temp_rotation, - angle_in_radians + angleOffset_in_radians, - v3f(0, -1, 0)); + angle_in_radians + angleOffset_in_radians, v3f(0, -1, 0)); rotation *= temp_rotation; break; case '*': temp_rotation.makeIdentity(); - temp_rotation = setRotationAxisRadians( - temp_rotation, angle_in_radians, v3f(1, 0, 0)); + temp_rotation = setRotationAxisRadians(temp_rotation, + angle_in_radians, v3f(1, 0, 0)); rotation *= temp_rotation; break; case '/': temp_rotation.makeIdentity(); - temp_rotation = setRotationAxisRadians( - temp_rotation, angle_in_radians, v3f(-1, 0, 0)); + temp_rotation = setRotationAxisRadians(temp_rotation, + angle_in_radians, v3f(-1, 0, 0)); rotation *= temp_rotation; break; default: @@ -503,18 +526,20 @@ treegen::error make_ltree(MMVManip &vmanip, v3s16 p0, const NodeDefManager *ndef return SUCCESS; } + void tree_node_placement(MMVManip &vmanip, v3f p0, MapNode node) { v3s16 p1 = v3s16(myround(p0.X), myround(p0.Y), myround(p0.Z)); if (!vmanip.m_area.contains(p1)) return; u32 vi = vmanip.m_area.index(p1); - if (vmanip.m_data[vi].getContent() != CONTENT_AIR && - vmanip.m_data[vi].getContent() != CONTENT_IGNORE) + if (vmanip.m_data[vi].getContent() != CONTENT_AIR + && vmanip.m_data[vi].getContent() != CONTENT_IGNORE) return; vmanip.m_data[vmanip.m_area.index(p1)] = node; } + void tree_trunk_placement(MMVManip &vmanip, v3f p0, TreeDef &tree_definition) { v3s16 p1 = v3s16(myround(p0.X), myround(p0.Y), myround(p0.Z)); @@ -522,16 +547,17 @@ void tree_trunk_placement(MMVManip &vmanip, v3f p0, TreeDef &tree_definition) return; u32 vi = vmanip.m_area.index(p1); content_t current_node = vmanip.m_data[vi].getContent(); - if (current_node != CONTENT_AIR && current_node != CONTENT_IGNORE && - current_node != tree_definition.leavesnode.getContent() && - current_node != tree_definition.leaves2node.getContent() && - current_node != tree_definition.fruitnode.getContent()) + if (current_node != CONTENT_AIR && current_node != CONTENT_IGNORE + && current_node != tree_definition.leavesnode.getContent() + && current_node != tree_definition.leaves2node.getContent() + && current_node != tree_definition.fruitnode.getContent()) return; vmanip.m_data[vi] = tree_definition.trunknode; } -void tree_leaves_placement( - MMVManip &vmanip, v3f p0, PseudoRandom ps, TreeDef &tree_definition) + +void tree_leaves_placement(MMVManip &vmanip, v3f p0, + PseudoRandom ps, TreeDef &tree_definition) { MapNode leavesnode = tree_definition.leavesnode; if (ps.range(1, 100) > 100 - tree_definition.leaves2_chance) @@ -540,13 +566,12 @@ void tree_leaves_placement( if (!vmanip.m_area.contains(p1)) return; u32 vi = vmanip.m_area.index(p1); - if (vmanip.m_data[vi].getContent() != CONTENT_AIR && - vmanip.m_data[vi].getContent() != CONTENT_IGNORE) + if (vmanip.m_data[vi].getContent() != CONTENT_AIR + && vmanip.m_data[vi].getContent() != CONTENT_IGNORE) return; if (tree_definition.fruit_chance > 0) { if (ps.range(1, 100) > 100 - tree_definition.fruit_chance) - vmanip.m_data[vmanip.m_area.index(p1)] = - tree_definition.fruitnode; + vmanip.m_data[vmanip.m_area.index(p1)] = tree_definition.fruitnode; else vmanip.m_data[vmanip.m_area.index(p1)] = leavesnode; } else if (ps.range(1, 100) > 20) { @@ -554,8 +579,9 @@ void tree_leaves_placement( } } -void tree_single_leaves_placement( - MMVManip &vmanip, v3f p0, PseudoRandom ps, TreeDef &tree_definition) + +void tree_single_leaves_placement(MMVManip &vmanip, v3f p0, + PseudoRandom ps, TreeDef &tree_definition) { MapNode leavesnode = tree_definition.leavesnode; if (ps.range(1, 100) > 100 - tree_definition.leaves2_chance) @@ -564,36 +590,38 @@ void tree_single_leaves_placement( if (!vmanip.m_area.contains(p1)) return; u32 vi = vmanip.m_area.index(p1); - if (vmanip.m_data[vi].getContent() != CONTENT_AIR && - vmanip.m_data[vi].getContent() != CONTENT_IGNORE) + if (vmanip.m_data[vi].getContent() != CONTENT_AIR + && vmanip.m_data[vi].getContent() != CONTENT_IGNORE) return; vmanip.m_data[vmanip.m_area.index(p1)] = leavesnode; } + void tree_fruit_placement(MMVManip &vmanip, v3f p0, TreeDef &tree_definition) { v3s16 p1 = v3s16(myround(p0.X), myround(p0.Y), myround(p0.Z)); if (!vmanip.m_area.contains(p1)) return; u32 vi = vmanip.m_area.index(p1); - if (vmanip.m_data[vi].getContent() != CONTENT_AIR && - vmanip.m_data[vi].getContent() != CONTENT_IGNORE) + if (vmanip.m_data[vi].getContent() != CONTENT_AIR + && vmanip.m_data[vi].getContent() != CONTENT_IGNORE) return; vmanip.m_data[vmanip.m_area.index(p1)] = tree_definition.fruitnode; } + irr::core::matrix4 setRotationAxisRadians(irr::core::matrix4 M, double angle, v3f axis) { double c = cos(angle); double s = sin(angle); double t = 1.0 - c; - double tx = t * axis.X; - double ty = t * axis.Y; - double tz = t * axis.Z; - double sx = s * axis.X; - double sy = s * axis.Y; - double sz = s * axis.Z; + double tx = t * axis.X; + double ty = t * axis.Y; + double tz = t * axis.Z; + double sx = s * axis.X; + double sy = s * axis.Y; + double sz = s * axis.Z; M[0] = tx * axis.X + c; M[1] = tx * axis.Y + sz; @@ -603,64 +631,65 @@ irr::core::matrix4 setRotationAxisRadians(irr::core::matrix4 M, double angle, v3 M[5] = ty * axis.Y + c; M[6] = ty * axis.Z + sx; - M[8] = tz * axis.X + sy; - M[9] = tz * axis.Y - sx; + M[8] = tz * axis.X + sy; + M[9] = tz * axis.Y - sx; M[10] = tz * axis.Z + c; return M; } + v3f transposeMatrix(irr::core::matrix4 M, v3f v) { v3f translated; - double x = M[0] * v.X + M[4] * v.Y + M[8] * v.Z + M[12]; - double y = M[1] * v.X + M[5] * v.Y + M[9] * v.Z + M[13]; - double z = M[2] * v.X + M[6] * v.Y + M[10] * v.Z + M[14]; + double x = M[0] * v.X + M[4] * v.Y + M[8] * v.Z +M[12]; + double y = M[1] * v.X + M[5] * v.Y + M[9] * v.Z +M[13]; + double z = M[2] * v.X + M[6] * v.Y + M[10] * v.Z +M[14]; translated.X = x; translated.Y = y; translated.Z = z; return translated; } -void make_jungletree(MMVManip &vmanip, v3s16 p0, const NodeDefManager *ndef, s32 seed) + +void make_jungletree(MMVManip &vmanip, v3s16 p0, const NodeDefManager *ndef, + s32 seed) { /* NOTE: Tree-placing code is currently duplicated in the engine and in games that have saplings; both are deprecated but not replaced yet */ - content_t c_tree = ndef->getId("mapgen_jungletree"); + content_t c_tree = ndef->getId("mapgen_jungletree"); content_t c_leaves = ndef->getId("mapgen_jungleleaves"); if (c_tree == CONTENT_IGNORE) c_tree = ndef->getId("mapgen_tree"); if (c_leaves == CONTENT_IGNORE) c_leaves = ndef->getId("mapgen_leaves"); if (c_tree == CONTENT_IGNORE) - errorstream << "Treegen: Mapgen alias 'mapgen_jungletree' is invalid!" - << std::endl; + errorstream << "Treegen: Mapgen alias 'mapgen_jungletree' is invalid!" << std::endl; if (c_leaves == CONTENT_IGNORE) - errorstream << "Treegen: Mapgen alias 'mapgen_jungleleaves' is invalid!" - << std::endl; + errorstream << "Treegen: Mapgen alias 'mapgen_jungleleaves' is invalid!" << std::endl; MapNode treenode(c_tree); MapNode leavesnode(c_leaves); PseudoRandom pr(seed); - for (s16 x = -1; x <= 1; x++) - for (s16 z = -1; z <= 1; z++) { - if (pr.range(0, 2) == 0) - continue; - v3s16 p1 = p0 + v3s16(x, 0, z); - v3s16 p2 = p0 + v3s16(x, -1, z); - u32 vi1 = vmanip.m_area.index(p1); - u32 vi2 = vmanip.m_area.index(p2); - - if (vmanip.m_area.contains(p2) && - vmanip.m_data[vi2].getContent() == CONTENT_AIR) - vmanip.m_data[vi2] = treenode; - else if (vmanip.m_area.contains(p1) && - vmanip.m_data[vi1].getContent() == CONTENT_AIR) - vmanip.m_data[vi1] = treenode; - } + for (s16 x= -1; x <= 1; x++) + for (s16 z= -1; z <= 1; z++) { + if (pr.range(0, 2) == 0) + continue; + v3s16 p1 = p0 + v3s16(x, 0, z); + v3s16 p2 = p0 + v3s16(x, -1, z); + u32 vi1 = vmanip.m_area.index(p1); + u32 vi2 = vmanip.m_area.index(p2); + + if (vmanip.m_area.contains(p2) && + vmanip.m_data[vi2].getContent() == CONTENT_AIR) + vmanip.m_data[vi2] = treenode; + else if (vmanip.m_area.contains(p1) && + vmanip.m_data[vi1].getContent() == CONTENT_AIR) + vmanip.m_data[vi1] = treenode; + } vmanip.m_data[vmanip.m_area.index(p0)] = treenode; s16 trunk_h = pr.range(8, 12); @@ -677,7 +706,7 @@ void make_jungletree(MMVManip &vmanip, v3s16 p0, const NodeDefManager *ndef, s32 p1.Y -= 1; VoxelArea leaves_a(v3s16(-3, -2, -3), v3s16(3, 2, 3)); - // SharedPtr<u8> leaves_d(new u8[leaves_a.getVolume()]); + //SharedPtr<u8> leaves_d(new u8[leaves_a.getVolume()]); Buffer<u8> leaves_d(leaves_a.getVolume()); for (s32 i = 0; i < leaves_a.getVolume(); i++) leaves_d[i] = 0; @@ -685,54 +714,56 @@ void make_jungletree(MMVManip &vmanip, v3s16 p0, const NodeDefManager *ndef, s32 // Force leaves at near the end of the trunk s16 d = 1; for (s16 z = -d; z <= d; z++) - for (s16 y = -d; y <= d; y++) - for (s16 x = -d; x <= d; x++) { - leaves_d[leaves_a.index(v3s16(x, y, z))] = 1; - } + for (s16 y = -d; y <= d; y++) + for (s16 x = -d; x <= d; x++) { + leaves_d[leaves_a.index(v3s16(x,y,z))] = 1; + } // Add leaves randomly for (u32 iii = 0; iii < 30; iii++) { - v3s16 p(pr.range(leaves_a.MinEdge.X, leaves_a.MaxEdge.X - d), - pr.range(leaves_a.MinEdge.Y, leaves_a.MaxEdge.Y - d), - pr.range(leaves_a.MinEdge.Z, leaves_a.MaxEdge.Z - d)); + v3s16 p( + pr.range(leaves_a.MinEdge.X, leaves_a.MaxEdge.X - d), + pr.range(leaves_a.MinEdge.Y, leaves_a.MaxEdge.Y - d), + pr.range(leaves_a.MinEdge.Z, leaves_a.MaxEdge.Z - d) + ); for (s16 z = 0; z <= d; z++) - for (s16 y = 0; y <= d; y++) - for (s16 x = 0; x <= d; x++) { - leaves_d[leaves_a.index(p + v3s16(x, y, z))] = 1; - } + for (s16 y = 0; y <= d; y++) + for (s16 x = 0; x <= d; x++) { + leaves_d[leaves_a.index(p + v3s16(x, y, z))] = 1; + } } // Blit leaves to vmanip for (s16 z = leaves_a.MinEdge.Z; z <= leaves_a.MaxEdge.Z; z++) - for (s16 y = leaves_a.MinEdge.Y; y <= leaves_a.MaxEdge.Y; y++) { - v3s16 pmin(leaves_a.MinEdge.X, y, z); - u32 i = leaves_a.index(pmin); - u32 vi = vmanip.m_area.index(pmin + p1); - for (s16 x = leaves_a.MinEdge.X; x <= leaves_a.MaxEdge.X; x++) { - v3s16 p(x, y, z); - if (vmanip.m_area.contains(p + p1) && - (vmanip.m_data[vi].getContent() == - CONTENT_AIR || - vmanip.m_data[vi].getContent() == - CONTENT_IGNORE)) { - if (leaves_d[i] == 1) - vmanip.m_data[vi] = leavesnode; - } - vi++; - i++; + for (s16 y = leaves_a.MinEdge.Y; y <= leaves_a.MaxEdge.Y; y++) { + v3s16 pmin(leaves_a.MinEdge.X, y, z); + u32 i = leaves_a.index(pmin); + u32 vi = vmanip.m_area.index(pmin + p1); + for (s16 x = leaves_a.MinEdge.X; x <= leaves_a.MaxEdge.X; x++) { + v3s16 p(x, y, z); + if (vmanip.m_area.contains(p + p1) && + (vmanip.m_data[vi].getContent() == CONTENT_AIR || + vmanip.m_data[vi].getContent() == CONTENT_IGNORE)) { + if (leaves_d[i] == 1) + vmanip.m_data[vi] = leavesnode; } + vi++; + i++; } + } } -void make_pine_tree(MMVManip &vmanip, v3s16 p0, const NodeDefManager *ndef, s32 seed) + +void make_pine_tree(MMVManip &vmanip, v3s16 p0, const NodeDefManager *ndef, + s32 seed) { /* NOTE: Tree-placing code is currently duplicated in the engine and in games that have saplings; both are deprecated but not replaced yet */ - content_t c_tree = ndef->getId("mapgen_pine_tree"); + content_t c_tree = ndef->getId("mapgen_pine_tree"); content_t c_leaves = ndef->getId("mapgen_pine_needles"); content_t c_snow = ndef->getId("mapgen_snow"); if (c_tree == CONTENT_IGNORE) @@ -742,11 +773,9 @@ void make_pine_tree(MMVManip &vmanip, v3s16 p0, const NodeDefManager *ndef, s32 if (c_snow == CONTENT_IGNORE) c_snow = CONTENT_AIR; if (c_tree == CONTENT_IGNORE) - errorstream << "Treegen: Mapgen alias 'mapgen_pine_tree' is invalid!" - << std::endl; + errorstream << "Treegen: Mapgen alias 'mapgen_pine_tree' is invalid!" << std::endl; if (c_leaves == CONTENT_IGNORE) - errorstream << "Treegen: Mapgen alias 'mapgen_pine_needles' is invalid!" - << std::endl; + errorstream << "Treegen: Mapgen alias 'mapgen_pine_needles' is invalid!" << std::endl; MapNode treenode(c_tree); MapNode leavesnode(c_leaves); @@ -776,7 +805,7 @@ void make_pine_tree(MMVManip &vmanip, v3s16 p0, const NodeDefManager *ndef, s32 for (s16 yy = -1; yy <= 1; yy++) { for (s16 zz = -dev; zz <= dev; zz++) { u32 i = leaves_a.index(v3s16(-dev, yy, zz)); - u32 ia = leaves_a.index(v3s16(-dev, yy + 1, zz)); + u32 ia = leaves_a.index(v3s16(-dev, yy+1, zz)); for (s16 xx = -dev; xx <= dev; xx++) { if (pr.range(0, 20) <= 19 - dev) { leaves_d[i] = 1; @@ -834,28 +863,25 @@ void make_pine_tree(MMVManip &vmanip, v3s16 p0, const NodeDefManager *ndef, s32 // Blit leaves to vmanip for (s16 z = leaves_a.MinEdge.Z; z <= leaves_a.MaxEdge.Z; z++) - for (s16 y = leaves_a.MinEdge.Y; y <= leaves_a.MaxEdge.Y; y++) { - v3s16 pmin(leaves_a.MinEdge.X, y, z); - u32 i = leaves_a.index(pmin); - u32 vi = vmanip.m_area.index(pmin + p1); - for (s16 x = leaves_a.MinEdge.X; x <= leaves_a.MaxEdge.X; x++) { - v3s16 p(x, y, z); - if (vmanip.m_area.contains(p + p1) && - (vmanip.m_data[vi].getContent() == - CONTENT_AIR || - vmanip.m_data[vi].getContent() == - CONTENT_IGNORE || - vmanip.m_data[vi] == - snownode)) { - if (leaves_d[i] == 1) - vmanip.m_data[vi] = leavesnode; - else if (leaves_d[i] == 2) - vmanip.m_data[vi] = snownode; - } - vi++; - i++; + for (s16 y = leaves_a.MinEdge.Y; y <= leaves_a.MaxEdge.Y; y++) { + v3s16 pmin(leaves_a.MinEdge.X, y, z); + u32 i = leaves_a.index(pmin); + u32 vi = vmanip.m_area.index(pmin + p1); + for (s16 x = leaves_a.MinEdge.X; x <= leaves_a.MaxEdge.X; x++) { + v3s16 p(x, y, z); + if (vmanip.m_area.contains(p + p1) && + (vmanip.m_data[vi].getContent() == CONTENT_AIR || + vmanip.m_data[vi].getContent() == CONTENT_IGNORE || + vmanip.m_data[vi] == snownode)) { + if (leaves_d[i] == 1) + vmanip.m_data[vi] = leavesnode; + else if (leaves_d[i] == 2) + vmanip.m_data[vi] = snownode; } + vi++; + i++; } + } } }; // namespace treegen diff --git a/src/mapgen/treegen.h b/src/mapgen/treegen.h index f2ee36a4e..447baabb3 100644 --- a/src/mapgen/treegen.h +++ b/src/mapgen/treegen.h @@ -28,64 +28,66 @@ class MMVManip; class NodeDefManager; class ServerMap; -namespace treegen -{ - -enum error -{ - SUCCESS, - UNBALANCED_BRACKETS -}; - -struct TreeDef -{ - std::string initial_axiom; - std::string rules_a; - std::string rules_b; - std::string rules_c; - std::string rules_d; - - MapNode trunknode; - MapNode leavesnode; - MapNode leaves2node; - - int leaves2_chance; - int angle; - int iterations; - int iterations_random_level; - std::string trunk_type; - bool thin_branches; - MapNode fruitnode; - int fruit_chance; - s32 seed; - bool explicit_seed; -}; - -// Add default tree -void make_tree(MMVManip &vmanip, v3s16 p0, bool is_apple_tree, const NodeDefManager *ndef, - s32 seed); -// Add jungle tree -void make_jungletree(MMVManip &vmanip, v3s16 p0, const NodeDefManager *ndef, s32 seed); -// Add pine tree -void make_pine_tree(MMVManip &vmanip, v3s16 p0, const NodeDefManager *ndef, s32 seed); - -// Add L-Systems tree (used by engine) -treegen::error make_ltree(MMVManip &vmanip, v3s16 p0, const NodeDefManager *ndef, - TreeDef tree_definition); -// Spawn L-systems tree from LUA -treegen::error spawn_ltree(ServerMap *map, v3s16 p0, const NodeDefManager *ndef, - const TreeDef &tree_definition); - -// L-System tree gen helper functions -void tree_node_placement(MMVManip &vmanip, v3f p0, MapNode node); -void tree_trunk_placement(MMVManip &vmanip, v3f p0, TreeDef &tree_definition); -void tree_leaves_placement( - MMVManip &vmanip, v3f p0, PseudoRandom ps, TreeDef &tree_definition); -void tree_single_leaves_placement( - MMVManip &vmanip, v3f p0, PseudoRandom ps, TreeDef &tree_definition); -void tree_fruit_placement(MMVManip &vmanip, v3f p0, TreeDef &tree_definition); -irr::core::matrix4 setRotationAxisRadians(irr::core::matrix4 M, double angle, v3f axis); - -v3f transposeMatrix(irr::core::matrix4 M, v3f v); +namespace treegen { + + enum error { + SUCCESS, + UNBALANCED_BRACKETS + }; + + struct TreeDef { + std::string initial_axiom; + std::string rules_a; + std::string rules_b; + std::string rules_c; + std::string rules_d; + + MapNode trunknode; + MapNode leavesnode; + MapNode leaves2node; + + int leaves2_chance; + int angle; + int iterations; + int iterations_random_level; + std::string trunk_type; + bool thin_branches; + MapNode fruitnode; + int fruit_chance; + s32 seed; + bool explicit_seed; + }; + + // Add default tree + void make_tree(MMVManip &vmanip, v3s16 p0, + bool is_apple_tree, const NodeDefManager *ndef, s32 seed); + // Add jungle tree + void make_jungletree(MMVManip &vmanip, v3s16 p0, + const NodeDefManager *ndef, s32 seed); + // Add pine tree + void make_pine_tree(MMVManip &vmanip, v3s16 p0, + const NodeDefManager *ndef, s32 seed); + + // Add L-Systems tree (used by engine) + treegen::error make_ltree(MMVManip &vmanip, v3s16 p0, + const NodeDefManager *ndef, TreeDef tree_definition); + // Spawn L-systems tree from LUA + treegen::error spawn_ltree (ServerMap *map, v3s16 p0, + const NodeDefManager *ndef, const TreeDef &tree_definition); + + // L-System tree gen helper functions + void tree_node_placement(MMVManip &vmanip, v3f p0, + MapNode node); + void tree_trunk_placement(MMVManip &vmanip, v3f p0, + TreeDef &tree_definition); + void tree_leaves_placement(MMVManip &vmanip, v3f p0, + PseudoRandom ps, TreeDef &tree_definition); + void tree_single_leaves_placement(MMVManip &vmanip, v3f p0, + PseudoRandom ps, TreeDef &tree_definition); + void tree_fruit_placement(MMVManip &vmanip, v3f p0, + TreeDef &tree_definition); + irr::core::matrix4 setRotationAxisRadians(irr::core::matrix4 M, double angle, v3f axis); + + v3f transposeMatrix(irr::core::matrix4 M ,v3f v); }; // namespace treegen |