mapgen.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092
  1. /*
  2. Minetest
  3. Copyright (C) 2010-2015 celeron55, Perttu Ahola <celeron55@gmail.com>
  4. Copyright (C) 2013-2016 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
  5. Copyright (C) 2015-2017 paramat
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU Lesser General Public License as published by
  8. the Free Software Foundation; either version 2.1 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU Lesser General Public License for more details.
  14. You should have received a copy of the GNU Lesser General Public License along
  15. with this program; if not, write to the Free Software Foundation, Inc.,
  16. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  17. */
  18. #include "mapgen.h"
  19. #include "voxel.h"
  20. #include "noise.h"
  21. #include "gamedef.h"
  22. #include "mg_biome.h"
  23. #include "mapblock.h"
  24. #include "mapnode.h"
  25. #include "map.h"
  26. #include "content_sao.h"
  27. #include "nodedef.h"
  28. #include "emerge.h"
  29. #include "voxelalgorithms.h"
  30. #include "porting.h"
  31. #include "profiler.h"
  32. #include "settings.h"
  33. #include "treegen.h"
  34. #include "serialization.h"
  35. #include "util/serialize.h"
  36. #include "util/numeric.h"
  37. #include "filesys.h"
  38. #include "log.h"
  39. #include "mapgen_flat.h"
  40. #include "mapgen_fractal.h"
  41. #include "mapgen_v5.h"
  42. #include "mapgen_v6.h"
  43. #include "mapgen_v7.h"
  44. #include "mapgen_valleys.h"
  45. #include "mapgen_singlenode.h"
  46. #include "cavegen.h"
  47. #include "dungeongen.h"
  48. FlagDesc flagdesc_mapgen[] = {
  49. {"caves", MG_CAVES},
  50. {"dungeons", MG_DUNGEONS},
  51. {"light", MG_LIGHT},
  52. {"decorations", MG_DECORATIONS},
  53. {NULL, 0}
  54. };
  55. FlagDesc flagdesc_gennotify[] = {
  56. {"dungeon", 1 << GENNOTIFY_DUNGEON},
  57. {"temple", 1 << GENNOTIFY_TEMPLE},
  58. {"cave_begin", 1 << GENNOTIFY_CAVE_BEGIN},
  59. {"cave_end", 1 << GENNOTIFY_CAVE_END},
  60. {"large_cave_begin", 1 << GENNOTIFY_LARGECAVE_BEGIN},
  61. {"large_cave_end", 1 << GENNOTIFY_LARGECAVE_END},
  62. {"decoration", 1 << GENNOTIFY_DECORATION},
  63. {NULL, 0}
  64. };
  65. struct MapgenDesc {
  66. const char *name;
  67. bool is_user_visible;
  68. };
  69. ////
  70. //// Built-in mapgens
  71. ////
  72. static MapgenDesc g_reg_mapgens[] = {
  73. {"v5", true},
  74. {"v6", true},
  75. {"v7", true},
  76. {"flat", true},
  77. {"fractal", true},
  78. {"valleys", true},
  79. {"singlenode", true},
  80. };
  81. STATIC_ASSERT(
  82. ARRLEN(g_reg_mapgens) == MAPGEN_INVALID,
  83. registered_mapgens_is_wrong_size);
  84. ////
  85. //// Mapgen
  86. ////
  87. Mapgen::Mapgen()
  88. {
  89. }
  90. Mapgen::Mapgen(int mapgenid, MapgenParams *params, EmergeManager *emerge) :
  91. gennotify(emerge->gen_notify_on, &emerge->gen_notify_on_deco_ids)
  92. {
  93. id = mapgenid;
  94. water_level = params->water_level;
  95. mapgen_limit = params->mapgen_limit;
  96. flags = params->flags;
  97. csize = v3s16(1, 1, 1) * (params->chunksize * MAP_BLOCKSIZE);
  98. /*
  99. We are losing half our entropy by doing this, but it is necessary to
  100. preserve reverse compatibility. If the top half of our current 64 bit
  101. seeds ever starts getting used, existing worlds will break due to a
  102. different hash outcome and no way to differentiate between versions.
  103. A solution could be to add a new bit to designate that the top half of
  104. the seed value should be used, essentially a 1-bit version code, but
  105. this would require increasing the total size of a seed to 9 bytes (yuck)
  106. It's probably okay if this never gets fixed. 4.2 billion possibilities
  107. ought to be enough for anyone.
  108. */
  109. seed = (s32)params->seed;
  110. ndef = emerge->ndef;
  111. }
  112. Mapgen::~Mapgen()
  113. {
  114. }
  115. MapgenType Mapgen::getMapgenType(const std::string &mgname)
  116. {
  117. for (size_t i = 0; i != ARRLEN(g_reg_mapgens); i++) {
  118. if (mgname == g_reg_mapgens[i].name)
  119. return (MapgenType)i;
  120. }
  121. return MAPGEN_INVALID;
  122. }
  123. const char *Mapgen::getMapgenName(MapgenType mgtype)
  124. {
  125. size_t index = (size_t)mgtype;
  126. if (index == MAPGEN_INVALID || index >= ARRLEN(g_reg_mapgens))
  127. return "invalid";
  128. return g_reg_mapgens[index].name;
  129. }
  130. Mapgen *Mapgen::createMapgen(MapgenType mgtype, int mgid,
  131. MapgenParams *params, EmergeManager *emerge)
  132. {
  133. switch (mgtype) {
  134. case MAPGEN_FLAT:
  135. return new MapgenFlat(mgid, (MapgenFlatParams *)params, emerge);
  136. case MAPGEN_FRACTAL:
  137. return new MapgenFractal(mgid, (MapgenFractalParams *)params, emerge);
  138. case MAPGEN_SINGLENODE:
  139. return new MapgenSinglenode(mgid, (MapgenSinglenodeParams *)params, emerge);
  140. case MAPGEN_V5:
  141. return new MapgenV5(mgid, (MapgenV5Params *)params, emerge);
  142. case MAPGEN_V6:
  143. return new MapgenV6(mgid, (MapgenV6Params *)params, emerge);
  144. case MAPGEN_V7:
  145. return new MapgenV7(mgid, (MapgenV7Params *)params, emerge);
  146. case MAPGEN_VALLEYS:
  147. return new MapgenValleys(mgid, (MapgenValleysParams *)params, emerge);
  148. default:
  149. return NULL;
  150. }
  151. }
  152. MapgenParams *Mapgen::createMapgenParams(MapgenType mgtype)
  153. {
  154. switch (mgtype) {
  155. case MAPGEN_FLAT:
  156. return new MapgenFlatParams;
  157. case MAPGEN_FRACTAL:
  158. return new MapgenFractalParams;
  159. case MAPGEN_SINGLENODE:
  160. return new MapgenSinglenodeParams;
  161. case MAPGEN_V5:
  162. return new MapgenV5Params;
  163. case MAPGEN_V6:
  164. return new MapgenV6Params;
  165. case MAPGEN_V7:
  166. return new MapgenV7Params;
  167. case MAPGEN_VALLEYS:
  168. return new MapgenValleysParams;
  169. default:
  170. return NULL;
  171. }
  172. }
  173. void Mapgen::getMapgenNames(std::vector<const char *> *mgnames, bool include_hidden)
  174. {
  175. for (u32 i = 0; i != ARRLEN(g_reg_mapgens); i++) {
  176. if (include_hidden || g_reg_mapgens[i].is_user_visible)
  177. mgnames->push_back(g_reg_mapgens[i].name);
  178. }
  179. }
  180. u32 Mapgen::getBlockSeed(v3s16 p, s32 seed)
  181. {
  182. return (u32)seed +
  183. p.Z * 38134234 +
  184. p.Y * 42123 +
  185. p.X * 23;
  186. }
  187. u32 Mapgen::getBlockSeed2(v3s16 p, s32 seed)
  188. {
  189. u32 n = 1619 * p.X + 31337 * p.Y + 52591 * p.Z + 1013 * seed;
  190. n = (n >> 13) ^ n;
  191. return (n * (n * n * 60493 + 19990303) + 1376312589);
  192. }
  193. // Returns Y one under area minimum if not found
  194. s16 Mapgen::findGroundLevelFull(v2s16 p2d)
  195. {
  196. v3s16 em = vm->m_area.getExtent();
  197. s16 y_nodes_max = vm->m_area.MaxEdge.Y;
  198. s16 y_nodes_min = vm->m_area.MinEdge.Y;
  199. u32 i = vm->m_area.index(p2d.X, y_nodes_max, p2d.Y);
  200. s16 y;
  201. for (y = y_nodes_max; y >= y_nodes_min; y--) {
  202. MapNode &n = vm->m_data[i];
  203. if (ndef->get(n).walkable)
  204. break;
  205. vm->m_area.add_y(em, i, -1);
  206. }
  207. return (y >= y_nodes_min) ? y : y_nodes_min - 1;
  208. }
  209. // Returns -MAX_MAP_GENERATION_LIMIT if not found
  210. s16 Mapgen::findGroundLevel(v2s16 p2d, s16 ymin, s16 ymax)
  211. {
  212. v3s16 em = vm->m_area.getExtent();
  213. u32 i = vm->m_area.index(p2d.X, ymax, p2d.Y);
  214. s16 y;
  215. for (y = ymax; y >= ymin; y--) {
  216. MapNode &n = vm->m_data[i];
  217. if (ndef->get(n).walkable)
  218. break;
  219. vm->m_area.add_y(em, i, -1);
  220. }
  221. return (y >= ymin) ? y : -MAX_MAP_GENERATION_LIMIT;
  222. }
  223. // Returns -MAX_MAP_GENERATION_LIMIT if not found or if ground is found first
  224. s16 Mapgen::findLiquidSurface(v2s16 p2d, s16 ymin, s16 ymax)
  225. {
  226. v3s16 em = vm->m_area.getExtent();
  227. u32 i = vm->m_area.index(p2d.X, ymax, p2d.Y);
  228. s16 y;
  229. for (y = ymax; y >= ymin; y--) {
  230. MapNode &n = vm->m_data[i];
  231. if (ndef->get(n).walkable)
  232. return -MAX_MAP_GENERATION_LIMIT;
  233. else if (ndef->get(n).isLiquid())
  234. break;
  235. vm->m_area.add_y(em, i, -1);
  236. }
  237. return (y >= ymin) ? y : -MAX_MAP_GENERATION_LIMIT;
  238. }
  239. void Mapgen::updateHeightmap(v3s16 nmin, v3s16 nmax)
  240. {
  241. if (!heightmap)
  242. return;
  243. //TimeTaker t("Mapgen::updateHeightmap", NULL, PRECISION_MICRO);
  244. int index = 0;
  245. for (s16 z = nmin.Z; z <= nmax.Z; z++) {
  246. for (s16 x = nmin.X; x <= nmax.X; x++, index++) {
  247. s16 y = findGroundLevel(v2s16(x, z), nmin.Y, nmax.Y);
  248. heightmap[index] = y;
  249. }
  250. }
  251. }
  252. inline bool Mapgen::isLiquidHorizontallyFlowable(u32 vi, v3s16 em)
  253. {
  254. u32 vi_neg_x = vi;
  255. vm->m_area.add_x(em, vi_neg_x, -1);
  256. if (vm->m_data[vi_neg_x].getContent() != CONTENT_IGNORE) {
  257. const ContentFeatures &c_nx = ndef->get(vm->m_data[vi_neg_x]);
  258. if (c_nx.floodable && !c_nx.isLiquid())
  259. return true;
  260. }
  261. u32 vi_pos_x = vi;
  262. vm->m_area.add_x(em, vi_pos_x, +1);
  263. if (vm->m_data[vi_pos_x].getContent() != CONTENT_IGNORE) {
  264. const ContentFeatures &c_px = ndef->get(vm->m_data[vi_pos_x]);
  265. if (c_px.floodable && !c_px.isLiquid())
  266. return true;
  267. }
  268. u32 vi_neg_z = vi;
  269. vm->m_area.add_z(em, vi_neg_z, -1);
  270. if (vm->m_data[vi_neg_z].getContent() != CONTENT_IGNORE) {
  271. const ContentFeatures &c_nz = ndef->get(vm->m_data[vi_neg_z]);
  272. if (c_nz.floodable && !c_nz.isLiquid())
  273. return true;
  274. }
  275. u32 vi_pos_z = vi;
  276. vm->m_area.add_z(em, vi_pos_z, +1);
  277. if (vm->m_data[vi_pos_z].getContent() != CONTENT_IGNORE) {
  278. const ContentFeatures &c_pz = ndef->get(vm->m_data[vi_pos_z]);
  279. if (c_pz.floodable && !c_pz.isLiquid())
  280. return true;
  281. }
  282. return false;
  283. }
  284. void Mapgen::updateLiquid(UniqueQueue<v3s16> *trans_liquid, v3s16 nmin, v3s16 nmax)
  285. {
  286. bool isignored, isliquid, wasignored, wasliquid, waschecked, waspushed;
  287. v3s16 em = vm->m_area.getExtent();
  288. for (s16 z = nmin.Z + 1; z <= nmax.Z - 1; z++)
  289. for (s16 x = nmin.X + 1; x <= nmax.X - 1; x++) {
  290. wasignored = true;
  291. wasliquid = false;
  292. waschecked = false;
  293. waspushed = false;
  294. u32 vi = vm->m_area.index(x, nmax.Y, z);
  295. for (s16 y = nmax.Y; y >= nmin.Y; y--) {
  296. isignored = vm->m_data[vi].getContent() == CONTENT_IGNORE;
  297. isliquid = ndef->get(vm->m_data[vi]).isLiquid();
  298. if (isignored || wasignored || isliquid == wasliquid) {
  299. // Neither topmost node of liquid column nor topmost node below column
  300. waschecked = false;
  301. waspushed = false;
  302. } else if (isliquid) {
  303. // This is the topmost node in the column
  304. bool ispushed = false;
  305. if (isLiquidHorizontallyFlowable(vi, em)) {
  306. trans_liquid->push_back(v3s16(x, y, z));
  307. ispushed = true;
  308. }
  309. // Remember waschecked and waspushed to avoid repeated
  310. // checks/pushes in case the column consists of only this node
  311. waschecked = true;
  312. waspushed = ispushed;
  313. } else {
  314. // This is the topmost node below a liquid column
  315. u32 vi_above = vi;
  316. vm->m_area.add_y(em, vi_above, 1);
  317. if (!waspushed && (ndef->get(vm->m_data[vi]).floodable ||
  318. (!waschecked && isLiquidHorizontallyFlowable(vi_above, em)))) {
  319. // Push back the lowest node in the column which is one
  320. // node above this one
  321. trans_liquid->push_back(v3s16(x, y + 1, z));
  322. }
  323. }
  324. wasliquid = isliquid;
  325. wasignored = isignored;
  326. vm->m_area.add_y(em, vi, -1);
  327. }
  328. }
  329. }
  330. void Mapgen::setLighting(u8 light, v3s16 nmin, v3s16 nmax)
  331. {
  332. ScopeProfiler sp(g_profiler, "EmergeThread: mapgen lighting update", SPT_AVG);
  333. VoxelArea a(nmin, nmax);
  334. for (int z = a.MinEdge.Z; z <= a.MaxEdge.Z; z++) {
  335. for (int y = a.MinEdge.Y; y <= a.MaxEdge.Y; y++) {
  336. u32 i = vm->m_area.index(a.MinEdge.X, y, z);
  337. for (int x = a.MinEdge.X; x <= a.MaxEdge.X; x++, i++)
  338. vm->m_data[i].param1 = light;
  339. }
  340. }
  341. }
  342. void Mapgen::lightSpread(VoxelArea &a, v3s16 p, u8 light)
  343. {
  344. if (light <= 1 || !a.contains(p))
  345. return;
  346. u32 vi = vm->m_area.index(p);
  347. MapNode &n = vm->m_data[vi];
  348. // Decay light in each of the banks separately
  349. u8 light_day = light & 0x0F;
  350. if (light_day > 0)
  351. light_day -= 0x01;
  352. u8 light_night = light & 0xF0;
  353. if (light_night > 0)
  354. light_night -= 0x10;
  355. // Bail out only if we have no more light from either bank to propogate, or
  356. // we hit a solid block that light cannot pass through.
  357. if ((light_day <= (n.param1 & 0x0F) &&
  358. light_night <= (n.param1 & 0xF0)) ||
  359. !ndef->get(n).light_propagates)
  360. return;
  361. // Since this recursive function only terminates when there is no light from
  362. // either bank left, we need to take the max of both banks into account for
  363. // the case where spreading has stopped for one light bank but not the other.
  364. light = MYMAX(light_day, n.param1 & 0x0F) |
  365. MYMAX(light_night, n.param1 & 0xF0);
  366. n.param1 = light;
  367. lightSpread(a, p + v3s16(0, 0, 1), light);
  368. lightSpread(a, p + v3s16(0, 1, 0), light);
  369. lightSpread(a, p + v3s16(1, 0, 0), light);
  370. lightSpread(a, p - v3s16(0, 0, 1), light);
  371. lightSpread(a, p - v3s16(0, 1, 0), light);
  372. lightSpread(a, p - v3s16(1, 0, 0), light);
  373. }
  374. void Mapgen::calcLighting(v3s16 nmin, v3s16 nmax, v3s16 full_nmin, v3s16 full_nmax,
  375. bool propagate_shadow)
  376. {
  377. ScopeProfiler sp(g_profiler, "EmergeThread: mapgen lighting update", SPT_AVG);
  378. //TimeTaker t("updateLighting");
  379. propagateSunlight(nmin, nmax, propagate_shadow);
  380. spreadLight(full_nmin, full_nmax);
  381. //printf("updateLighting: %dms\n", t.stop());
  382. }
  383. void Mapgen::propagateSunlight(v3s16 nmin, v3s16 nmax, bool propagate_shadow)
  384. {
  385. //TimeTaker t("propagateSunlight");
  386. VoxelArea a(nmin, nmax);
  387. bool block_is_underground = (water_level >= nmax.Y);
  388. v3s16 em = vm->m_area.getExtent();
  389. // NOTE: Direct access to the low 4 bits of param1 is okay here because,
  390. // by definition, sunlight will never be in the night lightbank.
  391. for (int z = a.MinEdge.Z; z <= a.MaxEdge.Z; z++) {
  392. for (int x = a.MinEdge.X; x <= a.MaxEdge.X; x++) {
  393. // see if we can get a light value from the overtop
  394. u32 i = vm->m_area.index(x, a.MaxEdge.Y + 1, z);
  395. if (vm->m_data[i].getContent() == CONTENT_IGNORE) {
  396. if (block_is_underground)
  397. continue;
  398. } else if ((vm->m_data[i].param1 & 0x0F) != LIGHT_SUN &&
  399. propagate_shadow) {
  400. continue;
  401. }
  402. vm->m_area.add_y(em, i, -1);
  403. for (int y = a.MaxEdge.Y; y >= a.MinEdge.Y; y--) {
  404. MapNode &n = vm->m_data[i];
  405. if (!ndef->get(n).sunlight_propagates)
  406. break;
  407. n.param1 = LIGHT_SUN;
  408. vm->m_area.add_y(em, i, -1);
  409. }
  410. }
  411. }
  412. //printf("propagateSunlight: %dms\n", t.stop());
  413. }
  414. void Mapgen::spreadLight(v3s16 nmin, v3s16 nmax)
  415. {
  416. //TimeTaker t("spreadLight");
  417. VoxelArea a(nmin, nmax);
  418. for (int z = a.MinEdge.Z; z <= a.MaxEdge.Z; z++) {
  419. for (int y = a.MinEdge.Y; y <= a.MaxEdge.Y; y++) {
  420. u32 i = vm->m_area.index(a.MinEdge.X, y, z);
  421. for (int x = a.MinEdge.X; x <= a.MaxEdge.X; x++, i++) {
  422. MapNode &n = vm->m_data[i];
  423. if (n.getContent() == CONTENT_IGNORE)
  424. continue;
  425. const ContentFeatures &cf = ndef->get(n);
  426. if (!cf.light_propagates)
  427. continue;
  428. // TODO(hmmmmm): Abstract away direct param1 accesses with a
  429. // wrapper, but something lighter than MapNode::get/setLight
  430. u8 light_produced = cf.light_source;
  431. if (light_produced)
  432. n.param1 = light_produced | (light_produced << 4);
  433. u8 light = n.param1;
  434. if (light) {
  435. lightSpread(a, v3s16(x, y, z + 1), light);
  436. lightSpread(a, v3s16(x, y + 1, z ), light);
  437. lightSpread(a, v3s16(x + 1, y, z ), light);
  438. lightSpread(a, v3s16(x, y, z - 1), light);
  439. lightSpread(a, v3s16(x, y - 1, z ), light);
  440. lightSpread(a, v3s16(x - 1, y, z ), light);
  441. }
  442. }
  443. }
  444. }
  445. //printf("spreadLight: %dms\n", t.stop());
  446. }
  447. ////
  448. //// MapgenBasic
  449. ////
  450. MapgenBasic::MapgenBasic(int mapgenid, MapgenParams *params, EmergeManager *emerge)
  451. : Mapgen(mapgenid, params, emerge)
  452. {
  453. this->m_emerge = emerge;
  454. this->m_bmgr = emerge->biomemgr;
  455. //// Here, 'stride' refers to the number of elements needed to skip to index
  456. //// an adjacent element for that coordinate in noise/height/biome maps
  457. //// (*not* vmanip content map!)
  458. // Note there is no X stride explicitly defined. Items adjacent in the X
  459. // coordinate are assumed to be adjacent in memory as well (i.e. stride of 1).
  460. // Number of elements to skip to get to the next Y coordinate
  461. this->ystride = csize.X;
  462. // Number of elements to skip to get to the next Z coordinate
  463. this->zstride = csize.X * csize.Y;
  464. // Z-stride value for maps oversized for 1-down overgeneration
  465. this->zstride_1d = csize.X * (csize.Y + 1);
  466. // Z-stride value for maps oversized for 1-up 1-down overgeneration
  467. this->zstride_1u1d = csize.X * (csize.Y + 2);
  468. //// Allocate heightmap
  469. this->heightmap = new s16[csize.X * csize.Z];
  470. //// Initialize biome generator
  471. // TODO(hmmmm): should we have a way to disable biomemanager biomes?
  472. biomegen = m_bmgr->createBiomeGen(BIOMEGEN_ORIGINAL, params->bparams, csize);
  473. biomemap = biomegen->biomemap;
  474. //// Look up some commonly used content
  475. c_stone = ndef->getId("mapgen_stone");
  476. c_desert_stone = ndef->getId("mapgen_desert_stone");
  477. c_sandstone = ndef->getId("mapgen_sandstone");
  478. c_water_source = ndef->getId("mapgen_water_source");
  479. c_river_water_source = ndef->getId("mapgen_river_water_source");
  480. c_lava_source = ndef->getId("mapgen_lava_source");
  481. // Fall back to more basic content if not defined
  482. // river_water_source cannot fallback to water_source because river water
  483. // needs to be non-renewable and have a short flow range.
  484. if (c_desert_stone == CONTENT_IGNORE)
  485. c_desert_stone = c_stone;
  486. if (c_sandstone == CONTENT_IGNORE)
  487. c_sandstone = c_stone;
  488. //// Content used for dungeon generation
  489. c_cobble = ndef->getId("mapgen_cobble");
  490. c_mossycobble = ndef->getId("mapgen_mossycobble");
  491. c_stair_cobble = ndef->getId("mapgen_stair_cobble");
  492. c_stair_desert_stone = ndef->getId("mapgen_stair_desert_stone");
  493. c_sandstonebrick = ndef->getId("mapgen_sandstonebrick");
  494. c_stair_sandstone_block = ndef->getId("mapgen_stair_sandstone_block");
  495. // Fall back to more basic content if not defined
  496. if (c_mossycobble == CONTENT_IGNORE)
  497. c_mossycobble = c_cobble;
  498. if (c_stair_cobble == CONTENT_IGNORE)
  499. c_stair_cobble = c_cobble;
  500. if (c_stair_desert_stone == CONTENT_IGNORE)
  501. c_stair_desert_stone = c_desert_stone;
  502. if (c_sandstonebrick == CONTENT_IGNORE)
  503. c_sandstonebrick = c_sandstone;
  504. if (c_stair_sandstone_block == CONTENT_IGNORE)
  505. c_stair_sandstone_block = c_sandstonebrick;
  506. }
  507. MapgenBasic::~MapgenBasic()
  508. {
  509. delete biomegen;
  510. delete []heightmap;
  511. }
  512. MgStoneType MapgenBasic::generateBiomes()
  513. {
  514. // can't generate biomes without a biome generator!
  515. assert(biomegen);
  516. assert(biomemap);
  517. v3s16 em = vm->m_area.getExtent();
  518. u32 index = 0;
  519. MgStoneType stone_type = MGSTONE_STONE;
  520. noise_filler_depth->perlinMap2D(node_min.X, node_min.Z);
  521. for (s16 z = node_min.Z; z <= node_max.Z; z++)
  522. for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
  523. Biome *biome = NULL;
  524. u16 depth_top = 0;
  525. u16 base_filler = 0;
  526. u16 depth_water_top = 0;
  527. u16 depth_riverbed = 0;
  528. u32 vi = vm->m_area.index(x, node_max.Y, z);
  529. // Check node at base of mapchunk above, either a node of a previously
  530. // generated mapchunk or if not, a node of overgenerated base terrain.
  531. content_t c_above = vm->m_data[vi + em.X].getContent();
  532. bool air_above = c_above == CONTENT_AIR;
  533. bool river_water_above = c_above == c_river_water_source;
  534. bool water_above = c_above == c_water_source || river_water_above;
  535. biomemap[index] = BIOME_NONE;
  536. // If there is air or water above enable top/filler placement, otherwise force
  537. // nplaced to stone level by setting a number exceeding any possible filler depth.
  538. u16 nplaced = (air_above || water_above) ? 0 : U16_MAX;
  539. for (s16 y = node_max.Y; y >= node_min.Y; y--) {
  540. content_t c = vm->m_data[vi].getContent();
  541. // Biome is recalculated each time an upper surface is detected while
  542. // working down a column. The selected biome then remains in effect for
  543. // all nodes below until the next surface and biome recalculation.
  544. // Biome is recalculated:
  545. // 1. At the surface of stone below air or water.
  546. // 2. At the surface of water below air.
  547. // 3. When stone or water is detected but biome has not yet been calculated.
  548. bool is_stone_surface = (c == c_stone) &&
  549. (air_above || water_above || !biome);
  550. bool is_water_surface =
  551. (c == c_water_source || c == c_river_water_source) &&
  552. (air_above || !biome);
  553. if (is_stone_surface || is_water_surface) {
  554. biome = biomegen->getBiomeAtIndex(index, y);
  555. if (biomemap[index] == BIOME_NONE && is_stone_surface)
  556. biomemap[index] = biome->index;
  557. depth_top = biome->depth_top;
  558. base_filler = MYMAX(depth_top +
  559. biome->depth_filler +
  560. noise_filler_depth->result[index], 0.f);
  561. depth_water_top = biome->depth_water_top;
  562. depth_riverbed = biome->depth_riverbed;
  563. // Detect stone type for dungeons during every biome calculation.
  564. // This is more efficient than detecting per-node and will not
  565. // miss any desert stone or sandstone biomes.
  566. if (biome->c_stone == c_desert_stone)
  567. stone_type = MGSTONE_DESERT_STONE;
  568. else if (biome->c_stone == c_sandstone)
  569. stone_type = MGSTONE_SANDSTONE;
  570. }
  571. if (c == c_stone) {
  572. content_t c_below = vm->m_data[vi - em.X].getContent();
  573. // If the node below isn't solid, make this node stone, so that
  574. // any top/filler nodes above are structurally supported.
  575. // This is done by aborting the cycle of top/filler placement
  576. // immediately by forcing nplaced to stone level.
  577. if (c_below == CONTENT_AIR
  578. || c_below == c_water_source
  579. || c_below == c_river_water_source)
  580. nplaced = U16_MAX;
  581. if (river_water_above) {
  582. if (nplaced < depth_riverbed) {
  583. vm->m_data[vi] = MapNode(biome->c_riverbed);
  584. nplaced++;
  585. } else {
  586. nplaced = U16_MAX; // Disable top/filler placement
  587. river_water_above = false;
  588. }
  589. } else if (nplaced < depth_top) {
  590. vm->m_data[vi] = MapNode(biome->c_top);
  591. nplaced++;
  592. } else if (nplaced < base_filler) {
  593. vm->m_data[vi] = MapNode(biome->c_filler);
  594. nplaced++;
  595. } else {
  596. vm->m_data[vi] = MapNode(biome->c_stone);
  597. }
  598. air_above = false;
  599. water_above = false;
  600. } else if (c == c_water_source) {
  601. vm->m_data[vi] = MapNode((y > (s32)(water_level - depth_water_top))
  602. ? biome->c_water_top : biome->c_water);
  603. nplaced = 0; // Enable top/filler placement for next surface
  604. air_above = false;
  605. water_above = true;
  606. } else if (c == c_river_water_source) {
  607. vm->m_data[vi] = MapNode(biome->c_river_water);
  608. nplaced = 0; // Enable riverbed placement for next surface
  609. air_above = false;
  610. water_above = true;
  611. river_water_above = true;
  612. } else if (c == CONTENT_AIR) {
  613. nplaced = 0; // Enable top/filler placement for next surface
  614. air_above = true;
  615. water_above = false;
  616. } else { // Possible various nodes overgenerated from neighbouring mapchunks
  617. nplaced = U16_MAX; // Disable top/filler placement
  618. air_above = false;
  619. water_above = false;
  620. }
  621. vm->m_area.add_y(em, vi, -1);
  622. }
  623. }
  624. return stone_type;
  625. }
  626. void MapgenBasic::dustTopNodes()
  627. {
  628. if (node_max.Y < water_level)
  629. return;
  630. v3s16 em = vm->m_area.getExtent();
  631. u32 index = 0;
  632. for (s16 z = node_min.Z; z <= node_max.Z; z++)
  633. for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
  634. Biome *biome = (Biome *)m_bmgr->getRaw(biomemap[index]);
  635. if (biome->c_dust == CONTENT_IGNORE)
  636. continue;
  637. u32 vi = vm->m_area.index(x, full_node_max.Y, z);
  638. content_t c_full_max = vm->m_data[vi].getContent();
  639. s16 y_start;
  640. if (c_full_max == CONTENT_AIR) {
  641. y_start = full_node_max.Y - 1;
  642. } else if (c_full_max == CONTENT_IGNORE) {
  643. vi = vm->m_area.index(x, node_max.Y + 1, z);
  644. content_t c_max = vm->m_data[vi].getContent();
  645. if (c_max == CONTENT_AIR)
  646. y_start = node_max.Y;
  647. else
  648. continue;
  649. } else {
  650. continue;
  651. }
  652. vi = vm->m_area.index(x, y_start, z);
  653. for (s16 y = y_start; y >= node_min.Y - 1; y--) {
  654. if (vm->m_data[vi].getContent() != CONTENT_AIR)
  655. break;
  656. vm->m_area.add_y(em, vi, -1);
  657. }
  658. content_t c = vm->m_data[vi].getContent();
  659. if (!ndef->get(c).buildable_to && c != CONTENT_IGNORE && c != biome->c_dust) {
  660. vm->m_area.add_y(em, vi, 1);
  661. vm->m_data[vi] = MapNode(biome->c_dust);
  662. }
  663. }
  664. }
  665. void MapgenBasic::generateCaves(s16 max_stone_y, s16 large_cave_depth)
  666. {
  667. if (max_stone_y < node_min.Y)
  668. return;
  669. CavesNoiseIntersection caves_noise(ndef, m_bmgr, csize,
  670. &np_cave1, &np_cave2, seed, cave_width);
  671. caves_noise.generateCaves(vm, node_min, node_max, biomemap);
  672. if (node_max.Y > large_cave_depth)
  673. return;
  674. PseudoRandom ps(blockseed + 21343);
  675. u32 bruises_count = ps.range(0, 2);
  676. for (u32 i = 0; i < bruises_count; i++) {
  677. CavesRandomWalk cave(ndef, &gennotify, seed, water_level,
  678. c_water_source, CONTENT_IGNORE);
  679. cave.makeCave(vm, node_min, node_max, &ps, true, max_stone_y, heightmap);
  680. }
  681. }
  682. bool MapgenBasic::generateCaverns(s16 max_stone_y)
  683. {
  684. if (node_min.Y > max_stone_y || node_min.Y > cavern_limit)
  685. return false;
  686. CavernsNoise caverns_noise(ndef, csize, &np_cavern,
  687. seed, cavern_limit, cavern_taper, cavern_threshold);
  688. return caverns_noise.generateCaverns(vm, node_min, node_max);
  689. }
  690. void MapgenBasic::generateDungeons(s16 max_stone_y, MgStoneType stone_type)
  691. {
  692. if (max_stone_y < node_min.Y)
  693. return;
  694. DungeonParams dp;
  695. dp.seed = seed;
  696. dp.c_water = c_water_source;
  697. dp.c_river_water = c_river_water_source;
  698. dp.only_in_ground = true;
  699. dp.corridor_len_min = 1;
  700. dp.corridor_len_max = 13;
  701. dp.rooms_min = 2;
  702. dp.rooms_max = 16;
  703. dp.y_min = -MAX_MAP_GENERATION_LIMIT;
  704. dp.y_max = MAX_MAP_GENERATION_LIMIT;
  705. dp.np_density = nparams_dungeon_density;
  706. dp.np_alt_wall = nparams_dungeon_alt_wall;
  707. switch (stone_type) {
  708. default:
  709. case MGSTONE_STONE:
  710. dp.c_wall = c_cobble;
  711. dp.c_alt_wall = c_mossycobble;
  712. dp.c_stair = c_stair_cobble;
  713. dp.diagonal_dirs = false;
  714. dp.holesize = v3s16(1, 2, 1);
  715. dp.room_size_min = v3s16(4, 4, 4);
  716. dp.room_size_max = v3s16(8, 6, 8);
  717. dp.room_size_large_min = v3s16(8, 8, 8);
  718. dp.room_size_large_max = v3s16(16, 16, 16);
  719. dp.notifytype = GENNOTIFY_DUNGEON;
  720. break;
  721. case MGSTONE_DESERT_STONE:
  722. dp.c_wall = c_desert_stone;
  723. dp.c_alt_wall = CONTENT_IGNORE;
  724. dp.c_stair = c_stair_desert_stone;
  725. dp.diagonal_dirs = true;
  726. dp.holesize = v3s16(2, 3, 2);
  727. dp.room_size_min = v3s16(6, 9, 6);
  728. dp.room_size_max = v3s16(10, 11, 10);
  729. dp.room_size_large_min = v3s16(10, 13, 10);
  730. dp.room_size_large_max = v3s16(18, 21, 18);
  731. dp.notifytype = GENNOTIFY_TEMPLE;
  732. break;
  733. case MGSTONE_SANDSTONE:
  734. dp.c_wall = c_sandstonebrick;
  735. dp.c_alt_wall = CONTENT_IGNORE;
  736. dp.c_stair = c_stair_sandstone_block;
  737. dp.diagonal_dirs = false;
  738. dp.holesize = v3s16(2, 2, 2);
  739. dp.room_size_min = v3s16(6, 4, 6);
  740. dp.room_size_max = v3s16(10, 6, 10);
  741. dp.room_size_large_min = v3s16(10, 8, 10);
  742. dp.room_size_large_max = v3s16(18, 16, 18);
  743. dp.notifytype = GENNOTIFY_DUNGEON;
  744. break;
  745. }
  746. DungeonGen dgen(ndef, &gennotify, &dp);
  747. dgen.generate(vm, blockseed, full_node_min, full_node_max);
  748. }
  749. ////
  750. //// GenerateNotifier
  751. ////
  752. GenerateNotifier::GenerateNotifier()
  753. {
  754. }
  755. GenerateNotifier::GenerateNotifier(u32 notify_on,
  756. std::set<u32> *notify_on_deco_ids)
  757. {
  758. m_notify_on = notify_on;
  759. m_notify_on_deco_ids = notify_on_deco_ids;
  760. }
  761. void GenerateNotifier::setNotifyOn(u32 notify_on)
  762. {
  763. m_notify_on = notify_on;
  764. }
  765. void GenerateNotifier::setNotifyOnDecoIds(std::set<u32> *notify_on_deco_ids)
  766. {
  767. m_notify_on_deco_ids = notify_on_deco_ids;
  768. }
  769. bool GenerateNotifier::addEvent(GenNotifyType type, v3s16 pos, u32 id)
  770. {
  771. if (!(m_notify_on & (1 << type)))
  772. return false;
  773. if (type == GENNOTIFY_DECORATION &&
  774. m_notify_on_deco_ids->find(id) == m_notify_on_deco_ids->end())
  775. return false;
  776. GenNotifyEvent gne;
  777. gne.type = type;
  778. gne.pos = pos;
  779. gne.id = id;
  780. m_notify_events.push_back(gne);
  781. return true;
  782. }
  783. void GenerateNotifier::getEvents(
  784. std::map<std::string, std::vector<v3s16> > &event_map,
  785. bool peek_events)
  786. {
  787. std::list<GenNotifyEvent>::iterator it;
  788. for (it = m_notify_events.begin(); it != m_notify_events.end(); ++it) {
  789. GenNotifyEvent &gn = *it;
  790. std::string name = (gn.type == GENNOTIFY_DECORATION) ?
  791. "decoration#"+ itos(gn.id) :
  792. flagdesc_gennotify[gn.type].name;
  793. event_map[name].push_back(gn.pos);
  794. }
  795. if (!peek_events)
  796. m_notify_events.clear();
  797. }
  798. ////
  799. //// MapgenParams
  800. ////
  801. MapgenParams::~MapgenParams()
  802. {
  803. delete bparams;
  804. }
  805. void MapgenParams::readParams(const Settings *settings)
  806. {
  807. std::string seed_str;
  808. const char *seed_name = (settings == g_settings) ? "fixed_map_seed" : "seed";
  809. if (settings->getNoEx(seed_name, seed_str)) {
  810. if (!seed_str.empty())
  811. seed = read_seed(seed_str.c_str());
  812. else
  813. myrand_bytes(&seed, sizeof(seed));
  814. }
  815. std::string mg_name;
  816. if (settings->getNoEx("mg_name", mg_name)) {
  817. mgtype = Mapgen::getMapgenType(mg_name);
  818. if (mgtype == MAPGEN_INVALID)
  819. mgtype = MAPGEN_DEFAULT;
  820. }
  821. settings->getS16NoEx("water_level", water_level);
  822. settings->getS16NoEx("mapgen_limit", mapgen_limit);
  823. settings->getS16NoEx("chunksize", chunksize);
  824. settings->getFlagStrNoEx("mg_flags", flags, flagdesc_mapgen);
  825. delete bparams;
  826. bparams = BiomeManager::createBiomeParams(BIOMEGEN_ORIGINAL);
  827. if (bparams) {
  828. bparams->readParams(settings);
  829. bparams->seed = seed;
  830. }
  831. }
  832. void MapgenParams::writeParams(Settings *settings) const
  833. {
  834. settings->set("mg_name", Mapgen::getMapgenName(mgtype));
  835. settings->setU64("seed", seed);
  836. settings->setS16("water_level", water_level);
  837. settings->setS16("mapgen_limit", mapgen_limit);
  838. settings->setS16("chunksize", chunksize);
  839. settings->setFlagStr("mg_flags", flags, flagdesc_mapgen, U32_MAX);
  840. if (bparams)
  841. bparams->writeParams(settings);
  842. }
  843. // Calculate edges of outermost generated mapchunks (less than
  844. // 'mapgen_limit'), and corresponding exact limits for SAO entities.
  845. void MapgenParams::calcMapgenEdges()
  846. {
  847. if (m_mapgen_edges_calculated)
  848. return;
  849. // Central chunk offset, in blocks
  850. s16 ccoff_b = -chunksize / 2;
  851. // Chunksize, in nodes
  852. s32 csize_n = chunksize * MAP_BLOCKSIZE;
  853. // Minp/maxp of central chunk, in nodes
  854. s16 ccmin = ccoff_b * MAP_BLOCKSIZE;
  855. s16 ccmax = ccmin + csize_n - 1;
  856. // Fullminp/fullmaxp of central chunk, in nodes
  857. s16 ccfmin = ccmin - MAP_BLOCKSIZE;
  858. s16 ccfmax = ccmax + MAP_BLOCKSIZE;
  859. // Effective mapgen limit, in blocks
  860. // Uses same calculation as ServerMap::blockpos_over_mapgen_limit(v3s16 p)
  861. s16 mapgen_limit_b = rangelim(mapgen_limit,
  862. 0, MAX_MAP_GENERATION_LIMIT) / MAP_BLOCKSIZE;
  863. // Effective mapgen limits, in nodes
  864. s16 mapgen_limit_min = -mapgen_limit_b * MAP_BLOCKSIZE;
  865. s16 mapgen_limit_max = (mapgen_limit_b + 1) * MAP_BLOCKSIZE - 1;
  866. // Number of complete chunks from central chunk fullminp/fullmaxp
  867. // to effective mapgen limits.
  868. s16 numcmin = MYMAX((ccfmin - mapgen_limit_min) / csize_n, 0);
  869. s16 numcmax = MYMAX((mapgen_limit_max - ccfmax) / csize_n, 0);
  870. // Mapgen edges, in nodes
  871. mapgen_edge_min = ccmin - numcmin * csize_n;
  872. mapgen_edge_max = ccmax + numcmax * csize_n;
  873. // SAO position limits, in Irrlicht units
  874. m_sao_limit_min = mapgen_edge_min * BS - 3.0f;
  875. m_sao_limit_max = mapgen_edge_max * BS + 3.0f;
  876. m_mapgen_edges_calculated = true;
  877. }
  878. bool MapgenParams::saoPosOverLimit(const v3f &p)
  879. {
  880. if (!m_mapgen_edges_calculated)
  881. calcMapgenEdges();
  882. return p.X < m_sao_limit_min ||
  883. p.X > m_sao_limit_max ||
  884. p.Y < m_sao_limit_min ||
  885. p.Y > m_sao_limit_max ||
  886. p.Z < m_sao_limit_min ||
  887. p.Z > m_sao_limit_max;
  888. }
  889. s32 MapgenParams::getSpawnRangeMax()
  890. {
  891. calcMapgenEdges();
  892. return MYMIN(-mapgen_edge_min, mapgen_edge_max);
  893. }