mapgen.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122
  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 "biome.h"
  20. #include "mapblock.h"
  21. #include "mapnode.h"
  22. #include "map.h"
  23. //#include "serverobject.h"
  24. #include "content_sao.h"
  25. #include "nodedef.h"
  26. #include "content_mapnode.h" // For content_mapnode_get_new_name
  27. #include "voxelalgorithms.h"
  28. #include "profiler.h"
  29. #include "settings.h" // For g_settings
  30. #include "main.h" // For g_profiler
  31. #include "treegen.h"
  32. #include "mapgen_v6.h"
  33. #include "mapgen_v7.h"
  34. #include "serialization.h"
  35. #include "util/serialize.h"
  36. #include "filesys.h"
  37. FlagDesc flagdesc_mapgen[] = {
  38. {"trees", MG_TREES},
  39. {"caves", MG_CAVES},
  40. {"dungeons", MG_DUNGEONS},
  41. {"flat", MG_FLAT},
  42. {"light", MG_LIGHT},
  43. {NULL, 0}
  44. };
  45. FlagDesc flagdesc_ore[] = {
  46. {"absheight", OREFLAG_ABSHEIGHT},
  47. {"scatter_noisedensity", OREFLAG_DENSITY},
  48. {"claylike_nodeisnt", OREFLAG_NODEISNT},
  49. {NULL, 0}
  50. };
  51. FlagDesc flagdesc_deco_schematic[] = {
  52. {"place_center_x", DECO_PLACE_CENTER_X},
  53. {"place_center_y", DECO_PLACE_CENTER_Y},
  54. {"place_center_z", DECO_PLACE_CENTER_Z},
  55. {NULL, 0}
  56. };
  57. FlagDesc flagdesc_gennotify[] = {
  58. {"dungeon", 1 << GENNOTIFY_DUNGEON},
  59. {"temple", 1 << GENNOTIFY_TEMPLE},
  60. {"cave_begin", 1 << GENNOTIFY_CAVE_BEGIN},
  61. {"cave_end", 1 << GENNOTIFY_CAVE_END},
  62. {"large_cave_begin", 1 << GENNOTIFY_LARGECAVE_BEGIN},
  63. {"large_cave_end", 1 << GENNOTIFY_LARGECAVE_END},
  64. {NULL, 0}
  65. };
  66. ///////////////////////////////////////////////////////////////////////////////
  67. Ore *createOre(OreType type) {
  68. switch (type) {
  69. case ORE_SCATTER:
  70. return new OreScatter;
  71. case ORE_SHEET:
  72. return new OreSheet;
  73. //case ORE_CLAYLIKE: //TODO: implement this!
  74. // return new OreClaylike;
  75. default:
  76. return NULL;
  77. }
  78. }
  79. Ore::~Ore() {
  80. delete np;
  81. delete noise;
  82. }
  83. void Ore::resolveNodeNames(INodeDefManager *ndef) {
  84. if (ore == CONTENT_IGNORE) {
  85. ore = ndef->getId(ore_name);
  86. if (ore == CONTENT_IGNORE) {
  87. errorstream << "Ore::resolveNodeNames: ore node '"
  88. << ore_name << "' not defined";
  89. ore = CONTENT_AIR;
  90. wherein.push_back(CONTENT_AIR);
  91. return;
  92. }
  93. }
  94. for (size_t i=0; i != wherein_names.size(); i++) {
  95. std::string name = wherein_names[i];
  96. content_t c = ndef->getId(name);
  97. if (c != CONTENT_IGNORE) {
  98. wherein.push_back(c);
  99. }
  100. }
  101. }
  102. void Ore::placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) {
  103. int in_range = 0;
  104. in_range |= (nmin.Y <= height_max && nmax.Y >= height_min);
  105. if (flags & OREFLAG_ABSHEIGHT)
  106. in_range |= (nmin.Y >= -height_max && nmax.Y <= -height_min) << 1;
  107. if (!in_range)
  108. return;
  109. int ymin, ymax;
  110. if (in_range & ORE_RANGE_MIRROR) {
  111. ymin = MYMAX(nmin.Y, -height_max);
  112. ymax = MYMIN(nmax.Y, -height_min);
  113. } else {
  114. ymin = MYMAX(nmin.Y, height_min);
  115. ymax = MYMIN(nmax.Y, height_max);
  116. }
  117. if (clust_size >= ymax - ymin + 1)
  118. return;
  119. nmin.Y = ymin;
  120. nmax.Y = ymax;
  121. generate(mg->vm, mg->seed, blockseed, nmin, nmax);
  122. }
  123. void OreScatter::generate(ManualMapVoxelManipulator *vm, int seed,
  124. u32 blockseed, v3s16 nmin, v3s16 nmax) {
  125. PseudoRandom pr(blockseed);
  126. MapNode n_ore(ore, 0, ore_param2);
  127. int volume = (nmax.X - nmin.X + 1) *
  128. (nmax.Y - nmin.Y + 1) *
  129. (nmax.Z - nmin.Z + 1);
  130. int csize = clust_size;
  131. int orechance = (csize * csize * csize) / clust_num_ores;
  132. int nclusters = volume / clust_scarcity;
  133. for (int i = 0; i != nclusters; i++) {
  134. int x0 = pr.range(nmin.X, nmax.X - csize + 1);
  135. int y0 = pr.range(nmin.Y, nmax.Y - csize + 1);
  136. int z0 = pr.range(nmin.Z, nmax.Z - csize + 1);
  137. if (np && (NoisePerlin3D(np, x0, y0, z0, seed) < nthresh))
  138. continue;
  139. for (int z1 = 0; z1 != csize; z1++)
  140. for (int y1 = 0; y1 != csize; y1++)
  141. for (int x1 = 0; x1 != csize; x1++) {
  142. if (pr.range(1, orechance) != 1)
  143. continue;
  144. u32 i = vm->m_area.index(x0 + x1, y0 + y1, z0 + z1);
  145. for (size_t ii = 0; ii < wherein.size(); ii++)
  146. if (vm->m_data[i].getContent() == wherein[ii])
  147. vm->m_data[i] = n_ore;
  148. }
  149. }
  150. }
  151. void OreSheet::generate(ManualMapVoxelManipulator *vm, int seed,
  152. u32 blockseed, v3s16 nmin, v3s16 nmax) {
  153. PseudoRandom pr(blockseed + 4234);
  154. MapNode n_ore(ore, 0, ore_param2);
  155. int max_height = clust_size;
  156. int y_start = pr.range(nmin.Y, nmax.Y - max_height);
  157. if (!noise) {
  158. int sx = nmax.X - nmin.X + 1;
  159. int sz = nmax.Z - nmin.Z + 1;
  160. noise = new Noise(np, 0, sx, sz);
  161. }
  162. noise->seed = seed + y_start;
  163. noise->perlinMap2D(nmin.X, nmin.Z);
  164. int index = 0;
  165. for (int z = nmin.Z; z <= nmax.Z; z++)
  166. for (int x = nmin.X; x <= nmax.X; x++) {
  167. float noiseval = noise->result[index++];
  168. if (noiseval < nthresh)
  169. continue;
  170. int height = max_height * (1. / pr.range(1, 3));
  171. int y0 = y_start + np->scale * noiseval; //pr.range(1, 3) - 1;
  172. int y1 = y0 + height;
  173. for (int y = y0; y != y1; y++) {
  174. u32 i = vm->m_area.index(x, y, z);
  175. if (!vm->m_area.contains(i))
  176. continue;
  177. for (size_t ii = 0; ii < wherein.size(); ii++)
  178. if (vm->m_data[i].getContent() == wherein[ii])
  179. vm->m_data[i] = n_ore;
  180. }
  181. }
  182. }
  183. ///////////////////////////////////////////////////////////////////////////////
  184. Decoration *createDecoration(DecorationType type) {
  185. switch (type) {
  186. case DECO_SIMPLE:
  187. return new DecoSimple;
  188. case DECO_SCHEMATIC:
  189. return new DecoSchematic;
  190. //case DECO_LSYSTEM:
  191. // return new DecoLSystem;
  192. default:
  193. return NULL;
  194. }
  195. }
  196. Decoration::Decoration() {
  197. mapseed = 0;
  198. np = NULL;
  199. fill_ratio = 0;
  200. sidelen = 1;
  201. }
  202. Decoration::~Decoration() {
  203. delete np;
  204. }
  205. void Decoration::resolveNodeNames(INodeDefManager *ndef) {
  206. this->ndef = ndef;
  207. if (c_place_on == CONTENT_IGNORE)
  208. c_place_on = ndef->getId(place_on_name);
  209. }
  210. void Decoration::placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) {
  211. PseudoRandom ps(blockseed + 53);
  212. int carea_size = nmax.X - nmin.X + 1;
  213. // Divide area into parts
  214. if (carea_size % sidelen) {
  215. errorstream << "Decoration::placeDeco: chunk size is not divisible by "
  216. "sidelen; setting sidelen to " << carea_size << std::endl;
  217. sidelen = carea_size;
  218. }
  219. s16 divlen = carea_size / sidelen;
  220. int area = sidelen * sidelen;
  221. for (s16 z0 = 0; z0 < divlen; z0++)
  222. for (s16 x0 = 0; x0 < divlen; x0++) {
  223. v2s16 p2d_center( // Center position of part of division
  224. nmin.X + sidelen / 2 + sidelen * x0,
  225. nmin.Z + sidelen / 2 + sidelen * z0
  226. );
  227. v2s16 p2d_min( // Minimum edge of part of division
  228. nmin.X + sidelen * x0,
  229. nmin.Z + sidelen * z0
  230. );
  231. v2s16 p2d_max( // Maximum edge of part of division
  232. nmin.X + sidelen + sidelen * x0 - 1,
  233. nmin.Z + sidelen + sidelen * z0 - 1
  234. );
  235. // Amount of decorations
  236. float nval = np ?
  237. NoisePerlin2D(np, p2d_center.X, p2d_center.Y, mapseed) :
  238. fill_ratio;
  239. u32 deco_count = area * MYMAX(nval, 0.f);
  240. for (u32 i = 0; i < deco_count; i++) {
  241. s16 x = ps.range(p2d_min.X, p2d_max.X);
  242. s16 z = ps.range(p2d_min.Y, p2d_max.Y);
  243. int mapindex = carea_size * (z - nmin.Z) + (x - nmin.X);
  244. s16 y = mg->heightmap ?
  245. mg->heightmap[mapindex] :
  246. mg->findGroundLevel(v2s16(x, z), nmin.Y, nmax.Y);
  247. if (y < nmin.Y || y > nmax.Y)
  248. continue;
  249. int height = getHeight();
  250. int max_y = nmax.Y;// + MAP_BLOCKSIZE - 1;
  251. if (y + 1 + height > max_y) {
  252. continue;
  253. #if 0
  254. printf("Decoration at (%d %d %d) cut off\n", x, y, z);
  255. //add to queue
  256. JMutexAutoLock cutofflock(cutoff_mutex);
  257. cutoffs.push_back(CutoffData(x, y, z, height));
  258. #endif
  259. }
  260. if (mg->biomemap) {
  261. std::set<u8>::iterator iter;
  262. if (biomes.size()) {
  263. iter = biomes.find(mg->biomemap[mapindex]);
  264. if (iter == biomes.end())
  265. continue;
  266. }
  267. }
  268. generate(mg, &ps, max_y, v3s16(x, y, z));
  269. }
  270. }
  271. }
  272. #if 0
  273. void Decoration::placeCutoffs(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) {
  274. PseudoRandom pr(blockseed + 53);
  275. std::vector<CutoffData> handled_cutoffs;
  276. // Copy over the cutoffs we're interested in so we don't needlessly hold a lock
  277. {
  278. JMutexAutoLock cutofflock(cutoff_mutex);
  279. for (std::list<CutoffData>::iterator i = cutoffs.begin();
  280. i != cutoffs.end(); ++i) {
  281. CutoffData cutoff = *i;
  282. v3s16 p = cutoff.p;
  283. s16 height = cutoff.height;
  284. if (p.X < nmin.X || p.X > nmax.X ||
  285. p.Z < nmin.Z || p.Z > nmax.Z)
  286. continue;
  287. if (p.Y + height < nmin.Y || p.Y > nmax.Y)
  288. continue;
  289. handled_cutoffs.push_back(cutoff);
  290. }
  291. }
  292. // Generate the cutoffs
  293. for (size_t i = 0; i != handled_cutoffs.size(); i++) {
  294. v3s16 p = handled_cutoffs[i].p;
  295. s16 height = handled_cutoffs[i].height;
  296. if (p.Y + height > nmax.Y) {
  297. //printf("Decoration at (%d %d %d) cut off again!\n", p.X, p.Y, p.Z);
  298. cuttoffs.push_back(v3s16(p.X, p.Y, p.Z));
  299. }
  300. generate(mg, &pr, nmax.Y, nmin.Y - p.Y, v3s16(p.X, nmin.Y, p.Z));
  301. }
  302. // Remove cutoffs that were handled from the cutoff list
  303. {
  304. JMutexAutoLock cutofflock(cutoff_mutex);
  305. for (std::list<CutoffData>::iterator i = cutoffs.begin();
  306. i != cutoffs.end(); ++i) {
  307. for (size_t j = 0; j != handled_cutoffs.size(); j++) {
  308. CutoffData coff = *i;
  309. if (coff.p == handled_cutoffs[j].p)
  310. i = cutoffs.erase(i);
  311. }
  312. }
  313. }
  314. }
  315. #endif
  316. ///////////////////////////////////////////////////////////////////////////////
  317. void DecoSimple::resolveNodeNames(INodeDefManager *ndef) {
  318. Decoration::resolveNodeNames(ndef);
  319. if (c_deco == CONTENT_IGNORE && !decolist_names.size()) {
  320. c_deco = ndef->getId(deco_name);
  321. if (c_deco == CONTENT_IGNORE) {
  322. errorstream << "DecoSimple::resolveNodeNames: decoration node '"
  323. << deco_name << "' not defined" << std::endl;
  324. c_deco = CONTENT_AIR;
  325. }
  326. }
  327. if (c_spawnby == CONTENT_IGNORE) {
  328. c_spawnby = ndef->getId(spawnby_name);
  329. if (c_spawnby == CONTENT_IGNORE) {
  330. errorstream << "DecoSimple::resolveNodeNames: spawnby node '"
  331. << spawnby_name << "' not defined" << std::endl;
  332. nspawnby = -1;
  333. c_spawnby = CONTENT_AIR;
  334. }
  335. }
  336. if (c_decolist.size())
  337. return;
  338. for (size_t i = 0; i != decolist_names.size(); i++) {
  339. content_t c = ndef->getId(decolist_names[i]);
  340. if (c == CONTENT_IGNORE) {
  341. errorstream << "DecoSimple::resolveNodeNames: decolist node '"
  342. << decolist_names[i] << "' not defined" << std::endl;
  343. c = CONTENT_AIR;
  344. }
  345. c_decolist.push_back(c);
  346. }
  347. }
  348. void DecoSimple::generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p) {
  349. ManualMapVoxelManipulator *vm = mg->vm;
  350. u32 vi = vm->m_area.index(p);
  351. if (vm->m_data[vi].getContent() != c_place_on &&
  352. c_place_on != CONTENT_IGNORE)
  353. return;
  354. if (nspawnby != -1) {
  355. int nneighs = 0;
  356. v3s16 dirs[8] = { // a Moore neighborhood
  357. v3s16( 0, 0, 1),
  358. v3s16( 0, 0, -1),
  359. v3s16( 1, 0, 0),
  360. v3s16(-1, 0, 0),
  361. v3s16( 1, 0, 1),
  362. v3s16(-1, 0, 1),
  363. v3s16(-1, 0, -1),
  364. v3s16( 1, 0, -1)
  365. };
  366. for (int i = 0; i != 8; i++) {
  367. u32 index = vm->m_area.index(p + dirs[i]);
  368. if (vm->m_area.contains(index) &&
  369. vm->m_data[index].getContent() == c_spawnby)
  370. nneighs++;
  371. }
  372. if (nneighs < nspawnby)
  373. return;
  374. }
  375. size_t ndecos = c_decolist.size();
  376. content_t c_place = ndecos ? c_decolist[pr->range(0, ndecos - 1)] : c_deco;
  377. s16 height = (deco_height_max > 0) ?
  378. pr->range(deco_height, deco_height_max) : deco_height;
  379. height = MYMIN(height, max_y - p.Y);
  380. v3s16 em = vm->m_area.getExtent();
  381. for (int i = 0; i < height; i++) {
  382. vm->m_area.add_y(em, vi, 1);
  383. content_t c = vm->m_data[vi].getContent();
  384. if (c != CONTENT_AIR && c != CONTENT_IGNORE)
  385. break;
  386. vm->m_data[vi] = MapNode(c_place);
  387. }
  388. }
  389. int DecoSimple::getHeight() {
  390. return (deco_height_max > 0) ? deco_height_max : deco_height;
  391. }
  392. std::string DecoSimple::getName() {
  393. return deco_name;
  394. }
  395. ///////////////////////////////////////////////////////////////////////////////
  396. DecoSchematic::DecoSchematic() {
  397. node_names = NULL;
  398. schematic = NULL;
  399. slice_probs = NULL;
  400. flags = 0;
  401. size = v3s16(0, 0, 0);
  402. }
  403. DecoSchematic::~DecoSchematic() {
  404. delete node_names;
  405. delete []schematic;
  406. delete []slice_probs;
  407. }
  408. void DecoSchematic::resolveNodeNames(INodeDefManager *ndef) {
  409. Decoration::resolveNodeNames(ndef);
  410. if (filename.empty())
  411. return;
  412. if (!node_names) {
  413. errorstream << "DecoSchematic::resolveNodeNames: node name list was "
  414. "not created" << std::endl;
  415. return;
  416. }
  417. for (size_t i = 0; i != node_names->size(); i++) {
  418. std::string name = node_names->at(i);
  419. std::map<std::string, std::string>::iterator it;
  420. it = replacements.find(name);
  421. if (it != replacements.end())
  422. name = it->second;
  423. content_t c = ndef->getId(name);
  424. if (c == CONTENT_IGNORE) {
  425. errorstream << "DecoSchematic::resolveNodeNames: node '"
  426. << name << "' not defined" << std::endl;
  427. c = CONTENT_AIR;
  428. }
  429. c_nodes.push_back(c);
  430. }
  431. for (int i = 0; i != size.X * size.Y * size.Z; i++)
  432. schematic[i].setContent(c_nodes[schematic[i].getContent()]);
  433. delete node_names;
  434. node_names = NULL;
  435. }
  436. void DecoSchematic::generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p) {
  437. ManualMapVoxelManipulator *vm = mg->vm;
  438. if (flags & DECO_PLACE_CENTER_X)
  439. p.X -= (size.X + 1) / 2;
  440. if (flags & DECO_PLACE_CENTER_Y)
  441. p.Y -= (size.Y + 1) / 2;
  442. if (flags & DECO_PLACE_CENTER_Z)
  443. p.Z -= (size.Z + 1) / 2;
  444. u32 vi = vm->m_area.index(p);
  445. if (vm->m_data[vi].getContent() != c_place_on &&
  446. c_place_on != CONTENT_IGNORE)
  447. return;
  448. Rotation rot = (rotation == ROTATE_RAND) ?
  449. (Rotation)pr->range(ROTATE_0, ROTATE_270) : rotation;
  450. blitToVManip(p, vm, rot, false);
  451. }
  452. int DecoSchematic::getHeight() {
  453. return size.Y;
  454. }
  455. std::string DecoSchematic::getName() {
  456. return filename;
  457. }
  458. void DecoSchematic::blitToVManip(v3s16 p, ManualMapVoxelManipulator *vm,
  459. Rotation rot, bool force_placement) {
  460. int xstride = 1;
  461. int ystride = size.X;
  462. int zstride = size.X * size.Y;
  463. s16 sx = size.X;
  464. s16 sy = size.Y;
  465. s16 sz = size.Z;
  466. int i_start, i_step_x, i_step_z;
  467. switch (rot) {
  468. case ROTATE_90:
  469. i_start = sx - 1;
  470. i_step_x = zstride;
  471. i_step_z = -xstride;
  472. SWAP(s16, sx, sz);
  473. break;
  474. case ROTATE_180:
  475. i_start = zstride * (sz - 1) + sx - 1;
  476. i_step_x = -xstride;
  477. i_step_z = -zstride;
  478. break;
  479. case ROTATE_270:
  480. i_start = zstride * (sz - 1);
  481. i_step_x = -zstride;
  482. i_step_z = xstride;
  483. SWAP(s16, sx, sz);
  484. break;
  485. default:
  486. i_start = 0;
  487. i_step_x = xstride;
  488. i_step_z = zstride;
  489. }
  490. s16 y_map = p.Y;
  491. for (s16 y = 0; y != sy; y++) {
  492. if (slice_probs[y] != MTSCHEM_PROB_ALWAYS &&
  493. myrand_range(1, 255) > slice_probs[y])
  494. continue;
  495. for (s16 z = 0; z != sz; z++) {
  496. u32 i = z * i_step_z + y * ystride + i_start;
  497. for (s16 x = 0; x != sx; x++, i += i_step_x) {
  498. u32 vi = vm->m_area.index(p.X + x, y_map, p.Z + z);
  499. if (!vm->m_area.contains(vi))
  500. continue;
  501. if (schematic[i].getContent() == CONTENT_IGNORE)
  502. continue;
  503. if (schematic[i].param1 == MTSCHEM_PROB_NEVER)
  504. continue;
  505. if (!force_placement) {
  506. content_t c = vm->m_data[vi].getContent();
  507. if (c != CONTENT_AIR && c != CONTENT_IGNORE)
  508. continue;
  509. }
  510. if (schematic[i].param1 != MTSCHEM_PROB_ALWAYS &&
  511. myrand_range(1, 255) > schematic[i].param1)
  512. continue;
  513. vm->m_data[vi] = schematic[i];
  514. vm->m_data[vi].param1 = 0;
  515. if (rot)
  516. vm->m_data[vi].rotateAlongYAxis(ndef, rot);
  517. }
  518. }
  519. y_map++;
  520. }
  521. }
  522. void DecoSchematic::placeStructure(Map *map, v3s16 p, bool force_placement) {
  523. assert(schematic != NULL);
  524. ManualMapVoxelManipulator *vm = new ManualMapVoxelManipulator(map);
  525. Rotation rot = (rotation == ROTATE_RAND) ?
  526. (Rotation)myrand_range(ROTATE_0, ROTATE_270) : rotation;
  527. v3s16 s = (rot == ROTATE_90 || rot == ROTATE_270) ?
  528. v3s16(size.Z, size.Y, size.X) : size;
  529. if (flags & DECO_PLACE_CENTER_X)
  530. p.X -= (s.X + 1) / 2;
  531. if (flags & DECO_PLACE_CENTER_Y)
  532. p.Y -= (s.Y + 1) / 2;
  533. if (flags & DECO_PLACE_CENTER_Z)
  534. p.Z -= (s.Z + 1) / 2;
  535. v3s16 bp1 = getNodeBlockPos(p);
  536. v3s16 bp2 = getNodeBlockPos(p + s - v3s16(1,1,1));
  537. vm->initialEmerge(bp1, bp2);
  538. blitToVManip(p, vm, rot, force_placement);
  539. std::map<v3s16, MapBlock *> lighting_modified_blocks;
  540. std::map<v3s16, MapBlock *> modified_blocks;
  541. vm->blitBackAll(&modified_blocks);
  542. // TODO: Optimize this by using Mapgen::calcLighting() instead
  543. lighting_modified_blocks.insert(modified_blocks.begin(), modified_blocks.end());
  544. map->updateLighting(lighting_modified_blocks, modified_blocks);
  545. MapEditEvent event;
  546. event.type = MEET_OTHER;
  547. for (std::map<v3s16, MapBlock *>::iterator
  548. it = modified_blocks.begin();
  549. it != modified_blocks.end(); ++it)
  550. event.modified_blocks.insert(it->first);
  551. map->dispatchEvent(&event);
  552. }
  553. bool DecoSchematic::loadSchematicFile() {
  554. content_t cignore = CONTENT_IGNORE;
  555. bool have_cignore = false;
  556. std::ifstream is(filename.c_str(), std::ios_base::binary);
  557. u32 signature = readU32(is);
  558. if (signature != MTSCHEM_FILE_SIGNATURE) {
  559. errorstream << "loadSchematicFile: invalid schematic "
  560. "file" << std::endl;
  561. return false;
  562. }
  563. u16 version = readU16(is);
  564. if (version > MTSCHEM_FILE_VER_HIGHEST_READ) {
  565. errorstream << "loadSchematicFile: unsupported schematic "
  566. "file version" << std::endl;
  567. return false;
  568. }
  569. size = readV3S16(is);
  570. delete []slice_probs;
  571. slice_probs = new u8[size.Y];
  572. if (version >= 3) {
  573. for (int y = 0; y != size.Y; y++)
  574. slice_probs[y] = readU8(is);
  575. } else {
  576. for (int y = 0; y != size.Y; y++)
  577. slice_probs[y] = MTSCHEM_PROB_ALWAYS;
  578. }
  579. int nodecount = size.X * size.Y * size.Z;
  580. u16 nidmapcount = readU16(is);
  581. node_names = new std::vector<std::string>;
  582. for (int i = 0; i != nidmapcount; i++) {
  583. std::string name = deSerializeString(is);
  584. if (name == "ignore") {
  585. name = "air";
  586. cignore = i;
  587. have_cignore = true;
  588. }
  589. node_names->push_back(name);
  590. }
  591. delete []schematic;
  592. schematic = new MapNode[nodecount];
  593. MapNode::deSerializeBulk(is, SER_FMT_VER_HIGHEST_READ, schematic,
  594. nodecount, 2, 2, true);
  595. if (version == 1) { // fix up the probability values
  596. for (int i = 0; i != nodecount; i++) {
  597. if (schematic[i].param1 == 0)
  598. schematic[i].param1 = MTSCHEM_PROB_ALWAYS;
  599. if (have_cignore && schematic[i].getContent() == cignore)
  600. schematic[i].param1 = MTSCHEM_PROB_NEVER;
  601. }
  602. }
  603. return true;
  604. }
  605. /*
  606. Minetest Schematic File Format
  607. All values are stored in big-endian byte order.
  608. [u32] signature: 'MTSM'
  609. [u16] version: 3
  610. [u16] size X
  611. [u16] size Y
  612. [u16] size Z
  613. For each Y:
  614. [u8] slice probability value
  615. [Name-ID table] Name ID Mapping Table
  616. [u16] name-id count
  617. For each name-id mapping:
  618. [u16] name length
  619. [u8[]] name
  620. ZLib deflated {
  621. For each node in schematic: (for z, y, x)
  622. [u16] content
  623. For each node in schematic:
  624. [u8] probability of occurance (param1)
  625. For each node in schematic:
  626. [u8] param2
  627. }
  628. Version changes:
  629. 1 - Initial version
  630. 2 - Fixed messy never/always place; 0 probability is now never, 0xFF is always
  631. 3 - Added y-slice probabilities; this allows for variable height structures
  632. */
  633. void DecoSchematic::saveSchematicFile(INodeDefManager *ndef) {
  634. std::ostringstream ss(std::ios_base::binary);
  635. writeU32(ss, MTSCHEM_FILE_SIGNATURE); // signature
  636. writeU16(ss, MTSCHEM_FILE_VER_HIGHEST_WRITE); // version
  637. writeV3S16(ss, size); // schematic size
  638. for (int y = 0; y != size.Y; y++) // Y slice probabilities
  639. writeU8(ss, slice_probs[y]);
  640. std::vector<content_t> usednodes;
  641. int nodecount = size.X * size.Y * size.Z;
  642. build_nnlist_and_update_ids(schematic, nodecount, &usednodes);
  643. u16 numids = usednodes.size();
  644. writeU16(ss, numids); // name count
  645. for (int i = 0; i != numids; i++)
  646. ss << serializeString(ndef->get(usednodes[i]).name); // node names
  647. // compressed bulk node data
  648. MapNode::serializeBulk(ss, SER_FMT_VER_HIGHEST_WRITE, schematic,
  649. nodecount, 2, 2, true);
  650. fs::safeWriteToFile(filename, ss.str());
  651. }
  652. void build_nnlist_and_update_ids(MapNode *nodes, u32 nodecount,
  653. std::vector<content_t> *usednodes) {
  654. std::map<content_t, content_t> nodeidmap;
  655. content_t numids = 0;
  656. for (u32 i = 0; i != nodecount; i++) {
  657. content_t id;
  658. content_t c = nodes[i].getContent();
  659. std::map<content_t, content_t>::const_iterator it = nodeidmap.find(c);
  660. if (it == nodeidmap.end()) {
  661. id = numids;
  662. numids++;
  663. usednodes->push_back(c);
  664. nodeidmap.insert(std::make_pair(c, id));
  665. } else {
  666. id = it->second;
  667. }
  668. nodes[i].setContent(id);
  669. }
  670. }
  671. bool DecoSchematic::getSchematicFromMap(Map *map, v3s16 p1, v3s16 p2) {
  672. ManualMapVoxelManipulator *vm = new ManualMapVoxelManipulator(map);
  673. v3s16 bp1 = getNodeBlockPos(p1);
  674. v3s16 bp2 = getNodeBlockPos(p2);
  675. vm->initialEmerge(bp1, bp2);
  676. size = p2 - p1 + 1;
  677. slice_probs = new u8[size.Y];
  678. for (s16 y = 0; y != size.Y; y++)
  679. slice_probs[y] = MTSCHEM_PROB_ALWAYS;
  680. schematic = new MapNode[size.X * size.Y * size.Z];
  681. u32 i = 0;
  682. for (s16 z = p1.Z; z <= p2.Z; z++)
  683. for (s16 y = p1.Y; y <= p2.Y; y++) {
  684. u32 vi = vm->m_area.index(p1.X, y, z);
  685. for (s16 x = p1.X; x <= p2.X; x++, i++, vi++) {
  686. schematic[i] = vm->m_data[vi];
  687. schematic[i].param1 = MTSCHEM_PROB_ALWAYS;
  688. }
  689. }
  690. delete vm;
  691. return true;
  692. }
  693. void DecoSchematic::applyProbabilities(v3s16 p0,
  694. std::vector<std::pair<v3s16, u8> > *plist,
  695. std::vector<std::pair<s16, u8> > *splist) {
  696. for (size_t i = 0; i != plist->size(); i++) {
  697. v3s16 p = (*plist)[i].first - p0;
  698. int index = p.Z * (size.Y * size.X) + p.Y * size.X + p.X;
  699. if (index < size.Z * size.Y * size.X) {
  700. u8 prob = (*plist)[i].second;
  701. schematic[index].param1 = prob;
  702. // trim unnecessary node names from schematic
  703. if (prob == MTSCHEM_PROB_NEVER)
  704. schematic[index].setContent(CONTENT_AIR);
  705. }
  706. }
  707. for (size_t i = 0; i != splist->size(); i++) {
  708. s16 y = (*splist)[i].first - p0.Y;
  709. slice_probs[y] = (*splist)[i].second;
  710. }
  711. }
  712. ///////////////////////////////////////////////////////////////////////////////
  713. Mapgen::Mapgen() {
  714. seed = 0;
  715. water_level = 0;
  716. generating = false;
  717. id = -1;
  718. vm = NULL;
  719. ndef = NULL;
  720. heightmap = NULL;
  721. biomemap = NULL;
  722. for (unsigned int i = 0; i != NUM_GEN_NOTIFY; i++)
  723. gen_notifications[i] = new std::vector<v3s16>;
  724. }
  725. Mapgen::~Mapgen() {
  726. for (unsigned int i = 0; i != NUM_GEN_NOTIFY; i++)
  727. delete gen_notifications[i];
  728. }
  729. // Returns Y one under area minimum if not found
  730. s16 Mapgen::findGroundLevelFull(v2s16 p2d) {
  731. v3s16 em = vm->m_area.getExtent();
  732. s16 y_nodes_max = vm->m_area.MaxEdge.Y;
  733. s16 y_nodes_min = vm->m_area.MinEdge.Y;
  734. u32 i = vm->m_area.index(p2d.X, y_nodes_max, p2d.Y);
  735. s16 y;
  736. for (y = y_nodes_max; y >= y_nodes_min; y--) {
  737. MapNode &n = vm->m_data[i];
  738. if (ndef->get(n).walkable)
  739. break;
  740. vm->m_area.add_y(em, i, -1);
  741. }
  742. return (y >= y_nodes_min) ? y : y_nodes_min - 1;
  743. }
  744. s16 Mapgen::findGroundLevel(v2s16 p2d, s16 ymin, s16 ymax) {
  745. v3s16 em = vm->m_area.getExtent();
  746. u32 i = vm->m_area.index(p2d.X, ymax, p2d.Y);
  747. s16 y;
  748. for (y = ymax; y >= ymin; y--) {
  749. MapNode &n = vm->m_data[i];
  750. if (ndef->get(n).walkable)
  751. break;
  752. vm->m_area.add_y(em, i, -1);
  753. }
  754. return y;
  755. }
  756. void Mapgen::updateHeightmap(v3s16 nmin, v3s16 nmax) {
  757. if (!heightmap)
  758. return;
  759. //TimeTaker t("Mapgen::updateHeightmap", NULL, PRECISION_MICRO);
  760. int index = 0;
  761. for (s16 z = nmin.Z; z <= nmax.Z; z++) {
  762. for (s16 x = nmin.X; x <= nmax.X; x++, index++) {
  763. s16 y = findGroundLevel(v2s16(x, z), nmin.Y, nmax.Y);
  764. // if the values found are out of range, trust the old heightmap
  765. if (y == nmax.Y && heightmap[index] > nmax.Y)
  766. continue;
  767. if (y == nmin.Y - 1 && heightmap[index] < nmin.Y)
  768. continue;
  769. heightmap[index] = y;
  770. }
  771. }
  772. //printf("updateHeightmap: %dus\n", t.stop());
  773. }
  774. void Mapgen::updateLiquid(UniqueQueue<v3s16> *trans_liquid, v3s16 nmin, v3s16 nmax) {
  775. bool isliquid, wasliquid;
  776. v3s16 em = vm->m_area.getExtent();
  777. for (s16 z = nmin.Z; z <= nmax.Z; z++) {
  778. for (s16 x = nmin.X; x <= nmax.X; x++) {
  779. wasliquid = true;
  780. u32 i = vm->m_area.index(x, nmax.Y, z);
  781. for (s16 y = nmax.Y; y >= nmin.Y; y--) {
  782. isliquid = ndef->get(vm->m_data[i]).isLiquid();
  783. // there was a change between liquid and nonliquid, add to queue.
  784. if (isliquid != wasliquid)
  785. trans_liquid->push_back(v3s16(x, y, z));
  786. wasliquid = isliquid;
  787. vm->m_area.add_y(em, i, -1);
  788. }
  789. }
  790. }
  791. }
  792. void Mapgen::setLighting(v3s16 nmin, v3s16 nmax, u8 light) {
  793. ScopeProfiler sp(g_profiler, "EmergeThread: mapgen lighting update", SPT_AVG);
  794. VoxelArea a(nmin, nmax);
  795. for (int z = a.MinEdge.Z; z <= a.MaxEdge.Z; z++) {
  796. for (int y = a.MinEdge.Y; y <= a.MaxEdge.Y; y++) {
  797. u32 i = vm->m_area.index(a.MinEdge.X, y, z);
  798. for (int x = a.MinEdge.X; x <= a.MaxEdge.X; x++, i++)
  799. vm->m_data[i].param1 = light;
  800. }
  801. }
  802. }
  803. void Mapgen::lightSpread(VoxelArea &a, v3s16 p, u8 light) {
  804. if (light <= 1 || !a.contains(p))
  805. return;
  806. u32 vi = vm->m_area.index(p);
  807. MapNode &nn = vm->m_data[vi];
  808. light--;
  809. // should probably compare masked, but doesn't seem to make a difference
  810. if (light <= nn.param1 || !ndef->get(nn).light_propagates)
  811. return;
  812. nn.param1 = light;
  813. lightSpread(a, p + v3s16(0, 0, 1), light);
  814. lightSpread(a, p + v3s16(0, 1, 0), light);
  815. lightSpread(a, p + v3s16(1, 0, 0), light);
  816. lightSpread(a, p - v3s16(0, 0, 1), light);
  817. lightSpread(a, p - v3s16(0, 1, 0), light);
  818. lightSpread(a, p - v3s16(1, 0, 0), light);
  819. }
  820. void Mapgen::calcLighting(v3s16 nmin, v3s16 nmax) {
  821. VoxelArea a(nmin, nmax);
  822. bool block_is_underground = (water_level >= nmax.Y);
  823. ScopeProfiler sp(g_profiler, "EmergeThread: mapgen lighting update", SPT_AVG);
  824. //TimeTaker t("updateLighting");
  825. // first, send vertical rays of sunshine downward
  826. v3s16 em = vm->m_area.getExtent();
  827. for (int z = a.MinEdge.Z; z <= a.MaxEdge.Z; z++) {
  828. for (int x = a.MinEdge.X; x <= a.MaxEdge.X; x++) {
  829. // see if we can get a light value from the overtop
  830. u32 i = vm->m_area.index(x, a.MaxEdge.Y + 1, z);
  831. if (vm->m_data[i].getContent() == CONTENT_IGNORE) {
  832. if (block_is_underground)
  833. continue;
  834. } else if ((vm->m_data[i].param1 & 0x0F) != LIGHT_SUN) {
  835. continue;
  836. }
  837. vm->m_area.add_y(em, i, -1);
  838. for (int y = a.MaxEdge.Y; y >= a.MinEdge.Y; y--) {
  839. MapNode &n = vm->m_data[i];
  840. if (!ndef->get(n).sunlight_propagates)
  841. break;
  842. n.param1 = LIGHT_SUN;
  843. vm->m_area.add_y(em, i, -1);
  844. }
  845. }
  846. }
  847. // now spread the sunlight and light up any sources
  848. for (int z = a.MinEdge.Z; z <= a.MaxEdge.Z; z++) {
  849. for (int y = a.MinEdge.Y; y <= a.MaxEdge.Y; y++) {
  850. u32 i = vm->m_area.index(a.MinEdge.X, y, z);
  851. for (int x = a.MinEdge.X; x <= a.MaxEdge.X; x++, i++) {
  852. MapNode &n = vm->m_data[i];
  853. if (n.getContent() == CONTENT_IGNORE ||
  854. !ndef->get(n).light_propagates)
  855. continue;
  856. u8 light_produced = ndef->get(n).light_source & 0x0F;
  857. if (light_produced)
  858. n.param1 = light_produced;
  859. u8 light = n.param1 & 0x0F;
  860. if (light) {
  861. lightSpread(a, v3s16(x, y, z + 1), light - 1);
  862. lightSpread(a, v3s16(x, y + 1, z ), light - 1);
  863. lightSpread(a, v3s16(x + 1, y, z ), light - 1);
  864. lightSpread(a, v3s16(x, y, z - 1), light - 1);
  865. lightSpread(a, v3s16(x, y - 1, z ), light - 1);
  866. lightSpread(a, v3s16(x - 1, y, z ), light - 1);
  867. }
  868. }
  869. }
  870. }
  871. //printf("updateLighting: %dms\n", t.stop());
  872. }
  873. void Mapgen::calcLightingOld(v3s16 nmin, v3s16 nmax) {
  874. enum LightBank banks[2] = {LIGHTBANK_DAY, LIGHTBANK_NIGHT};
  875. VoxelArea a(nmin, nmax);
  876. bool block_is_underground = (water_level > nmax.Y);
  877. bool sunlight = !block_is_underground;
  878. ScopeProfiler sp(g_profiler, "EmergeThread: mapgen lighting update", SPT_AVG);
  879. for (int i = 0; i < 2; i++) {
  880. enum LightBank bank = banks[i];
  881. std::set<v3s16> light_sources;
  882. std::map<v3s16, u8> unlight_from;
  883. voxalgo::clearLightAndCollectSources(*vm, a, bank, ndef,
  884. light_sources, unlight_from);
  885. voxalgo::propagateSunlight(*vm, a, sunlight, light_sources, ndef);
  886. vm->unspreadLight(bank, unlight_from, light_sources, ndef);
  887. vm->spreadLight(bank, light_sources, ndef);
  888. }
  889. }