mapgen_v5.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. /*
  2. Minetest
  3. Copyright (C) 2014-2018 paramat
  4. Copyright (C) 2014-2018 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU Lesser General Public License as published by
  7. the Free Software Foundation; either version 2.1 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public License along
  14. with this program; if not, write to the Free Software Foundation, Inc.,
  15. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  16. */
  17. #include "mapgen.h"
  18. #include "voxel.h"
  19. #include "noise.h"
  20. #include "mapblock.h"
  21. #include "mapnode.h"
  22. #include "map.h"
  23. #include "nodedef.h"
  24. #include "voxelalgorithms.h"
  25. //#include "profiler.h" // For TimeTaker
  26. #include "settings.h" // For g_settings
  27. #include "emerge.h"
  28. #include "dungeongen.h"
  29. #include "cavegen.h"
  30. #include "mg_biome.h"
  31. #include "mg_ore.h"
  32. #include "mg_decoration.h"
  33. #include "mapgen_v5.h"
  34. FlagDesc flagdesc_mapgen_v5[] = {
  35. {"caverns", MGV5_CAVERNS},
  36. {NULL, 0}
  37. };
  38. MapgenV5::MapgenV5(MapgenV5Params *params, EmergeParams *emerge)
  39. : MapgenBasic(MAPGEN_V5, params, emerge)
  40. {
  41. spflags = params->spflags;
  42. cave_width = params->cave_width;
  43. large_cave_depth = params->large_cave_depth;
  44. small_cave_num_min = params->small_cave_num_min;
  45. small_cave_num_max = params->small_cave_num_max;
  46. large_cave_num_min = params->large_cave_num_min;
  47. large_cave_num_max = params->large_cave_num_max;
  48. large_cave_flooded = params->large_cave_flooded;
  49. cavern_limit = params->cavern_limit;
  50. cavern_taper = params->cavern_taper;
  51. cavern_threshold = params->cavern_threshold;
  52. dungeon_ymin = params->dungeon_ymin;
  53. dungeon_ymax = params->dungeon_ymax;
  54. // Terrain noise
  55. noise_filler_depth = new Noise(&params->np_filler_depth, seed, csize.X, csize.Z);
  56. noise_factor = new Noise(&params->np_factor, seed, csize.X, csize.Z);
  57. noise_height = new Noise(&params->np_height, seed, csize.X, csize.Z);
  58. // 3D terrain noise
  59. // 1-up 1-down overgeneration
  60. noise_ground = new Noise(&params->np_ground, seed, csize.X, csize.Y + 2, csize.Z);
  61. // 1 down overgeneration
  62. MapgenBasic::np_cave1 = params->np_cave1;
  63. MapgenBasic::np_cave2 = params->np_cave2;
  64. MapgenBasic::np_cavern = params->np_cavern;
  65. MapgenBasic::np_dungeons = params->np_dungeons;
  66. }
  67. MapgenV5::~MapgenV5()
  68. {
  69. delete noise_filler_depth;
  70. delete noise_factor;
  71. delete noise_height;
  72. delete noise_ground;
  73. }
  74. MapgenV5Params::MapgenV5Params():
  75. np_filler_depth (0, 1, v3f(150, 150, 150), 261, 4, 0.7, 2.0),
  76. np_factor (0, 1, v3f(250, 250, 250), 920381, 3, 0.45, 2.0),
  77. np_height (0, 10, v3f(250, 250, 250), 84174, 4, 0.5, 2.0),
  78. np_ground (0, 40, v3f(80, 80, 80), 983240, 4, 0.55, 2.0, NOISE_FLAG_EASED),
  79. np_cave1 (0, 12, v3f(61, 61, 61), 52534, 3, 0.5, 2.0),
  80. np_cave2 (0, 12, v3f(67, 67, 67), 10325, 3, 0.5, 2.0),
  81. np_cavern (0, 1, v3f(384, 128, 384), 723, 5, 0.63, 2.0),
  82. np_dungeons (0.9, 0.5, v3f(500, 500, 500), 0, 2, 0.8, 2.0)
  83. {
  84. }
  85. void MapgenV5Params::readParams(const Settings *settings)
  86. {
  87. settings->getFlagStrNoEx("mgv5_spflags", spflags, flagdesc_mapgen_v5);
  88. settings->getFloatNoEx("mgv5_cave_width", cave_width);
  89. settings->getS16NoEx("mgv5_large_cave_depth", large_cave_depth);
  90. settings->getU16NoEx("mgv5_small_cave_num_min", small_cave_num_min);
  91. settings->getU16NoEx("mgv5_small_cave_num_max", small_cave_num_max);
  92. settings->getU16NoEx("mgv5_large_cave_num_min", large_cave_num_min);
  93. settings->getU16NoEx("mgv5_large_cave_num_max", large_cave_num_max);
  94. settings->getFloatNoEx("mgv5_large_cave_flooded", large_cave_flooded);
  95. settings->getS16NoEx("mgv5_cavern_limit", cavern_limit);
  96. settings->getS16NoEx("mgv5_cavern_taper", cavern_taper);
  97. settings->getFloatNoEx("mgv5_cavern_threshold", cavern_threshold);
  98. settings->getS16NoEx("mgv5_dungeon_ymin", dungeon_ymin);
  99. settings->getS16NoEx("mgv5_dungeon_ymax", dungeon_ymax);
  100. settings->getNoiseParams("mgv5_np_filler_depth", np_filler_depth);
  101. settings->getNoiseParams("mgv5_np_factor", np_factor);
  102. settings->getNoiseParams("mgv5_np_height", np_height);
  103. settings->getNoiseParams("mgv5_np_ground", np_ground);
  104. settings->getNoiseParams("mgv5_np_cave1", np_cave1);
  105. settings->getNoiseParams("mgv5_np_cave2", np_cave2);
  106. settings->getNoiseParams("mgv5_np_cavern", np_cavern);
  107. settings->getNoiseParams("mgv5_np_dungeons", np_dungeons);
  108. }
  109. void MapgenV5Params::writeParams(Settings *settings) const
  110. {
  111. settings->setFlagStr("mgv5_spflags", spflags, flagdesc_mapgen_v5);
  112. settings->setFloat("mgv5_cave_width", cave_width);
  113. settings->setS16("mgv5_large_cave_depth", large_cave_depth);
  114. settings->setU16("mgv5_small_cave_num_min", small_cave_num_min);
  115. settings->setU16("mgv5_small_cave_num_max", small_cave_num_max);
  116. settings->setU16("mgv5_large_cave_num_min", large_cave_num_min);
  117. settings->setU16("mgv5_large_cave_num_max", large_cave_num_max);
  118. settings->setFloat("mgv5_large_cave_flooded", large_cave_flooded);
  119. settings->setS16("mgv5_cavern_limit", cavern_limit);
  120. settings->setS16("mgv5_cavern_taper", cavern_taper);
  121. settings->setFloat("mgv5_cavern_threshold", cavern_threshold);
  122. settings->setS16("mgv5_dungeon_ymin", dungeon_ymin);
  123. settings->setS16("mgv5_dungeon_ymax", dungeon_ymax);
  124. settings->setNoiseParams("mgv5_np_filler_depth", np_filler_depth);
  125. settings->setNoiseParams("mgv5_np_factor", np_factor);
  126. settings->setNoiseParams("mgv5_np_height", np_height);
  127. settings->setNoiseParams("mgv5_np_ground", np_ground);
  128. settings->setNoiseParams("mgv5_np_cave1", np_cave1);
  129. settings->setNoiseParams("mgv5_np_cave2", np_cave2);
  130. settings->setNoiseParams("mgv5_np_cavern", np_cavern);
  131. settings->setNoiseParams("mgv5_np_dungeons", np_dungeons);
  132. }
  133. void MapgenV5Params::setDefaultSettings(Settings *settings)
  134. {
  135. settings->setDefault("mgv5_spflags", flagdesc_mapgen_v5, MGV5_CAVERNS);
  136. }
  137. /////////////////////////////////////////////////////////////////
  138. int MapgenV5::getSpawnLevelAtPoint(v2s16 p)
  139. {
  140. float f = 0.55 + NoisePerlin2D(&noise_factor->np, p.X, p.Y, seed);
  141. if (f < 0.01)
  142. f = 0.01;
  143. else if (f >= 1.0)
  144. f *= 1.6;
  145. float h = NoisePerlin2D(&noise_height->np, p.X, p.Y, seed);
  146. // noise_height 'offset' is the average level of terrain. At least 50% of
  147. // terrain will be below this.
  148. // Raising the maximum spawn level above 'water_level + 16' is necessary
  149. // for when noise_height 'offset' is set much higher than water_level.
  150. s16 max_spawn_y = MYMAX(noise_height->np.offset, water_level + 16);
  151. // Starting spawn search at max_spawn_y + 128 ensures 128 nodes of open
  152. // space above spawn position. Avoids spawning in possibly sealed voids.
  153. for (s16 y = max_spawn_y + 128; y >= water_level; y--) {
  154. float n_ground = NoisePerlin3D(&noise_ground->np, p.X, y, p.Y, seed);
  155. if (n_ground * f > y - h) { // If solid
  156. if (y < water_level || y > max_spawn_y)
  157. return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
  158. // y + 2 because y is surface and due to biome 'dust' nodes.
  159. return y + 2;
  160. }
  161. }
  162. // Unsuitable spawn position, no ground found
  163. return MAX_MAP_GENERATION_LIMIT;
  164. }
  165. void MapgenV5::makeChunk(BlockMakeData *data)
  166. {
  167. // Pre-conditions
  168. assert(data->vmanip);
  169. assert(data->nodedef);
  170. this->generating = true;
  171. this->vm = data->vmanip;
  172. this->ndef = data->nodedef;
  173. //TimeTaker t("makeChunk");
  174. v3s16 blockpos_min = data->blockpos_min;
  175. v3s16 blockpos_max = data->blockpos_max;
  176. node_min = blockpos_min * MAP_BLOCKSIZE;
  177. node_max = (blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
  178. full_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE;
  179. full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
  180. // Create a block-specific seed
  181. blockseed = getBlockSeed2(full_node_min, seed);
  182. // Generate base terrain
  183. s16 stone_surface_max_y = generateBaseTerrain();
  184. // Create heightmap
  185. updateHeightmap(node_min, node_max);
  186. // Init biome generator, place biome-specific nodes, and build biomemap
  187. if (flags & MG_BIOMES) {
  188. biomegen->calcBiomeNoise(node_min);
  189. generateBiomes();
  190. }
  191. // Generate tunnels, caverns and large randomwalk caves
  192. if (flags & MG_CAVES) {
  193. // Generate tunnels first as caverns confuse them
  194. generateCavesNoiseIntersection(stone_surface_max_y);
  195. // Generate caverns
  196. bool near_cavern = false;
  197. if (spflags & MGV5_CAVERNS)
  198. near_cavern = generateCavernsNoise(stone_surface_max_y);
  199. // Generate large randomwalk caves
  200. if (near_cavern)
  201. // Disable large randomwalk caves in this mapchunk by setting
  202. // 'large cave depth' to world base. Avoids excessive liquid in
  203. // large caverns and floating blobs of overgenerated liquid.
  204. generateCavesRandomWalk(stone_surface_max_y,
  205. -MAX_MAP_GENERATION_LIMIT);
  206. else
  207. generateCavesRandomWalk(stone_surface_max_y, large_cave_depth);
  208. }
  209. // Generate the registered ores
  210. if (flags & MG_ORES)
  211. m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
  212. // Generate dungeons and desert temples
  213. if (flags & MG_DUNGEONS)
  214. generateDungeons(stone_surface_max_y);
  215. // Generate the registered decorations
  216. if (flags & MG_DECORATIONS)
  217. m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
  218. // Sprinkle some dust on top after everything else was generated
  219. if (flags & MG_BIOMES)
  220. dustTopNodes();
  221. //printf("makeChunk: %dms\n", t.stop());
  222. // Add top and bottom side of water to transforming_liquid queue
  223. updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);
  224. // Calculate lighting
  225. if (flags & MG_LIGHT) {
  226. calcLighting(node_min - v3s16(0, 1, 0), node_max + v3s16(0, 1, 0),
  227. full_node_min, full_node_max);
  228. }
  229. this->generating = false;
  230. }
  231. int MapgenV5::generateBaseTerrain()
  232. {
  233. u32 index = 0;
  234. u32 index2d = 0;
  235. int stone_surface_max_y = -MAX_MAP_GENERATION_LIMIT;
  236. noise_factor->perlinMap2D(node_min.X, node_min.Z);
  237. noise_height->perlinMap2D(node_min.X, node_min.Z);
  238. noise_ground->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
  239. for (s16 z=node_min.Z; z<=node_max.Z; z++) {
  240. for (s16 y=node_min.Y - 1; y<=node_max.Y + 1; y++) {
  241. u32 vi = vm->m_area.index(node_min.X, y, z);
  242. for (s16 x=node_min.X; x<=node_max.X; x++, vi++, index++, index2d++) {
  243. if (vm->m_data[vi].getContent() != CONTENT_IGNORE)
  244. continue;
  245. float f = 0.55 + noise_factor->result[index2d];
  246. if (f < 0.01)
  247. f = 0.01;
  248. else if (f >= 1.0)
  249. f *= 1.6;
  250. float h = noise_height->result[index2d];
  251. if (noise_ground->result[index] * f < y - h) {
  252. if (y <= water_level)
  253. vm->m_data[vi] = MapNode(c_water_source);
  254. else
  255. vm->m_data[vi] = MapNode(CONTENT_AIR);
  256. } else {
  257. vm->m_data[vi] = MapNode(c_stone);
  258. if (y > stone_surface_max_y)
  259. stone_surface_max_y = y;
  260. }
  261. }
  262. index2d -= ystride;
  263. }
  264. index2d += ystride;
  265. }
  266. return stone_surface_max_y;
  267. }