mapgen_v6.cpp 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027
  1. /*
  2. Minetest
  3. Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. #include "mapgen.h"
  17. #include "voxel.h"
  18. #include "noise.h"
  19. #include "mapblock.h"
  20. #include "mapnode.h"
  21. #include "map.h"
  22. //#include "serverobject.h"
  23. #include "content_sao.h"
  24. #include "nodedef.h"
  25. #include "content_mapnode.h" // For content_mapnode_get_new_name
  26. #include "voxelalgorithms.h"
  27. #include "profiler.h"
  28. #include "settings.h" // For g_settings
  29. #include "main.h" // For g_profiler
  30. #include "emerge.h"
  31. #include "dungeongen.h"
  32. #include "cavegen.h"
  33. #include "treegen.h"
  34. #include "mapgen_v6.h"
  35. FlagDesc flagdesc_mapgen_v6[] = {
  36. {"jungles", MGV6_JUNGLES},
  37. {"biomeblend", MGV6_BIOMEBLEND},
  38. {"mudflow", MGV6_MUDFLOW},
  39. {NULL, 0}
  40. };
  41. ///////////////////////////////////////////////////////////////////////////////
  42. MapgenV6::MapgenV6(int mapgenid, MapgenParams *params, EmergeManager *emerge) {
  43. this->generating = false;
  44. this->id = mapgenid;
  45. this->emerge = emerge;
  46. this->seed = (int)params->seed;
  47. this->water_level = params->water_level;
  48. this->flags = params->flags;
  49. this->csize = v3s16(1, 1, 1) * params->chunksize * MAP_BLOCKSIZE;
  50. this->gennotify = emerge->gennotify;
  51. this->ystride = csize.X; //////fix this
  52. MapgenV6Params *sp = (MapgenV6Params *)params->sparams;
  53. this->spflags = sp->spflags;
  54. this->freq_desert = sp->freq_desert;
  55. this->freq_beach = sp->freq_beach;
  56. np_cave = &sp->np_cave;
  57. np_humidity = &sp->np_humidity;
  58. np_trees = &sp->np_trees;
  59. np_apple_trees = &sp->np_apple_trees;
  60. noise_terrain_base = new Noise(&sp->np_terrain_base, seed, csize.X, csize.Y);
  61. noise_terrain_higher = new Noise(&sp->np_terrain_higher, seed, csize.X, csize.Y);
  62. noise_steepness = new Noise(&sp->np_steepness, seed, csize.X, csize.Y);
  63. noise_height_select = new Noise(&sp->np_height_select, seed, csize.X, csize.Y);
  64. noise_mud = new Noise(&sp->np_mud, seed, csize.X, csize.Y);
  65. noise_beach = new Noise(&sp->np_beach, seed, csize.X, csize.Y);
  66. noise_biome = new Noise(&sp->np_biome, seed, csize.X, csize.Y);
  67. }
  68. MapgenV6::~MapgenV6() {
  69. delete noise_terrain_base;
  70. delete noise_terrain_higher;
  71. delete noise_steepness;
  72. delete noise_height_select;
  73. delete noise_mud;
  74. delete noise_beach;
  75. delete noise_biome;
  76. }
  77. MapgenV6Params::MapgenV6Params() {
  78. spflags = MGV6_BIOMEBLEND | MGV6_MUDFLOW;
  79. freq_desert = 0.45;
  80. freq_beach = 0.15;
  81. np_terrain_base = NoiseParams(-4, 20.0, v3f(250.0, 250.0, 250.0), 82341, 5, 0.6);
  82. np_terrain_higher = NoiseParams(20, 16.0, v3f(500.0, 500.0, 500.0), 85039, 5, 0.6);
  83. np_steepness = NoiseParams(0.85,0.5, v3f(125.0, 125.0, 125.0), -932, 5, 0.7);
  84. np_height_select = NoiseParams(0.5, 1.0, v3f(250.0, 250.0, 250.0), 4213, 5, 0.69);
  85. np_mud = NoiseParams(4, 2.0, v3f(200.0, 200.0, 200.0), 91013, 3, 0.55);
  86. np_beach = NoiseParams(0, 1.0, v3f(250.0, 250.0, 250.0), 59420, 3, 0.50);
  87. np_biome = NoiseParams(0, 1.0, v3f(250.0, 250.0, 250.0), 9130, 3, 0.50);
  88. np_cave = NoiseParams(6, 6.0, v3f(250.0, 250.0, 250.0), 34329, 3, 0.50);
  89. np_humidity = NoiseParams(0.5, 0.5, v3f(500.0, 500.0, 500.0), 72384, 4, 0.66);
  90. np_trees = NoiseParams(0, 1.0, v3f(125.0, 125.0, 125.0), 2, 4, 0.66);
  91. np_apple_trees = NoiseParams(0, 1.0, v3f(100.0, 100.0, 100.0), 342902, 3, 0.45);
  92. }
  93. void MapgenV6Params::readParams(Settings *settings) {
  94. settings->getFlagStrNoEx("mgv6_spflags", spflags, flagdesc_mapgen_v6);
  95. settings->getFloatNoEx("mgv6_freq_desert", freq_desert);
  96. settings->getFloatNoEx("mgv6_freq_beach", freq_beach);
  97. settings->getNoiseParams("mgv6_np_terrain_base", np_terrain_base);
  98. settings->getNoiseParams("mgv6_np_terrain_higher", np_terrain_higher);
  99. settings->getNoiseParams("mgv6_np_steepness", np_steepness);
  100. settings->getNoiseParams("mgv6_np_height_select", np_height_select);
  101. settings->getNoiseParams("mgv6_np_mud", np_mud);
  102. settings->getNoiseParams("mgv6_np_beach", np_beach);
  103. settings->getNoiseParams("mgv6_np_biome", np_biome);
  104. settings->getNoiseParams("mgv6_np_cave", np_cave);
  105. settings->getNoiseParams("mgv6_np_humidity", np_humidity);
  106. settings->getNoiseParams("mgv6_np_trees", np_trees);
  107. settings->getNoiseParams("mgv6_np_apple_trees", np_apple_trees);
  108. }
  109. void MapgenV6Params::writeParams(Settings *settings) {
  110. settings->setFlagStr("mgv6_spflags", spflags, flagdesc_mapgen_v6, (u32)-1);
  111. settings->setFloat("mgv6_freq_desert", freq_desert);
  112. settings->setFloat("mgv6_freq_beach", freq_beach);
  113. settings->setNoiseParams("mgv6_np_terrain_base", np_terrain_base);
  114. settings->setNoiseParams("mgv6_np_terrain_higher", np_terrain_higher);
  115. settings->setNoiseParams("mgv6_np_steepness", np_steepness);
  116. settings->setNoiseParams("mgv6_np_height_select", np_height_select);
  117. settings->setNoiseParams("mgv6_np_mud", np_mud);
  118. settings->setNoiseParams("mgv6_np_beach", np_beach);
  119. settings->setNoiseParams("mgv6_np_biome", np_biome);
  120. settings->setNoiseParams("mgv6_np_cave", np_cave);
  121. settings->setNoiseParams("mgv6_np_humidity", np_humidity);
  122. settings->setNoiseParams("mgv6_np_trees", np_trees);
  123. settings->setNoiseParams("mgv6_np_apple_trees", np_apple_trees);
  124. }
  125. //////////////////////// Some helper functions for the map generator
  126. // Returns Y one under area minimum if not found
  127. s16 MapgenV6::find_stone_level(v2s16 p2d) {
  128. v3s16 em = vm->m_area.getExtent();
  129. s16 y_nodes_max = vm->m_area.MaxEdge.Y;
  130. s16 y_nodes_min = vm->m_area.MinEdge.Y;
  131. u32 i = vm->m_area.index(p2d.X, y_nodes_max, p2d.Y);
  132. s16 y;
  133. for (y = y_nodes_max; y >= y_nodes_min; y--) {
  134. MapNode &n = vm->m_data[i];
  135. content_t c = n.getContent();
  136. if (c != CONTENT_IGNORE && (
  137. c == c_stone || c == c_desert_stone))
  138. break;
  139. vm->m_area.add_y(em, i, -1);
  140. }
  141. return (y >= y_nodes_min) ? y : y_nodes_min - 1;
  142. }
  143. // Required by mapgen.h
  144. bool MapgenV6::block_is_underground(u64 seed, v3s16 blockpos)
  145. {
  146. /*s16 minimum_groundlevel = (s16)get_sector_minimum_ground_level(
  147. seed, v2s16(blockpos.X, blockpos.Z));*/
  148. // Nah, this is just a heuristic, just return something
  149. s16 minimum_groundlevel = water_level;
  150. if(blockpos.Y*MAP_BLOCKSIZE + MAP_BLOCKSIZE <= minimum_groundlevel)
  151. return true;
  152. else
  153. return false;
  154. }
  155. //////////////////////// Base terrain height functions
  156. float MapgenV6::baseTerrainLevel(float terrain_base, float terrain_higher,
  157. float steepness, float height_select) {
  158. float base = 1 + terrain_base;
  159. float higher = 1 + terrain_higher;
  160. // Limit higher ground level to at least base
  161. if(higher < base)
  162. higher = base;
  163. // Steepness factor of cliffs
  164. float b = steepness;
  165. b = rangelim(b, 0.0, 1000.0);
  166. b = 5 * b * b * b * b * b * b * b;
  167. b = rangelim(b, 0.5, 1000.0);
  168. // Values 1.5...100 give quite horrible looking slopes
  169. if (b > 1.5 && b < 100.0)
  170. b = (b < 10.0) ? 1.5 : 100.0;
  171. float a_off = -0.20; // Offset to more low
  172. float a = 0.5 + b * (a_off + height_select);
  173. a = rangelim(a, 0.0, 1.0); // Limit
  174. return base * (1.0 - a) + higher * a;
  175. }
  176. float MapgenV6::baseTerrainLevelFromNoise(v2s16 p) {
  177. if (flags & MG_FLAT)
  178. return water_level;
  179. float terrain_base = NoisePerlin2DPosOffset(noise_terrain_base->np,
  180. p.X, 0.5, p.Y, 0.5, seed);
  181. float terrain_higher = NoisePerlin2DPosOffset(noise_terrain_higher->np,
  182. p.X, 0.5, p.Y, 0.5, seed);
  183. float steepness = NoisePerlin2DPosOffset(noise_steepness->np,
  184. p.X, 0.5, p.Y, 0.5, seed);
  185. float height_select = NoisePerlin2DNoTxfmPosOffset(noise_height_select->np,
  186. p.X, 0.5, p.Y, 0.5, seed);
  187. return baseTerrainLevel(terrain_base, terrain_higher,
  188. steepness, height_select);
  189. }
  190. float MapgenV6::baseTerrainLevelFromMap(v2s16 p) {
  191. int index = (p.Y - node_min.Z) * ystride + (p.X - node_min.X);
  192. return baseTerrainLevelFromMap(index);
  193. }
  194. float MapgenV6::baseTerrainLevelFromMap(int index) {
  195. if (flags & MG_FLAT)
  196. return water_level;
  197. float terrain_base = noise_terrain_base->result[index];
  198. float terrain_higher = noise_terrain_higher->result[index];
  199. float steepness = noise_steepness->result[index];
  200. float height_select = noise_height_select->result[index];
  201. return baseTerrainLevel(terrain_base, terrain_higher,
  202. steepness, height_select);
  203. }
  204. s16 MapgenV6::find_ground_level_from_noise(u64 seed, v2s16 p2d, s16 precision) {
  205. return baseTerrainLevelFromNoise(p2d) + AVERAGE_MUD_AMOUNT;
  206. }
  207. int MapgenV6::getGroundLevelAtPoint(v2s16 p) {
  208. return baseTerrainLevelFromNoise(p) + AVERAGE_MUD_AMOUNT;
  209. }
  210. //////////////////////// Noise functions
  211. float MapgenV6::getMudAmount(v2s16 p) {
  212. int index = (p.Y - node_min.Z) * ystride + (p.X - node_min.X);
  213. return getMudAmount(index);
  214. }
  215. bool MapgenV6::getHaveBeach(v2s16 p) {
  216. int index = (p.Y - node_min.Z) * ystride + (p.X - node_min.X);
  217. return getHaveBeach(index);
  218. }
  219. BiomeType MapgenV6::getBiome(v2s16 p) {
  220. int index = (p.Y - node_min.Z) * ystride + (p.X - node_min.X);
  221. return getBiome(index, p);
  222. }
  223. float MapgenV6::getHumidity(v2s16 p)
  224. {
  225. /*double noise = noise2d_perlin(
  226. 0.5+(float)p.X/500, 0.5+(float)p.Y/500,
  227. seed+72384, 4, 0.66);
  228. noise = (noise + 1.0)/2.0;*/
  229. float noise = NoisePerlin2D(np_humidity, p.X, p.Y, seed);
  230. if (noise < 0.0)
  231. noise = 0.0;
  232. if (noise > 1.0)
  233. noise = 1.0;
  234. return noise;
  235. }
  236. float MapgenV6::getTreeAmount(v2s16 p)
  237. {
  238. /*double noise = noise2d_perlin(
  239. 0.5+(float)p.X/125, 0.5+(float)p.Y/125,
  240. seed+2, 4, 0.66);*/
  241. float noise = NoisePerlin2D(np_trees, p.X, p.Y, seed);
  242. float zeroval = -0.39;
  243. if (noise < zeroval)
  244. return 0;
  245. else
  246. return 0.04 * (noise-zeroval) / (1.0-zeroval);
  247. }
  248. bool MapgenV6::getHaveAppleTree(v2s16 p)
  249. {
  250. /*is_apple_tree = noise2d_perlin(
  251. 0.5+(float)p.X/100, 0.5+(float)p.Z/100,
  252. data->seed+342902, 3, 0.45) > 0.2;*/
  253. float noise = NoisePerlin2D(np_apple_trees, p.X, p.Y, seed);
  254. return noise > 0.2;
  255. }
  256. float MapgenV6::getMudAmount(int index)
  257. {
  258. if (flags & MG_FLAT)
  259. return AVERAGE_MUD_AMOUNT;
  260. /*return ((float)AVERAGE_MUD_AMOUNT + 2.0 * noise2d_perlin(
  261. 0.5+(float)p.X/200, 0.5+(float)p.Y/200,
  262. seed+91013, 3, 0.55));*/
  263. return noise_mud->result[index];
  264. }
  265. bool MapgenV6::getHaveBeach(int index)
  266. {
  267. // Determine whether to have sand here
  268. /*double sandnoise = noise2d_perlin(
  269. 0.2+(float)p2d.X/250, 0.7+(float)p2d.Y/250,
  270. seed+59420, 3, 0.50);*/
  271. float sandnoise = noise_beach->result[index];
  272. return (sandnoise > freq_beach);
  273. }
  274. BiomeType MapgenV6::getBiome(int index, v2s16 p)
  275. {
  276. // Just do something very simple as for now
  277. /*double d = noise2d_perlin(
  278. 0.6+(float)p2d.X/250, 0.2+(float)p2d.Y/250,
  279. seed+9130, 3, 0.50);*/
  280. float d = noise_biome->result[index];
  281. if (d > freq_desert)
  282. return BT_DESERT;
  283. if ((spflags & MGV6_BIOMEBLEND) &&
  284. (d > freq_desert - 0.10) &&
  285. ((noise2d(p.X, p.Y, seed) + 1.0) > (freq_desert - d) * 20.0))
  286. return BT_DESERT;
  287. return BT_NORMAL;
  288. }
  289. u32 MapgenV6::get_blockseed(u64 seed, v3s16 p)
  290. {
  291. s32 x=p.X, y=p.Y, z=p.Z;
  292. return (u32)(seed%0x100000000ULL) + z*38134234 + y*42123 + x*23;
  293. }
  294. //////////////////////// Map generator
  295. void MapgenV6::makeChunk(BlockMakeData *data) {
  296. assert(data->vmanip);
  297. assert(data->nodedef);
  298. assert(data->blockpos_requested.X >= data->blockpos_min.X &&
  299. data->blockpos_requested.Y >= data->blockpos_min.Y &&
  300. data->blockpos_requested.Z >= data->blockpos_min.Z);
  301. assert(data->blockpos_requested.X <= data->blockpos_max.X &&
  302. data->blockpos_requested.Y <= data->blockpos_max.Y &&
  303. data->blockpos_requested.Z <= data->blockpos_max.Z);
  304. this->generating = true;
  305. this->vm = data->vmanip;
  306. this->ndef = data->nodedef;
  307. // Hack: use minimum block coords for old code that assumes a single block
  308. v3s16 blockpos = data->blockpos_requested;
  309. v3s16 blockpos_min = data->blockpos_min;
  310. v3s16 blockpos_max = data->blockpos_max;
  311. // Area of central chunk
  312. node_min = blockpos_min*MAP_BLOCKSIZE;
  313. node_max = (blockpos_max+v3s16(1,1,1))*MAP_BLOCKSIZE-v3s16(1,1,1);
  314. // Full allocated area
  315. full_node_min = (blockpos_min-1)*MAP_BLOCKSIZE;
  316. full_node_max = (blockpos_max+2)*MAP_BLOCKSIZE-v3s16(1,1,1);
  317. central_area_size = node_max - node_min + v3s16(1,1,1);
  318. assert(central_area_size.X == central_area_size.Z);
  319. int volume_blocks = (blockpos_max.X - blockpos_min.X + 1)
  320. * (blockpos_max.Y - blockpos_min.Y + 1)
  321. * (blockpos_max.Z - blockpos_max.Z + 1);
  322. volume_nodes = volume_blocks *
  323. MAP_BLOCKSIZE * MAP_BLOCKSIZE * MAP_BLOCKSIZE;
  324. // Create a block-specific seed
  325. blockseed = get_blockseed(data->seed, full_node_min);
  326. // Make some noise
  327. calculateNoise();
  328. c_stone = ndef->getId("mapgen_stone");
  329. c_dirt = ndef->getId("mapgen_dirt");
  330. c_dirt_with_grass = ndef->getId("mapgen_dirt_with_grass");
  331. c_sand = ndef->getId("mapgen_sand");
  332. c_water_source = ndef->getId("mapgen_water_source");
  333. c_lava_source = ndef->getId("mapgen_lava_source");
  334. c_gravel = ndef->getId("mapgen_gravel");
  335. c_cobble = ndef->getId("mapgen_cobble");
  336. c_desert_sand = ndef->getId("mapgen_desert_sand");
  337. c_desert_stone = ndef->getId("mapgen_desert_stone");
  338. c_mossycobble = ndef->getId("mapgen_mossycobble");
  339. c_sandbrick = ndef->getId("mapgen_sandstonebrick");
  340. c_stair_cobble = ndef->getId("mapgen_stair_cobble");
  341. c_stair_sandstone = ndef->getId("mapgen_stair_sandstone");
  342. if (c_desert_sand == CONTENT_IGNORE)
  343. c_desert_sand = c_sand;
  344. if (c_desert_stone == CONTENT_IGNORE)
  345. c_desert_stone = c_stone;
  346. if (c_mossycobble == CONTENT_IGNORE)
  347. c_mossycobble = c_cobble;
  348. if (c_sandbrick == CONTENT_IGNORE)
  349. c_sandbrick = c_desert_stone;
  350. if (c_stair_cobble == CONTENT_IGNORE)
  351. c_stair_cobble = c_cobble;
  352. if (c_stair_sandstone == CONTENT_IGNORE)
  353. c_stair_sandstone = c_sandbrick;
  354. // Maximum height of the stone surface and obstacles.
  355. // This is used to guide the cave generation
  356. s16 stone_surface_max_y;
  357. // Generate general ground level to full area
  358. stone_surface_max_y = generateGround();
  359. generateExperimental();
  360. const s16 max_spread_amount = MAP_BLOCKSIZE;
  361. // Limit dirt flow area by 1 because mud is flown into neighbors.
  362. s16 mudflow_minpos = -max_spread_amount + 1;
  363. s16 mudflow_maxpos = central_area_size.X + max_spread_amount - 2;
  364. // Loop this part, it will make stuff look older and newer nicely
  365. const u32 age_loops = 2;
  366. for (u32 i_age = 0; i_age < age_loops; i_age++) { // Aging loop
  367. // Make caves (this code is relatively horrible)
  368. if (flags & MG_CAVES)
  369. generateCaves(stone_surface_max_y);
  370. // Add mud to the central chunk
  371. addMud();
  372. // Add blobs of dirt and gravel underground
  373. addDirtGravelBlobs();
  374. // Flow mud away from steep edges
  375. if (spflags & MGV6_MUDFLOW)
  376. flowMud(mudflow_minpos, mudflow_maxpos);
  377. }
  378. // Add dungeons
  379. if (flags & MG_DUNGEONS) {
  380. DungeonParams dp;
  381. dp.np_rarity = nparams_dungeon_rarity;
  382. dp.np_density = nparams_dungeon_density;
  383. dp.np_wetness = nparams_dungeon_wetness;
  384. dp.c_water = c_water_source;
  385. if (getBiome(0, v2s16(node_min.X, node_min.Z)) == BT_NORMAL) {
  386. dp.c_cobble = c_cobble;
  387. dp.c_moss = c_mossycobble;
  388. dp.c_stair = c_stair_cobble;
  389. dp.diagonal_dirs = false;
  390. dp.mossratio = 3.0;
  391. dp.holesize = v3s16(1, 2, 1);
  392. dp.roomsize = v3s16(0, 0, 0);
  393. dp.notifytype = GENNOTIFY_DUNGEON;
  394. } else {
  395. dp.c_cobble = c_sandbrick;
  396. dp.c_moss = c_sandbrick; // should make this 'cracked sandstone' later
  397. dp.c_stair = c_stair_sandstone;
  398. dp.diagonal_dirs = true;
  399. dp.mossratio = 0.0;
  400. dp.holesize = v3s16(2, 3, 2);
  401. dp.roomsize = v3s16(2, 5, 2);
  402. dp.notifytype = GENNOTIFY_TEMPLE;
  403. }
  404. DungeonGen dgen(this, &dp);
  405. dgen.generate(blockseed, full_node_min, full_node_max);
  406. }
  407. // Add top and bottom side of water to transforming_liquid queue
  408. updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);
  409. // Grow grass
  410. growGrass();
  411. // Generate some trees, and add grass, if a jungle
  412. if (flags & MG_TREES)
  413. placeTreesAndJungleGrass();
  414. // Generate the registered decorations
  415. for (unsigned int i = 0; i != emerge->decorations.size(); i++) {
  416. Decoration *deco = emerge->decorations[i];
  417. deco->placeDeco(this, blockseed + i, node_min, node_max);
  418. }
  419. // Generate the registered ores
  420. for (unsigned int i = 0; i != emerge->ores.size(); i++) {
  421. Ore *ore = emerge->ores[i];
  422. ore->placeOre(this, blockseed + i, node_min, node_max);
  423. }
  424. // Calculate lighting
  425. if (flags & MG_LIGHT)
  426. calcLighting(node_min - v3s16(1, 1, 1) * MAP_BLOCKSIZE,
  427. node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE);
  428. this->generating = false;
  429. }
  430. void MapgenV6::calculateNoise() {
  431. int x = node_min.X;
  432. int z = node_min.Z;
  433. // Need to adjust for the original implementation's +.5 offset...
  434. if (!(flags & MG_FLAT)) {
  435. noise_terrain_base->perlinMap2D(
  436. x + 0.5 * noise_terrain_base->np->spread.X,
  437. z + 0.5 * noise_terrain_base->np->spread.Z);
  438. noise_terrain_base->transformNoiseMap();
  439. noise_terrain_higher->perlinMap2D(
  440. x + 0.5 * noise_terrain_higher->np->spread.X,
  441. z + 0.5 * noise_terrain_higher->np->spread.Z);
  442. noise_terrain_higher->transformNoiseMap();
  443. noise_steepness->perlinMap2D(
  444. x + 0.5 * noise_steepness->np->spread.X,
  445. z + 0.5 * noise_steepness->np->spread.Z);
  446. noise_steepness->transformNoiseMap();
  447. noise_height_select->perlinMap2D(
  448. x + 0.5 * noise_height_select->np->spread.X,
  449. z + 0.5 * noise_height_select->np->spread.Z);
  450. noise_mud->perlinMap2D(
  451. x + 0.5 * noise_mud->np->spread.X,
  452. z + 0.5 * noise_mud->np->spread.Z);
  453. noise_mud->transformNoiseMap();
  454. }
  455. noise_beach->perlinMap2D(
  456. x + 0.2 * noise_beach->np->spread.X,
  457. z + 0.7 * noise_beach->np->spread.Z);
  458. noise_biome->perlinMap2D(
  459. x + 0.6 * noise_biome->np->spread.X,
  460. z + 0.2 * noise_biome->np->spread.Z);
  461. }
  462. int MapgenV6::generateGround() {
  463. //TimeTaker timer1("Generating ground level");
  464. MapNode n_air(CONTENT_AIR), n_water_source(c_water_source);
  465. MapNode n_stone(c_stone), n_desert_stone(c_desert_stone);
  466. int stone_surface_max_y = -MAP_GENERATION_LIMIT;
  467. u32 index = 0;
  468. for (s16 z = node_min.Z; z <= node_max.Z; z++)
  469. for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
  470. // Surface height
  471. s16 surface_y = (s16)baseTerrainLevelFromMap(index);
  472. // Log it
  473. if (surface_y > stone_surface_max_y)
  474. stone_surface_max_y = surface_y;
  475. BiomeType bt = getBiome(index, v2s16(x, z));
  476. // Fill ground with stone
  477. v3s16 em = vm->m_area.getExtent();
  478. u32 i = vm->m_area.index(x, node_min.Y, z);
  479. for (s16 y = node_min.Y; y <= node_max.Y; y++) {
  480. if (vm->m_data[i].getContent() == CONTENT_IGNORE) {
  481. if (y <= surface_y) {
  482. vm->m_data[i] = (y > water_level && bt == BT_DESERT) ?
  483. n_desert_stone : n_stone;
  484. } else if (y <= water_level) {
  485. vm->m_data[i] = n_water_source;
  486. } else {
  487. vm->m_data[i] = n_air;
  488. }
  489. }
  490. vm->m_area.add_y(em, i, 1);
  491. }
  492. }
  493. return stone_surface_max_y;
  494. }
  495. void MapgenV6::addMud() {
  496. // 15ms @cs=8
  497. //TimeTaker timer1("add mud");
  498. MapNode n_dirt(c_dirt), n_gravel(c_gravel);
  499. MapNode n_sand(c_sand), n_desert_sand(c_desert_sand);
  500. MapNode addnode;
  501. u32 index = 0;
  502. for (s16 z = node_min.Z; z <= node_max.Z; z++)
  503. for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
  504. // Randomize mud amount
  505. s16 mud_add_amount = getMudAmount(index) / 2.0 + 0.5;
  506. // Find ground level
  507. s16 surface_y = find_stone_level(v2s16(x, z)); /////////////////optimize this!
  508. // Handle area not found
  509. if (surface_y == vm->m_area.MinEdge.Y - 1)
  510. continue;
  511. BiomeType bt = getBiome(index, v2s16(x, z));
  512. addnode = (bt == BT_DESERT) ? n_desert_sand : n_dirt;
  513. if (bt == BT_DESERT && surface_y + mud_add_amount <= water_level + 1) {
  514. addnode = n_sand;
  515. } else if (mud_add_amount <= 0) {
  516. mud_add_amount = 1 - mud_add_amount;
  517. addnode = n_gravel;
  518. } else if (bt == BT_NORMAL && getHaveBeach(index) &&
  519. surface_y + mud_add_amount <= water_level + 2) {
  520. addnode = n_sand;
  521. }
  522. if (bt == BT_DESERT && surface_y > 20)
  523. mud_add_amount = MYMAX(0, mud_add_amount - (surface_y - 20) / 5);
  524. // If topmost node is grass, change it to mud. It might be if it was
  525. // flown to there from a neighboring chunk and then converted.
  526. u32 i = vm->m_area.index(x, surface_y, z);
  527. if (vm->m_data[i].getContent() == c_dirt_with_grass)
  528. vm->m_data[i] = n_dirt;
  529. // Add mud on ground
  530. s16 mudcount = 0;
  531. v3s16 em = vm->m_area.getExtent();
  532. s16 y_start = surface_y + 1;
  533. i = vm->m_area.index(x, y_start, z);
  534. for (s16 y = y_start; y <= node_max.Y; y++) {
  535. if (mudcount >= mud_add_amount)
  536. break;
  537. vm->m_data[i] = addnode;
  538. mudcount++;
  539. vm->m_area.add_y(em, i, 1);
  540. }
  541. }
  542. }
  543. void MapgenV6::flowMud(s16 &mudflow_minpos, s16 &mudflow_maxpos) {
  544. // 340ms @cs=8
  545. TimeTaker timer1("flow mud");
  546. // Iterate a few times
  547. for(s16 k = 0; k < 3; k++) {
  548. for (s16 z = mudflow_minpos; z <= mudflow_maxpos; z++)
  549. for (s16 x = mudflow_minpos; x <= mudflow_maxpos; x++) {
  550. // Invert coordinates every 2nd iteration
  551. if (k % 2 == 0) {
  552. x = mudflow_maxpos - (x - mudflow_minpos);
  553. z = mudflow_maxpos - (z - mudflow_minpos);
  554. }
  555. // Node position in 2d
  556. v2s16 p2d = v2s16(node_min.X, node_min.Z) + v2s16(x, z);
  557. v3s16 em = vm->m_area.getExtent();
  558. u32 i = vm->m_area.index(p2d.X, node_max.Y, p2d.Y);
  559. s16 y = node_max.Y;
  560. while(y >= node_min.Y)
  561. {
  562. for(;; y--)
  563. {
  564. MapNode *n = NULL;
  565. // Find mud
  566. for(; y >= node_min.Y; y--) {
  567. n = &vm->m_data[i];
  568. if (n->getContent() == c_dirt ||
  569. n->getContent() == c_dirt_with_grass ||
  570. n->getContent() == c_gravel)
  571. break;
  572. vm->m_area.add_y(em, i, -1);
  573. }
  574. // Stop if out of area
  575. //if(vmanip.m_area.contains(i) == false)
  576. if (y < node_min.Y)
  577. break;
  578. if (n->getContent() == c_dirt ||
  579. n->getContent() == c_dirt_with_grass)
  580. {
  581. // Make it exactly mud
  582. n->setContent(c_dirt);
  583. // Don't flow it if the stuff under it is not mud
  584. {
  585. u32 i2 = i;
  586. vm->m_area.add_y(em, i2, -1);
  587. // Cancel if out of area
  588. if(vm->m_area.contains(i2) == false)
  589. continue;
  590. MapNode *n2 = &vm->m_data[i2];
  591. if (n2->getContent() != c_dirt &&
  592. n2->getContent() != c_dirt_with_grass)
  593. continue;
  594. }
  595. }
  596. v3s16 dirs4[4] = {
  597. v3s16(0,0,1), // back
  598. v3s16(1,0,0), // right
  599. v3s16(0,0,-1), // front
  600. v3s16(-1,0,0), // left
  601. };
  602. // Check that upper is air or doesn't exist.
  603. // Cancel dropping if upper keeps it in place
  604. u32 i3 = i;
  605. vm->m_area.add_y(em, i3, 1);
  606. if (vm->m_area.contains(i3) == true &&
  607. ndef->get(vm->m_data[i3]).walkable)
  608. continue;
  609. // Drop mud on side
  610. for(u32 di=0; di<4; di++) {
  611. v3s16 dirp = dirs4[di];
  612. u32 i2 = i;
  613. // Move to side
  614. vm->m_area.add_p(em, i2, dirp);
  615. // Fail if out of area
  616. if (vm->m_area.contains(i2) == false)
  617. continue;
  618. // Check that side is air
  619. MapNode *n2 = &vm->m_data[i2];
  620. if (ndef->get(*n2).walkable)
  621. continue;
  622. // Check that under side is air
  623. vm->m_area.add_y(em, i2, -1);
  624. if (vm->m_area.contains(i2) == false)
  625. continue;
  626. n2 = &vm->m_data[i2];
  627. if (ndef->get(*n2).walkable)
  628. continue;
  629. // Loop further down until not air
  630. bool dropped_to_unknown = false;
  631. do {
  632. vm->m_area.add_y(em, i2, -1);
  633. n2 = &vm->m_data[i2];
  634. // if out of known area
  635. if(vm->m_area.contains(i2) == false ||
  636. n2->getContent() == CONTENT_IGNORE) {
  637. dropped_to_unknown = true;
  638. break;
  639. }
  640. } while (ndef->get(*n2).walkable == false);
  641. // Loop one up so that we're in air
  642. vm->m_area.add_y(em, i2, 1);
  643. n2 = &vm->m_data[i2];
  644. bool old_is_water = (n->getContent() == c_water_source);
  645. // Move mud to new place
  646. if (!dropped_to_unknown) {
  647. *n2 = *n;
  648. // Set old place to be air (or water)
  649. if(old_is_water)
  650. *n = MapNode(c_water_source);
  651. else
  652. *n = MapNode(CONTENT_AIR);
  653. }
  654. // Done
  655. break;
  656. }
  657. }
  658. }
  659. }
  660. }
  661. }
  662. void MapgenV6::addDirtGravelBlobs() {
  663. if (getBiome(v2s16(node_min.X, node_min.Z)) != BT_NORMAL)
  664. return;
  665. PseudoRandom pr(blockseed + 983);
  666. for (int i = 0; i < volume_nodes/10/10/10; i++) {
  667. bool only_fill_cave = (myrand_range(0,1) != 0);
  668. v3s16 size(
  669. pr.range(1, 8),
  670. pr.range(1, 8),
  671. pr.range(1, 8)
  672. );
  673. v3s16 p0(
  674. pr.range(node_min.X, node_max.X) - size.X / 2,
  675. pr.range(node_min.Y, node_max.Y) - size.Y / 2,
  676. pr.range(node_min.Z, node_max.Z) - size.Z / 2
  677. );
  678. MapNode n1((p0.Y > -32 && !pr.range(0, 1)) ? c_dirt : c_gravel);
  679. for (int z1 = 0; z1 < size.Z; z1++)
  680. for (int y1 = 0; y1 < size.Y; y1++)
  681. for (int x1 = 0; x1 < size.X; x1++) {
  682. v3s16 p = p0 + v3s16(x1, y1, z1);
  683. u32 i = vm->m_area.index(p);
  684. if (!vm->m_area.contains(i))
  685. continue;
  686. // Cancel if not stone and not cave air
  687. if (vm->m_data[i].getContent() != c_stone &&
  688. !(vm->m_flags[i] & VMANIP_FLAG_CAVE))
  689. continue;
  690. if (only_fill_cave && !(vm->m_flags[i] & VMANIP_FLAG_CAVE))
  691. continue;
  692. vm->m_data[i] = n1;
  693. }
  694. }
  695. }
  696. void MapgenV6::placeTreesAndJungleGrass() {
  697. //TimeTaker t("placeTrees");
  698. if (node_max.Y < water_level)
  699. return;
  700. PseudoRandom grassrandom(blockseed + 53);
  701. content_t c_junglegrass = ndef->getId("mapgen_junglegrass");
  702. // if we don't have junglegrass, don't place cignore... that's bad
  703. if (c_junglegrass == CONTENT_IGNORE)
  704. c_junglegrass = CONTENT_AIR;
  705. MapNode n_junglegrass(c_junglegrass);
  706. v3s16 em = vm->m_area.getExtent();
  707. // Divide area into parts
  708. s16 div = 8;
  709. s16 sidelen = central_area_size.X / div;
  710. double area = sidelen * sidelen;
  711. // N.B. We must add jungle grass first, since tree leaves will
  712. // obstruct the ground, giving us a false ground level
  713. for (s16 z0 = 0; z0 < div; z0++)
  714. for (s16 x0 = 0; x0 < div; x0++) {
  715. // Center position of part of division
  716. v2s16 p2d_center(
  717. node_min.X + sidelen / 2 + sidelen * x0,
  718. node_min.Z + sidelen / 2 + sidelen * z0
  719. );
  720. // Minimum edge of part of division
  721. v2s16 p2d_min(
  722. node_min.X + sidelen * x0,
  723. node_min.Z + sidelen * z0
  724. );
  725. // Maximum edge of part of division
  726. v2s16 p2d_max(
  727. node_min.X + sidelen + sidelen * x0 - 1,
  728. node_min.Z + sidelen + sidelen * z0 - 1
  729. );
  730. // Amount of trees, jungle area
  731. u32 tree_count = area * getTreeAmount(p2d_center);
  732. float humidity;
  733. bool is_jungle = false;
  734. if (spflags & MGV6_JUNGLES) {
  735. humidity = getHumidity(p2d_center);
  736. if (humidity > 0.75) {
  737. is_jungle = true;
  738. tree_count *= 4;
  739. }
  740. }
  741. // Add jungle grass
  742. if (is_jungle) {
  743. u32 grass_count = 5 * humidity * tree_count;
  744. for (u32 i = 0; i < grass_count; i++) {
  745. s16 x = grassrandom.range(p2d_min.X, p2d_max.X);
  746. s16 z = grassrandom.range(p2d_min.Y, p2d_max.Y);
  747. s16 y = findGroundLevelFull(v2s16(x, z)); ////////////////optimize this!
  748. if (y < water_level || y < node_min.Y || y > node_max.Y)
  749. continue;
  750. u32 vi = vm->m_area.index(x, y, z);
  751. // place on dirt_with_grass, since we know it is exposed to sunlight
  752. if (vm->m_data[vi].getContent() == c_dirt_with_grass) {
  753. vm->m_area.add_y(em, vi, 1);
  754. vm->m_data[vi] = n_junglegrass;
  755. }
  756. }
  757. }
  758. // Put trees in random places on part of division
  759. for (u32 i = 0; i < tree_count; i++) {
  760. s16 x = myrand_range(p2d_min.X, p2d_max.X);
  761. s16 z = myrand_range(p2d_min.Y, p2d_max.Y);
  762. s16 y = findGroundLevelFull(v2s16(x, z)); ////////////////////optimize this!
  763. // Don't make a tree under water level
  764. // Don't make a tree so high that it doesn't fit
  765. if(y < water_level || y > node_max.Y - 6)
  766. continue;
  767. v3s16 p(x,y,z);
  768. // Trees grow only on mud and grass
  769. {
  770. u32 i = vm->m_area.index(p);
  771. MapNode *n = &vm->m_data[i];
  772. if (n->getContent() != c_dirt &&
  773. n->getContent() != c_dirt_with_grass)
  774. continue;
  775. }
  776. p.Y++;
  777. // Make a tree
  778. if (is_jungle) {
  779. treegen::make_jungletree(*vm, p, ndef, myrand());
  780. } else {
  781. bool is_apple_tree = (myrand_range(0, 3) == 0) &&
  782. getHaveAppleTree(v2s16(x, z));
  783. treegen::make_tree(*vm, p, is_apple_tree, ndef, myrand());
  784. }
  785. }
  786. }
  787. //printf("placeTreesAndJungleGrass: %dms\n", t.stop());
  788. }
  789. void MapgenV6::growGrass() {
  790. for (s16 z = full_node_min.Z; z <= full_node_max.Z; z++)
  791. for (s16 x = full_node_min.X; x <= full_node_max.X; x++) {
  792. // Find the lowest surface to which enough light ends up to make
  793. // grass grow. Basically just wait until not air and not leaves.
  794. s16 surface_y = 0;
  795. {
  796. v3s16 em = vm->m_area.getExtent();
  797. u32 i = vm->m_area.index(x, node_max.Y, z);
  798. s16 y;
  799. // Go to ground level
  800. for (y = node_max.Y; y >= full_node_min.Y; y--) {
  801. MapNode &n = vm->m_data[i];
  802. if (ndef->get(n).param_type != CPT_LIGHT ||
  803. ndef->get(n).liquid_type != LIQUID_NONE)
  804. break;
  805. vm->m_area.add_y(em, i, -1);
  806. }
  807. surface_y = (y >= full_node_min.Y) ? y : full_node_min.Y;
  808. }
  809. u32 i = vm->m_area.index(x, surface_y, z);
  810. MapNode *n = &vm->m_data[i];
  811. if (n->getContent() == c_dirt && surface_y >= water_level - 20)
  812. n->setContent(c_dirt_with_grass);
  813. }
  814. }
  815. void MapgenV6::generateCaves(int max_stone_y) {
  816. float cave_amount = NoisePerlin2D(np_cave, node_min.X, node_min.Y, seed);
  817. int volume_nodes = (node_max.X - node_min.X + 1) *
  818. (node_max.Y - node_min.Y + 1) * MAP_BLOCKSIZE;
  819. cave_amount = MYMAX(0.0, cave_amount);
  820. u32 caves_count = cave_amount * volume_nodes / 50000;
  821. u32 bruises_count = 1;
  822. PseudoRandom ps(blockseed + 21343);
  823. PseudoRandom ps2(blockseed + 1032);
  824. if (ps.range(1, 6) == 1)
  825. bruises_count = ps.range(0, ps.range(0, 2));
  826. if (getBiome(v2s16(node_min.X, node_min.Z)) == BT_DESERT) {
  827. caves_count /= 3;
  828. bruises_count /= 3;
  829. }
  830. for (u32 i = 0; i < caves_count + bruises_count; i++) {
  831. bool large_cave = (i >= caves_count);
  832. CaveV6 cave(this, &ps, &ps2, large_cave);
  833. cave.makeCave(node_min, node_max, max_stone_y);
  834. }
  835. }