diff --git a/doc/lua_api.txt b/doc/lua_api.txt index beb70db15..ca00fc1f9 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -394,6 +394,13 @@ All default ores are of the uniformly-distributed scatter type. Places ore if there are no more than clust_scarcity number of specified nodes within a Von Neumann neighborhood of clust_size radius. +Ore attributes +------------------- +Currently supported flags: absheight + - absheight + Also produce this same ore between the height range of -height_max and -height_min. + Useful for having ore in sky realms without having to duplicate ore entries. + Representations of simple things -------------------------------- Position/vector: @@ -1723,6 +1730,8 @@ Ore definition (register_ore) ^ In this example, there is a 3x3x3 cluster where 8 out of the 27 nodes are coal ore height_min = -31000, height_max = 64, + flags = "", + ^ Attributes for this ore generation noise_threshhold = 0.5, ^ If noise is above this threshhold, ore is placed. Not needed for a uniform distribution noise_params = {offset=0, scale=1, spread={x=100, y=100, z=100}, seed=23, octaves=3, persist=0.70} diff --git a/src/mapgen.cpp b/src/mapgen.cpp index b5deaae52..64c1886b3 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -42,7 +42,14 @@ FlagDesc flagdesc_mapgen[] = { {"v6_jungles", MGV6_JUNGLES}, {"v6_biome_blend", MGV6_BIOME_BLEND}, {"flat", MG_FLAT}, - {NULL, 0} + {NULL, 0} +}; + +FlagDesc flagdesc_ore[] = { + {"absheight", OREFLAG_ABSHEIGHT}, + {"scatter_noisedensity", OREFLAG_DENSITY}, + {"claylike_nodeisnt", OREFLAG_NODEISNT}, + {NULL, 0} }; @@ -87,17 +94,28 @@ void Ore::resolveNodeNames(INodeDefManager *ndef) { void OreScatter::generate(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) { - if (nmin.Y > height_max || nmax.Y < height_min) + int in_range = 0; + + in_range |= (nmin.Y <= height_max && nmax.Y >= height_min); + if (flags & OREFLAG_ABSHEIGHT) + in_range |= (nmin.Y >= -height_max && nmax.Y <= -height_min) << 1; + if (!in_range) return; - + resolveNodeNames(mg->ndef); MapNode n_ore(ore); ManualMapVoxelManipulator *vm = mg->vm; PseudoRandom pr(blockseed); + int ymin, ymax; - int ymin = MYMAX(nmin.Y, height_min); - int ymax = MYMIN(nmax.Y, height_max); + if (in_range & ORE_RANGE_MIRROR) { + ymin = MYMAX(nmin.Y, -height_max); + ymax = MYMIN(nmax.Y, -height_min); + } else { + ymin = MYMAX(nmin.Y, height_min); + ymax = MYMIN(nmax.Y, height_max); + } if (clust_size >= ymax - ymin + 1) return; @@ -131,17 +149,29 @@ void OreScatter::generate(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) { void OreSheet::generate(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) { - if (nmin.Y > height_max || nmax.Y < height_min) - return; + int in_range = 0; + in_range |= (nmin.Y <= height_max && nmax.Y >= height_min); + if (flags & OREFLAG_ABSHEIGHT) + in_range |= (nmin.Y >= -height_max && nmax.Y <= -height_min) << 1; + if (!in_range) + return; + resolveNodeNames(mg->ndef); MapNode n_ore(ore); ManualMapVoxelManipulator *vm = mg->vm; PseudoRandom pr(blockseed + 4234); + int ymin, ymax; - int ymin = MYMAX(nmin.Y, height_min); - int ymax = MYMIN(nmax.Y, height_max); + if (in_range & ORE_RANGE_MIRROR) { + ymin = MYMAX(nmin.Y, -height_max); + ymax = MYMIN(nmax.Y, -height_min); + } else { + ymin = MYMAX(nmin.Y, height_min); + ymax = MYMIN(nmax.Y, height_max); + } + if (clust_size >= ymax - ymin + 1) return; diff --git a/src/mapgen.h b/src/mapgen.h index ee8a8c20c..e708f23b1 100644 --- a/src/mapgen.h +++ b/src/mapgen.h @@ -36,7 +36,17 @@ with this program; if not, write to the Free Software Foundation, Inc., #define MGV6_BIOME_BLEND 0x10 #define MG_FLAT 0x20 +/////////////////// Ore generation flags +// Use absolute value of height to determine ore placement +#define OREFLAG_ABSHEIGHT 0x01 +// Use 3d noise to get density of ore placement, instead of just the position +#define OREFLAG_DENSITY 0x02 // not yet implemented +// For claylike ore types, place ore if the number of surrounding +// nodes isn't the specified node +#define OREFLAG_NODEISNT 0x04 // not yet implemented + extern FlagDesc flagdesc_mapgen[]; +extern FlagDesc flagdesc_ore[]; class BiomeDefManager; class Biome; @@ -103,6 +113,9 @@ enum OreType { ORE_CLAYLIKE }; +#define ORE_RANGE_ACTUAL 1 +#define ORE_RANGE_MIRROR 2 + class Ore { public: std::string ore_name; @@ -115,6 +128,7 @@ public: s16 clust_size; // how large (in nodes) a chunk of ore is s16 height_min; s16 height_max; + u32 flags; // attributes for this ore float nthresh; // threshhold for noise at which an ore is placed NoiseParams *np; // noise for distribution of clusters (NULL for uniform scattering) Noise *noise; diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index 81fcc08d3..c372456d4 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -717,6 +717,7 @@ static int l_register_ore(lua_State *L) ore->clust_size = getintfield_default(L, index, "clust_size", 0); ore->height_min = getintfield_default(L, index, "height_min", 0); ore->height_max = getintfield_default(L, index, "height_max", 0); + ore->flags = getflagsfield(L, index, "flags", flagdesc_ore); ore->nthresh = getfloatfield_default(L, index, "noise_threshhold", 0.); lua_getfield(L, index, "noise_params"); diff --git a/src/scriptapi_types.cpp b/src/scriptapi_types.cpp index 3d06f1623..01a9b3bc3 100644 --- a/src/scriptapi_types.cpp +++ b/src/scriptapi_types.cpp @@ -336,6 +336,13 @@ void setboolfield(lua_State *L, int table, lua_setfield(L, table, fieldname); } +u32 getflagsfield(lua_State *L, int table, + const char *fieldname, FlagDesc *flagdesc) { + std::string flagstring; + + flagstring = getstringfield_default(L, table, fieldname, ""); + return readFlagString(flagstring, flagdesc); +} /* minetest specific types */ MapNode readnode(lua_State *L, int index, INodeDefManager *ndef) diff --git a/src/scriptapi_types.h b/src/scriptapi_types.h index e3a611a9d..1eeed66df 100644 --- a/src/scriptapi_types.h +++ b/src/scriptapi_types.h @@ -51,6 +51,8 @@ bool getboolfield(lua_State *L, int table, const char *fieldname, bool &result); bool getfloatfield(lua_State *L, int table, const char *fieldname, float &result); +u32 getflagsfield(lua_State *L, int table, + const char *fieldname, FlagDesc *flagdesc); std::string checkstringfield(lua_State *L, int table, const char *fieldname);