diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 13227260c..a6d02ebb5 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1069,7 +1069,6 @@ within the currently generated chunk. The vertical top and bottom displacement of each puff are determined by the noise parameters `np_puff_top` and `np_puff_bottom`, respectively. - ### `blob` Creates a deformed sphere of ore according to 3d perlin noise described by `noise_params`. The maximum size of the blob is `clust_size`, and @@ -1099,6 +1098,22 @@ to small changes. The following is a decent set of parameters to work from: **WARNING**: Use this ore type *very* sparingly since it is ~200x more computationally expensive than any other ore. +### `stratum` +Creates a single undulating ore stratum that is continuous across mapchunk +borders and horizontally spans the world. +The 2D perlin noise described by `noise_params` varies the Y co-ordinate of the +stratum midpoint. The 2D perlin noise described by `np_stratum_thickness` +varies the stratum's vertical thickness (in units of nodes). Due to being +continuous across mapchunk borders the stratum's vertical thickness is +unlimited. +`y_min` and `y_max` define the limits of the ore generation and for performance +reasons should be set as close together as possible but without clipping the +stratum's Y variation. +Each node in the stratum has a 1-in-`clust_scarcity` chance of being ore, so a +solid-ore stratum would require a `clust_scarcity` of 1. +The parameters `clust_num_ores`, `clust_size`, `noise_threshold` and +`random_factor` are ignored by this ore type. + Ore attributes -------------- See section "Flag Specifier Format". @@ -4558,6 +4573,8 @@ Definition tables { ore_type = "scatter", -- See "Ore types" ore = "default:stone_with_coal", + ore_param2 = 3, + -- ^ Facedir rotation. Default is 0 (unchanged rotation) wherein = "default:stone", -- ^ a list of nodenames is supported too clust_scarcity = 8*8*8, diff --git a/src/mg_ore.cpp b/src/mg_ore.cpp index 5f11dda92..54e332116 100644 --- a/src/mg_ore.cpp +++ b/src/mg_ore.cpp @@ -74,6 +74,7 @@ void OreManager::clear() /////////////////////////////////////////////////////////////////////////////// + Ore::~Ore() { delete noise; @@ -221,6 +222,8 @@ void OreSheet::generate(MMVManip *vm, int mapseed, u32 blockseed, /////////////////////////////////////////////////////////////////////////////// + + OrePuff::~OrePuff() { delete noise_puff_top; @@ -365,6 +368,8 @@ void OreBlob::generate(MMVManip *vm, int mapseed, u32 blockseed, /////////////////////////////////////////////////////////////////////////////// + + OreVein::~OreVein() { delete noise2; @@ -422,3 +427,58 @@ void OreVein::generate(MMVManip *vm, int mapseed, u32 blockseed, vm->m_data[i] = n_ore; } } + + +/////////////////////////////////////////////////////////////////////////////// + + +OreStratum::~OreStratum() +{ + delete noise_stratum_thickness; +} + + +void OreStratum::generate(MMVManip *vm, int mapseed, u32 blockseed, + v3s16 nmin, v3s16 nmax, u8 *biomemap) +{ + PcgRandom pr(blockseed + 4234); + MapNode n_ore(c_ore, 0, ore_param2); + + if (!noise) { + int sx = nmax.X - nmin.X + 1; + int sz = nmax.Z - nmin.Z + 1; + noise = new Noise(&np, 0, sx, sz); + noise_stratum_thickness = new Noise(&np_stratum_thickness, 0, sx, sz); + } + noise->perlinMap2D(nmin.X, nmin.Z); + noise_stratum_thickness->perlinMap2D(nmin.X, nmin.Z); + + 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()) { + std::unordered_set::const_iterator it = biomes.find(biomemap[index]); + if (it == biomes.end()) + continue; + } + + float nmid = noise->result[index]; + float nhalfthick = noise_stratum_thickness->result[index] / 2.0f; + int y0 = MYMAX(nmin.Y, nmid - nhalfthick); + int y1 = MYMIN(nmax.Y, nmid + nhalfthick); + + 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; + + vm->m_data[i] = n_ore; + } + } +} diff --git a/src/mg_ore.h b/src/mg_ore.h index 253b115a2..b4309f2f9 100644 --- a/src/mg_ore.h +++ b/src/mg_ore.h @@ -42,6 +42,7 @@ enum OreType { ORE_PUFF, ORE_BLOB, ORE_VEIN, + ORE_STRATUM, }; extern FlagDesc flagdesc_ore[]; @@ -133,6 +134,20 @@ public: v3s16 nmin, v3s16 nmax, u8 *biomemap); }; +class OreStratum : public Ore { +public: + static const bool NEEDS_NOISE = true; + + NoiseParams np_stratum_thickness; + Noise *noise_stratum_thickness = nullptr; + + OreStratum() = default; + virtual ~OreStratum(); + + virtual void generate(MMVManip *vm, int mapseed, u32 blockseed, + v3s16 nmin, v3s16 nmax, u8 *biomemap); +}; + class OreManager : public ObjDefManager { public: OreManager(IGameDef *gamedef); @@ -156,6 +171,8 @@ public: return new OreBlob; case ORE_VEIN: return new OreVein; + case ORE_STRATUM: + return new OreStratum; default: return nullptr; } diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp index 0875e2c95..c2b256228 100644 --- a/src/script/lua_api/l_mapgen.cpp +++ b/src/script/lua_api/l_mapgen.cpp @@ -73,6 +73,7 @@ struct EnumString ModApiMapgen::es_OreType[] = {ORE_PUFF, "puff"}, {ORE_BLOB, "blob"}, {ORE_VEIN, "vein"}, + {ORE_STRATUM, "stratum"}, {0, NULL}, }; @@ -1149,6 +1150,15 @@ int ModApiMapgen::l_register_ore(lua_State *L) break; } + case ORE_STRATUM: { + OreStratum *orestratum = (OreStratum *)ore; + + lua_getfield(L, index, "np_stratum_thickness"); + read_noiseparams(L, -1, &orestratum->np_stratum_thickness); + lua_pop(L, 1); + + break; + } default: break; }