mapgen.lua 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202
  1. jarkati = {}
  2. -- These match values in the realm-control mod.
  3. jarkati.REALM_START = 3600
  4. jarkati.REALM_END = 3900
  5. jarkati.SEA_LEVEL = 3740
  6. jarkati.LAVA_LEVEL = 3610
  7. local ENABLE_BEDROCK = true
  8. local ENABLE_DECORATIONS = true
  9. local ENABLE_TOPSOIL = true
  10. local ENABLE_CAVES = true
  11. local ENABLE_OREGEN = true
  12. local ENABLE_CRYSTAL = true
  13. jarkati.biomes = {}
  14. jarkati.decorations = {}
  15. -- Public API function.
  16. function jarkati.register_layer(data)
  17. local td = table.copy(data)
  18. assert(type(td.node) == "string")
  19. -- Convert string name to content ID.
  20. td.cid = minetest.get_content_id(td.node)
  21. td.min_level = td.min_level or 1
  22. td.max_level = td.max_level or 1
  23. assert(td.min_level <= td.max_level)
  24. td.min_depth = td.min_depth or 1
  25. td.max_depth = td.max_depth or 1
  26. assert(td.min_depth <= td.max_depth)
  27. jarkati.biomes[#jarkati.biomes + 1] = td
  28. end
  29. -- Public API function.
  30. function jarkati.register_decoration(data)
  31. local td = table.copy(data)
  32. -- Convert single node to table.
  33. if type(td.nodes) == "string" then
  34. td.nodes = {td.nodes}
  35. end
  36. if type(td.replace_surface) == "string" then
  37. td.replace_surface = {td.replace_surface}
  38. end
  39. if type(td.place_on) == "string" then
  40. td.place_on = {td.place_on}
  41. end
  42. -- Used only with the `nodes` parameter.
  43. td.param2 = data.param2 or {0}
  44. assert(type(td.nodes) == "table" or type(td.schematic) == "string" or type(td.schematic) == "table")
  45. assert(type(td.probability) == "number")
  46. assert(td.probability >= 1)
  47. -- Ensure all node names are actually registered!
  48. if td.nodes then
  49. for k, v in ipairs(td.nodes) do
  50. assert(minetest.registered_nodes[v])
  51. end
  52. end
  53. if not td.all_ceilings and not td.all_floors then
  54. td.ground_level = true
  55. end
  56. -- Default schematic parameters.
  57. td.rotation = data.rotation or "0"
  58. td.replacements = data.replacements or {}
  59. td.force_placement = data.force_placement or false
  60. td.flags = data.flags or ""
  61. -- Placement Y-offset is always 0 (ignored) if `place_center_y` is specified.
  62. if td.flags:find("place_center_y") then
  63. td.place_offset_y = 0
  64. else
  65. td.place_offset_y = data.place_offset_y or 0
  66. -- Invert for `all_ceilings` decorations.
  67. if td.all_ceilings and td.place_offset_y > 0 then
  68. td.place_offset_y = -td.place_offset_y
  69. end
  70. end
  71. -- The object or schematic's aprox `radius`, when checking for flat ground.
  72. -- Non-zero basically means all ground in the radius must be the same height.
  73. td.radius = data.radius or 0
  74. td.y_min = data.y_min or -31000
  75. td.y_max = data.y_max or 31000
  76. td.chunk_chance = data.chunk_chance or 1
  77. jarkati.decorations[#jarkati.decorations + 1] = td
  78. end
  79. jarkati.register_layer({
  80. node = "default:desert_sand",
  81. min_depth = 1,
  82. max_depth = 2,
  83. min_level = 1,
  84. max_level = 1,
  85. })
  86. jarkati.register_layer({
  87. node = "default:sand",
  88. min_depth = 3,
  89. max_depth = 3,
  90. min_level = 1,
  91. max_level = 1,
  92. })
  93. jarkati.register_layer({
  94. node = "default:desert_cobble",
  95. min_depth = 7,
  96. max_depth = 7,
  97. min_level = 1,
  98. max_level = 1,
  99. })
  100. jarkati.register_layer({
  101. node = "default:sandstone",
  102. min_depth = 4,
  103. max_depth = 6,
  104. min_level = 1,
  105. max_level = 1,
  106. })
  107. jarkati.register_decoration({
  108. nodes = "stairs:slab_desert_cobble",
  109. probability = 700,
  110. place_on = {"default:desert_sand"},
  111. })
  112. jarkati.register_decoration({
  113. nodes = "aloevera:aloe_plant_04",
  114. probability = 1500,
  115. place_on = {"default:desert_sand"},
  116. replace_surface = "default:dirt_with_dry_grass",
  117. chunk_chance = 1,
  118. })
  119. -- Scatter "rubble" around the bases of cliffs.
  120. jarkati.register_decoration({
  121. nodes = {"default:desert_cobble", "stairs:slab_desert_cobble"},
  122. probability = 10,
  123. spawn_by = {"default:desert_stone", "default:sandstone"},
  124. place_on = {"default:desert_sand"},
  125. })
  126. jarkati.register_decoration({
  127. nodes = "default:dry_shrub",
  128. probability = 150,
  129. place_on = {"default:desert_sand"},
  130. })
  131. jarkati.register_decoration({
  132. nodes = "default:dry_shrub2",
  133. probability = 400,
  134. place_on = {"default:desert_sand"},
  135. param2 = {4},
  136. })
  137. jarkati.register_decoration({
  138. nodes = "flowers:desertrose_red",
  139. probability = 3000,
  140. place_on = {"default:desert_sand"},
  141. replace_surface = "default:dirt_with_dry_grass",
  142. chunk_chance = 7,
  143. })
  144. jarkati.register_decoration({
  145. nodes = "flowers:desertrose_pink",
  146. probability = 3000,
  147. place_on = {"default:desert_sand"},
  148. replace_surface = "default:dirt_with_dry_grass",
  149. chunk_chance = 7,
  150. })
  151. jarkati.register_decoration({
  152. nodes = "flowers:thornstalk",
  153. probability = 3000,
  154. place_on = {"default:desert_sand"},
  155. replace_surface = "default:dirt_with_dry_grass",
  156. chunk_chance = 5,
  157. })
  158. jarkati.register_decoration({
  159. nodes = {
  160. "default:dry_grass_1",
  161. "default:dry_grass_2",
  162. "default:dry_grass_3",
  163. "default:dry_grass_4",
  164. "default:dry_grass_5",
  165. },
  166. param2 = {2},
  167. probability = 50,
  168. place_on = {"default:desert_sand"},
  169. replace_surface = "default:dirt_with_dry_grass",
  170. })
  171. jarkati.register_decoration({
  172. nodes = {
  173. "cavestuff:redspike1",
  174. "cavestuff:redspike2",
  175. "cavestuff:redspike3",
  176. "cavestuff:redspike4",
  177. },
  178. param2 = {0, 1, 2, 3},
  179. probability = 120,
  180. all_floors = true,
  181. place_on = {"default:desert_stone"},
  182. replace_surface = {
  183. "default:desert_cobble",
  184. "default:desert_cobble2",
  185. "default:desert_cobble2",
  186. "default:desert_cobble2",
  187. },
  188. })
  189. jarkati.register_decoration({
  190. nodes = "default:tvine_stunted",
  191. probability = 1400,
  192. all_floors = true,
  193. place_on = "default:desert_stone",
  194. replace_surface = "talinite:desert_ore",
  195. })
  196. do
  197. local L = {name = "default:tvine"}
  198. local R = {name = "default:tvine_alt"}
  199. local S = {name = "default:tvine_top"}
  200. jarkati.register_decoration({
  201. schematic = {
  202. size = {x=1, y=3, z=1},
  203. data = {
  204. L,
  205. R,
  206. S,
  207. },
  208. },
  209. flags = "place_center_x,place_center_z",
  210. probability = 3400,
  211. all_floors = true,
  212. place_on = "default:desert_stone",
  213. replace_surface = "talinite:desert_ore",
  214. })
  215. end
  216. ---[[
  217. do
  218. local _ = {name = "air"}
  219. local X = {name = "default:gravel"}
  220. local C1 = {name = "stairs:micro_desert_sandstone", param2 = 1}
  221. local C2 = {name = "stairs:micro_desert_sandstone", param2 = 2}
  222. local C3 = {name = "stairs:micro_desert_sandstone", param2 = 0}
  223. local C4 = {name = "stairs:micro_desert_sandstone", param2 = 3}
  224. local L = {name = "stairs:slab_desert_sandstone"}
  225. local R = {name = "default:desert_sandstone"}
  226. local S = {name = "default:desert_sand"}
  227. jarkati.register_decoration({
  228. schematic = {
  229. size = {x=4, y=2, z=4},
  230. data = {
  231. S, R, R, S,
  232. C1, L, L, C3,
  233. R, X, X, R,
  234. L, _, _, L,
  235. R, X, X, R,
  236. L, _, _, L,
  237. S, R, R, S,
  238. C2, L, L, C4,
  239. },
  240. },
  241. force_placement = true,
  242. flags = "place_center_x,place_center_z",
  243. rotation = "random",
  244. place_offset_y = -1,
  245. radius = 3,
  246. probability = 800,
  247. place_on = {"default:desert_sand"},
  248. -- Called with 'pos', the placement position of the decoration.
  249. custom_func = function(gennotify_data, pos)
  250. local t = gennotify_data.nest_positions
  251. t[#t + 1] = pos
  252. end,
  253. y_max = 3760,
  254. y_min = 3730,
  255. })
  256. end
  257. --]]
  258. ---[[
  259. do
  260. local _ = {name = "air"}
  261. local X = {name = "default:gravel"}
  262. local C1 = {name = "stairs:micro_desert_sandstone", param2 = 1}
  263. local C2 = {name = "stairs:micro_desert_sandstone", param2 = 2}
  264. local C3 = {name = "stairs:micro_desert_sandstone", param2 = 0}
  265. local C4 = {name = "stairs:micro_desert_sandstone", param2 = 3}
  266. local L1 = {name = "stairs:stair_desert_sandstone", param2 = 0}
  267. local L2 = {name = "stairs:stair_desert_sandstone", param2 = 1}
  268. local L3 = {name = "stairs:stair_desert_sandstone", param2 = 2}
  269. local L4 = {name = "stairs:stair_desert_sandstone", param2 = 3}
  270. local R = {name = "default:desert_sandstone"}
  271. local S = {name = "default:desert_sand"}
  272. jarkati.register_decoration({
  273. schematic = {
  274. size = {x=4, y=2, z=4},
  275. data = {
  276. S, R, R, S,
  277. C1, L1, L1, C3,
  278. R, X, X, R,
  279. L2, _, _, L4,
  280. R, X, X, R,
  281. L2, _, _, L4,
  282. S, R, R, S,
  283. C2, L3, L3, C4,
  284. },
  285. },
  286. force_placement = true,
  287. flags = "place_center_x,place_center_z",
  288. rotation = "random",
  289. place_offset_y = -1,
  290. radius = 4,
  291. probability = 800,
  292. place_on = {"default:desert_sand"},
  293. -- Called with 'pos', the placement position of the decoration.
  294. custom_func = function(gennotify_data, pos)
  295. local t = gennotify_data.nest_positions
  296. t[#t + 1] = pos
  297. end,
  298. y_max = 3760,
  299. y_min = 3730,
  300. })
  301. end
  302. --]]
  303. ---[[
  304. do
  305. local _ = {name = "air"}
  306. local X = {name = "rackstone:nether_grit"}
  307. local C1 = {name = "stairs:micro_desert_sandstone", param2 = 1}
  308. local C2 = {name = "stairs:micro_desert_sandstone", param2 = 2}
  309. local C3 = {name = "stairs:micro_desert_sandstone", param2 = 0}
  310. local C4 = {name = "stairs:micro_desert_sandstone", param2 = 3}
  311. local L = {name = "stairs:slab_desert_sandstone"}
  312. local R = {name = "default:desert_sandstone"}
  313. local S = {name = "default:desert_sand"}
  314. jarkati.register_decoration({
  315. schematic = {
  316. size = {x=4, y=2, z=4},
  317. data = {
  318. S, R, R, S,
  319. C1, L, L, C3,
  320. R, X, X, R,
  321. L, _, _, L,
  322. R, X, X, R,
  323. L, _, _, L,
  324. S, R, R, S,
  325. C2, L, L, C4,
  326. },
  327. },
  328. force_placement = true,
  329. flags = "place_center_x,place_center_z",
  330. rotation = "random",
  331. place_offset_y = -1,
  332. radius = 3,
  333. probability = 2500,
  334. place_on = {"default:desert_sand"},
  335. y_max = 3750,
  336. y_min = 3730,
  337. })
  338. end
  339. --]]
  340. ---[[
  341. do
  342. local _ = {name = "air"}
  343. local X = {name = "rackstone:nether_grit"}
  344. local C1 = {name = "stairs:micro_desert_sandstone", param2 = 1}
  345. local C2 = {name = "stairs:micro_desert_sandstone", param2 = 2}
  346. local C3 = {name = "stairs:micro_desert_sandstone", param2 = 0}
  347. local C4 = {name = "stairs:micro_desert_sandstone", param2 = 3}
  348. local L1 = {name = "stairs:stair_desert_sandstone", param2 = 0}
  349. local L2 = {name = "stairs:stair_desert_sandstone", param2 = 1}
  350. local L3 = {name = "stairs:stair_desert_sandstone", param2 = 2}
  351. local L4 = {name = "stairs:stair_desert_sandstone", param2 = 3}
  352. local R = {name = "default:desert_sandstone"}
  353. local S = {name = "default:desert_sand"}
  354. jarkati.register_decoration({
  355. schematic = {
  356. size = {x=4, y=2, z=4},
  357. data = {
  358. S, R, R, S,
  359. C1, L1, L1, C3,
  360. R, X, X, R,
  361. L2, _, _, L4,
  362. R, X, X, R,
  363. L2, _, _, L4,
  364. S, R, R, S,
  365. C2, L3, L3, C4,
  366. },
  367. },
  368. force_placement = true,
  369. flags = "place_center_x,place_center_z",
  370. rotation = "random",
  371. place_offset_y = -1,
  372. radius = 4,
  373. probability = 2500,
  374. place_on = {"default:desert_sand"},
  375. y_max = 3750,
  376. y_min = 3730,
  377. })
  378. end
  379. --]]
  380. local NOISE_SCALE = 1
  381. -- Base terrain height (may be modified to be negative or positive).
  382. jarkati.noise1param2d = {
  383. offset = 0,
  384. scale = 1,
  385. spread = {x=128*NOISE_SCALE, y=128*NOISE_SCALE, z=128*NOISE_SCALE},
  386. seed = 5719,
  387. octaves = 6,
  388. persist = 0.5,
  389. lacunarity = 2,
  390. }
  391. -- Modifies frequency of vertical tunnel shafts.
  392. jarkati.noise2param2d = {
  393. offset = 0,
  394. scale = 1,
  395. spread = {x=64*NOISE_SCALE, y=64*NOISE_SCALE, z=64*NOISE_SCALE},
  396. seed = 8827,
  397. octaves = 6,
  398. persist = 0.4, -- Amplitude multiplier.
  399. lacunarity = 2, -- Wavelength divisor.
  400. }
  401. -- Mese/tableland terrain-height modifier.
  402. jarkati.noise3param2d = {
  403. offset = 0,
  404. scale = 1,
  405. spread = {x=64*NOISE_SCALE, y=64*NOISE_SCALE, z=64*NOISE_SCALE},
  406. seed = 54871,
  407. octaves = 5,
  408. persist = 0.5,
  409. lacunarity = 2,
  410. }
  411. -- Modifies the frequency (strength) of tablelands over big area.
  412. jarkati.noise4param2d = {
  413. offset = 0,
  414. scale = 1,
  415. spread = {x=128*NOISE_SCALE, y=128*NOISE_SCALE, z=128*NOISE_SCALE},
  416. seed = 2819,
  417. octaves = 3,
  418. persist = 0.5,
  419. lacunarity = 2,
  420. }
  421. -- Disjunction height modifier.
  422. jarkati.noise5param2d = {
  423. offset = 0,
  424. scale = 1,
  425. spread = {x=512*NOISE_SCALE, y=512*NOISE_SCALE, z=512*NOISE_SCALE},
  426. seed = 3819,
  427. octaves = 6,
  428. persist = 0.7,
  429. lacunarity = 2,
  430. }
  431. -- Primary cavern noise.
  432. jarkati.noise6param3d = {
  433. offset = 0,
  434. scale = 1,
  435. spread = {x=128*NOISE_SCALE, y=32*NOISE_SCALE, z=128*NOISE_SCALE},
  436. seed = 3817,
  437. octaves = 5,
  438. persist = 0.5,
  439. lacunarity = 2,
  440. }
  441. -- Vertical tunnel noise.
  442. jarkati.noise7param3d = {
  443. offset = 0,
  444. scale = 1,
  445. spread = {x=8*NOISE_SCALE, y=64*NOISE_SCALE, z=8*NOISE_SCALE},
  446. seed = 7848,
  447. octaves = 4,
  448. persist = 0.7,
  449. lacunarity = 1.5,
  450. }
  451. -- Content IDs used with the voxel manipulator.
  452. local c_air = minetest.get_content_id("air")
  453. local c_ignore = minetest.get_content_id("ignore")
  454. local c_desert_stone = minetest.get_content_id("default:desert_stone")
  455. local c_desert_cobble = minetest.get_content_id("default:desert_cobble")
  456. local c_desert_cobble2 = minetest.get_content_id("default:desert_cobble2")
  457. local c_bedrock = minetest.get_content_id("bedrock:bedrock")
  458. local c_sand = minetest.get_content_id("default:sand")
  459. local c_desert_sand = minetest.get_content_id("default:desert_sand")
  460. local c_gravel = minetest.get_content_id("default:gravel")
  461. local c_water = minetest.get_content_id("default:water_source")
  462. local c_lava = minetest.get_content_id("default:lava_source")
  463. local c_crystal = minetest.get_content_id("cavestuff:glow_white_crystal")
  464. local c_worm = minetest.get_content_id("cavestuff:glow_worm")
  465. local c_fungus = minetest.get_content_id("cavestuff:glow_fungus")
  466. local c_sandstone = minetest.get_content_id("default:sandstone")
  467. local c_desertsandstone = minetest.get_content_id("default:desert_sandstone")
  468. -- Externally located tables for performance.
  469. local vm_data = {}
  470. local vm_light = {}
  471. local biome_data = {}
  472. local heightmap = {}
  473. local noisemap1 = {}
  474. local noisemap2 = {}
  475. local noisemap3 = {}
  476. local noisemap4 = {}
  477. local noisemap5 = {}
  478. local noisemap6 = {}
  479. local noisemap7 = {}
  480. local perlin1
  481. local perlin2
  482. local perlin3
  483. local perlin4
  484. local perlin5
  485. local perlin6
  486. local perlin7
  487. jarkati.generate_realm = function(vm, minp, maxp, seed)
  488. local nbeg = jarkati.REALM_START
  489. local nend = jarkati.REALM_END
  490. local slev = jarkati.SEA_LEVEL
  491. local lbeg = jarkati.REALM_START
  492. local lend = jarkati.LAVA_LEVEL
  493. local gennotify_data = {}
  494. gennotify_data.nest_positions = {}
  495. gennotify_data.minp = minp
  496. gennotify_data.maxp = maxp
  497. -- Don't run for out-of-bounds mapchunks.
  498. if minp.y > nend or maxp.y < nbeg then
  499. return
  500. end
  501. -- Grab the voxel manipulator.
  502. -- Read current map data.
  503. local emin, emax = vm:get_emerged_area()
  504. vm:get_data(vm_data)
  505. vm:get_light_data(vm_light)
  506. local area = VoxelArea:new({MinEdge=emin, MaxEdge=emax})
  507. -- Actual emerged area should be bigger than the chunk we're generating!
  508. assert(emin.y < minp.y and emin.x < minp.x and emin.z < minp.z)
  509. assert(emax.y > maxp.y and emax.x > maxp.x and emax.z > maxp.z)
  510. local pr = PseudoRandom(seed + 351)
  511. local dpr = PseudoRandom(seed + 2891) -- For decoration placement probability.
  512. -- Start out by overgenerating by 1 node.
  513. local x1 = maxp.x + 1
  514. local y1 = maxp.y + 1
  515. local z1 = maxp.z + 1
  516. local x0 = minp.x - 1
  517. local y0 = minp.y - 1
  518. local z0 = minp.z - 1
  519. local noisearea = VoxelArea:new({MinEdge={x=x0, y=y0, z=z0}, MaxEdge={x=x1, y=y1, z=z1}})
  520. -- Compute side lengths.
  521. local side_len_x = ((x1-x0)+1)
  522. local side_len_y = ((y1-y0)+1)
  523. local side_len_z = ((z1-z0)+1)
  524. local sides2D = {x=side_len_x, y=side_len_z}
  525. local sides3D = {x=side_len_x, y=side_len_z, z=side_len_y}
  526. local bp2d = {x=x0, y=z0}
  527. local bp3d = {x=x0, y=y0, z=z0}
  528. -- Get noisemaps.
  529. perlin1 = perlin1 or minetest.get_perlin_map(jarkati.noise1param2d, sides2D)
  530. perlin1:get_2d_map_flat(bp2d, noisemap1)
  531. perlin2 = perlin2 or minetest.get_perlin_map(jarkati.noise2param2d, sides2D)
  532. perlin2:get_2d_map_flat(bp2d, noisemap2)
  533. perlin3 = perlin3 or minetest.get_perlin_map(jarkati.noise3param2d, sides2D)
  534. perlin3:get_2d_map_flat(bp2d, noisemap3)
  535. perlin4 = perlin4 or minetest.get_perlin_map(jarkati.noise4param2d, sides2D)
  536. perlin4:get_2d_map_flat(bp2d, noisemap4)
  537. perlin5 = perlin5 or minetest.get_perlin_map(jarkati.noise5param2d, sides2D)
  538. perlin5:get_2d_map_flat(bp2d, noisemap5)
  539. perlin6 = perlin6 or minetest.get_perlin_map(jarkati.noise6param3d, sides3D)
  540. perlin6:get_3d_map_flat(bp3d, noisemap6)
  541. perlin7 = perlin7 or minetest.get_perlin_map(jarkati.noise7param3d, sides3D)
  542. perlin7:get_3d_map_flat(bp3d, noisemap7)
  543. -- Localize commonly used functions for speed.
  544. local floor = math.floor
  545. local ceil = math.ceil
  546. local abs = math.abs
  547. local min = math.min
  548. local max = math.max
  549. -- Terrain height function (does not handle caves).
  550. local function height(z, x)
  551. -- Get index into 2D noise arrays.
  552. local nx = (x - x0)
  553. local nz = (z - z0)
  554. local ni2 = (side_len_z*nz+nx)
  555. -- Lua arrays start indexing at 1, not 0. Urrrrgh.
  556. ni2 = ni2 + 1
  557. local n1 = noisemap1[ni2]
  558. local n2 = noisemap2[ni2]
  559. local n3 = noisemap3[ni2]
  560. local n4 = noisemap4[ni2]
  561. local n5 = noisemap5[ni2]
  562. -- Calc base terrain height.
  563. local h = slev + (abs(n1) * 16)
  564. -- Modify the tableland noise parameter with this noise.
  565. n3 = n3 * abs(n4)
  566. n1 = n1 * abs(n5)
  567. -- If tableland noise over threshold, then flatten/invert terrain height.
  568. -- This generates "tablelands", buttes, etc.
  569. if n3 > -0.1 then
  570. h = slev + (n1 * 3)
  571. end
  572. -- If even farther over the threshold, then intensify/invert once again.
  573. -- This can result in apparent "land bridges" if the surrounding landscape
  574. -- is low, or it can create simple "canyons" if the surroundings are high.
  575. if n3 > 0.3 then
  576. h = slev - (n1 * 5)
  577. end
  578. if n3 > 0.6 then
  579. h = slev + (n1 * 8)
  580. end
  581. return h
  582. end
  583. local function cavern(x, y, z)
  584. local np = noisearea:index(x, y, z)
  585. local n1 = noisemap6[np]
  586. local n2 = noisemap7[np]
  587. -- Get index into 2D noise arrays.
  588. local nx = (x - x0)
  589. local nz = (z - z0)
  590. local ni2 = (side_len_z*nz+nx)
  591. -- Lua arrays start indexing at 1, not 0. Urrrrgh.
  592. ni2 = ni2 + 1
  593. local n3 = abs(noisemap2[ni2])
  594. -- Reduce cavern noise at realm base.
  595. local d = (y - nbeg)
  596. if d < 0 then d = 0 end
  597. d = d / 16
  598. if d > 1 then d = 1 end
  599. if d < 0 then d = 0 end
  600. n1 = n1 * d
  601. -- Reduce cavern noise at surface level.
  602. local f = (slev - y)
  603. if f < 0 then f = 0 end
  604. f = f / 16
  605. if f > 1 then f = 1 end
  606. if f < 0 then f = 0 end
  607. n1 = n1 * f
  608. -- Expand cavern noise 50 meters below surface level, 10 meters above and below.
  609. local x = abs((slev - 50) - y)
  610. x = x * -1 + 16 -- Invert range.
  611. x = x / 16
  612. if x > 1 then x = 1 end
  613. if x < 0 then x = 0 end
  614. n1 = n1 * (1 + x)
  615. local bigcavern = false
  616. if abs(n1) > 0.6 then
  617. bigcavern = true
  618. end
  619. local vertspike = false
  620. if (abs(n2) * (n3 * n3)) > 0.8 then
  621. vertspike = true
  622. end
  623. local crystal = false
  624. if vertspike and (abs(n2) * (n3 * n3)) < 1.0 then
  625. crystal = true
  626. end
  627. return bigcavern, vertspike, crystal
  628. end
  629. -- Generic filler stone type.
  630. local c_stone = c_desert_stone
  631. -- First mapgen pass. Generate stone terrain shape, fill rest with air (critical).
  632. -- This also constructs the heightmap, which caches the height values.
  633. for z = z0, z1 do
  634. for x = x0, x1 do
  635. local ground = floor(height(z, x))
  636. heightmap[area:index(x, 0, z)] = ground
  637. local miny = (y0 - 0)
  638. local maxy = (y1 + 0)
  639. miny = max(miny, nbeg)
  640. maxy = min(maxy, nend)
  641. -- Flag set once a cave has carved away part of the surface in this column.
  642. -- Second flag set once the floor of the first cave is reached.
  643. -- Once the floor of the first cave is reached, the heightmap is adjusted.
  644. -- The heightmap is ONLY adjusted for caves that intersect with base ground level.
  645. local gc0 = false
  646. local gc1 = false
  647. -- First pass through column.
  648. -- Iterate downwards so we can detect when caves modify the surface height.
  649. for y = maxy, miny, -1 do
  650. --for y = y1, y0, -1 do
  651. local cave, vertspike, crystal = cavern(x, y, z)
  652. local vp = area:index(x, y, z)
  653. local cid = vm_data[vp]
  654. --vm_data[vp] = c_stone
  655. ---[[
  656. -- Don't overwrite previously existing stuff (non-ignore, non-air).
  657. -- This avoids ruining schematics that were previously placed.
  658. if (cid == c_air or cid == c_ignore) then
  659. if ENABLE_CRYSTAL and crystal then
  660. if y <= ground - 6 then
  661. vm_data[vp] = c_crystal
  662. end
  663. elseif ENABLE_CRYSTAL and vertspike then
  664. -- Cap crystals with lava just below the jarkati surface.
  665. -- Make a crystal floor so the lava doesn't fall into the caves.
  666. local lmin = ground - 6
  667. local lmax = ground - 4
  668. local croof = ground - 7
  669. if y >= lmin and y <= lmax then
  670. vm_data[vp] = c_lava
  671. elseif y == croof then
  672. vm_data[vp] = c_crystal
  673. end
  674. elseif ENABLE_CAVES and (cave or vertspike) then
  675. -- We've started carving a cave in this column.
  676. -- Don't bother flagging this unless the cave roof would be above ground level.
  677. if (y > ground and not gc0) then
  678. gc0 = true
  679. end
  680. if (y >= lbeg and y <= lend) then
  681. vm_data[vp] = c_lava
  682. else
  683. vm_data[vp] = c_air
  684. end
  685. else
  686. if y <= ground then
  687. -- We've finished carving a cave in this column.
  688. -- Adjust heightmap.
  689. -- But don't bother if cave floor would be above ground level.
  690. if (gc0 and not gc1) then
  691. heightmap[area:index(x, 0, z)] = y
  692. gc1 = true
  693. end
  694. vm_data[vp] = c_stone
  695. else
  696. if (y >= lbeg and y <= lend) then
  697. vm_data[vp] = c_lava
  698. else
  699. vm_data[vp] = c_air
  700. end
  701. end
  702. end
  703. end
  704. --]]
  705. end -- End column loop.
  706. end
  707. end
  708. if ENABLE_TOPSOIL then
  709. -- Localize for speed.
  710. local all_biomes = jarkati.biomes
  711. local function biomes(biomes)
  712. local biome_count = 0
  713. for k, v in ipairs(biomes) do
  714. biome_count = biome_count + 1
  715. biome_data[biome_count] = v
  716. end
  717. return biome_data, biome_count -- Table is continuously reused.
  718. end
  719. -- Second mapgen pass. Generate topsoil layers.
  720. for z = z0, z1 do
  721. for x = x0, x1 do
  722. local miny = (y0 - 0)
  723. local maxy = (y1 + 0)
  724. -- Get heightmap value at this location. This may have been adjusted by a surface cave.
  725. local ground = heightmap[area:index(x, 0, z)]
  726. -- Count of how many "surfaces" were detected (so far) while iterating down.
  727. -- 0 means we haven't found ground yet. 1 means found ground, >1 indicates a cave surface.
  728. local count = 0
  729. local depth = 0
  730. -- Get array and array-size of all biomes valid for this position.
  731. local vb, bc = biomes(all_biomes)
  732. -- Second pass through column. Iterate backwards for depth checking.
  733. for y = maxy, miny, -1 do
  734. if y >= nbeg and y <= nend then
  735. local vp0 = area:index(x, y, z)
  736. local vpu = area:index(x, (y - 1), z)
  737. if y <= ground then
  738. count = 1
  739. -- Do not place topsoil layers in these nodes.
  740. if vm_data[vp0] == c_lava or vm_data[vp0] == c_crystal then
  741. depth = 0
  742. elseif vm_data[vp0] ~= c_air and vm_data[vpu] ~= c_air and vm_data[vpu] ~= c_ignore then
  743. -- Otherwise, replace everything other than air and ignore.
  744. depth = (ground - y) + 1
  745. else
  746. -- Skip replacing air and ignore.
  747. depth = 0
  748. end
  749. else
  750. -- Above ground, can't place layer soil here.
  751. count = 0
  752. depth = 0
  753. end
  754. -- Place topsoils & layers, etc. using current biome data.
  755. for i = 1, bc do
  756. -- Get biome data.
  757. local v = vb[i]
  758. if (count >= v.min_level and count <= v.max_level) then
  759. if (depth >= v.min_depth and depth <= v.max_depth) then
  760. vm_data[vp0] = v.cid
  761. end
  762. end
  763. end
  764. end
  765. end -- End column loop.
  766. end
  767. end
  768. end
  769. if ENABLE_CRYSTAL then
  770. for x = x0, x1 do
  771. for z = z0, z1 do
  772. -- Don't place these decorations near the bedrock layer.
  773. -- Glow worms in particular were seen generating *underneath* the bottom
  774. -- of the bedrock, because there *was* crystal there before the bedrock
  775. -- code force-replaced it.
  776. local miny = math.max(y0, nbeg + 16)
  777. local maxy = y1
  778. for y = miny, maxy do
  779. local vp = area:index(x, y, z)
  780. local vd = area:index(x, y-1, z)
  781. local vu = area:index(x, y+1, z)
  782. local v1 = area:index(x+1, y, z)
  783. local v2 = area:index(x-1, y, z)
  784. local v3 = area:index(x, y, z+1)
  785. local v4 = area:index(x, y, z-1)
  786. local crystals = 0
  787. if vm_data[v1] == c_crystal then crystals = crystals + 1 end
  788. if vm_data[v2] == c_crystal then crystals = crystals + 1 end
  789. if vm_data[v3] == c_crystal then crystals = crystals + 1 end
  790. if vm_data[v4] == c_crystal then crystals = crystals + 1 end
  791. local stones = 0
  792. if vm_data[v1] == c_stone then stones = stones + 1 end
  793. if vm_data[v2] == c_stone then stones = stones + 1 end
  794. if vm_data[v3] == c_stone then stones = stones + 1 end
  795. if vm_data[v4] == c_stone then stones = stones + 1 end
  796. local lavasrc = 0
  797. if vm_data[v1] == c_lava then lavasrc = lavasrc + 1 end
  798. if vm_data[v2] == c_lava then lavasrc = lavasrc + 1 end
  799. if vm_data[v3] == c_lava then lavasrc = lavasrc + 1 end
  800. if vm_data[v4] == c_lava then lavasrc = lavasrc + 1 end
  801. -- Stone next to crystal turns to cobble.
  802. -- Place fungus and glow worms and top and bottom, too, if there's room.
  803. if vm_data[vp] == c_stone and crystals > 0 then
  804. vm_data[vp] = c_desert_cobble2
  805. if vm_data[vd] == c_air and pr:next(1, 2) == 1 then
  806. vm_data[vd] = c_worm
  807. end
  808. if vm_data[vu] == c_air and pr:next(1, 2) == 1 then
  809. vm_data[vu] = c_fungus
  810. end
  811. end
  812. -- Sand next to lava (horizontal only) turns to ... gravel?
  813. if (vm_data[vp] == c_sand or vm_data[vp] == c_desert_sand or
  814. vm_data[vp] == c_sandstone or vm_data[vp] == c_desertsandstone)
  815. and lavasrc > 0 then
  816. vm_data[vp] = c_gravel
  817. end
  818. end
  819. end
  820. end
  821. end
  822. if ENABLE_BEDROCK then
  823. -- Third mapgen pass. Generate bedrock layer overwriting everything else (critical).
  824. if not (y1 < nbeg or y0 > (nbeg + 10)) then
  825. for z = z0, z1 do
  826. for x = x0, x1 do
  827. -- Randomize height of the bedrock a bit.
  828. local bedrock = (nbeg + pr:next(5, pr:next(6, 7)))
  829. local miny = max(y0, nbeg)
  830. local maxy = min(y1, bedrock)
  831. -- Third pass through column.
  832. for y = miny, maxy do
  833. local vp = area:index(x, y, z)
  834. vm_data[vp] = c_bedrock
  835. end -- End column loop.
  836. end
  837. end
  838. end
  839. end
  840. -- Finalize voxel manipulator.
  841. vm:set_data(vm_data)
  842. if ENABLE_OREGEN then
  843. minetest.generate_ores(vm)
  844. end
  845. --vm:write_to_map(false)
  846. -- Not needed to do this, it will be done during the "mapfix" call.
  847. --vm:update_liquids()
  848. if ENABLE_DECORATIONS then
  849. -- Localize for speed.
  850. local all_decorations = jarkati.decorations
  851. local decopos = {x=0, y=0, z=0}
  852. local set_node = minetest.set_node
  853. local get_node = minetest.get_node
  854. local put_schem = minetest.place_schematic
  855. local deconode = {name="", param2=0}
  856. local function put_schem(pos, schem, rot, replace, fp, flags)
  857. -- Don't place trees intersecting chunk borders in the X,Z directions.
  858. --local b = 5
  859. --if pos.x >= (emin.x + b) and pos.x <= (emax.x - b) and
  860. -- pos.z >= (emin.z + b) and pos.z <= (emax.z - b) then
  861. minetest.place_schematic_on_vmanip(vm, pos, schem, rot, replace, fp, flags)
  862. --end
  863. end
  864. local function decorate(v, x, y, z, d)
  865. -- Don't place decorations outside chunk boundaries.
  866. -- (X and Z are already checked.)
  867. if (y < y0 or y > y1) then
  868. return
  869. end
  870. if (y > v.y_max or y < v.y_min) then
  871. return
  872. end
  873. decopos.x = x
  874. decopos.y = y
  875. decopos.z = z
  876. if v.spawn_by then
  877. if not minetest.find_node_near(decopos, (v.radius + 1), v.spawn_by) then
  878. return
  879. end
  880. end
  881. -- Validate the ground/ceiling surface.
  882. do
  883. local x1 = decopos.x - v.radius
  884. local x2 = decopos.x + v.radius
  885. local z1 = decopos.z - v.radius
  886. local z2 = decopos.z + v.radius
  887. local nn
  888. -- All must be a valid floor/ceiling node!
  889. decopos.y = decopos.y + d
  890. for x = x1, x2 do
  891. for z = z1, z2 do
  892. decopos.x = x
  893. decopos.z = z
  894. nn = get_node(decopos).name
  895. -- Always check to make sure we're not air, here.
  896. -- This avoids spawning decorations on ground that was carved away by the cavegen.
  897. if nn == "air" or nn == "ignore" then
  898. return
  899. end
  900. -- If decoration requires specific node type, check if we have it.
  901. if v.place_on then
  902. local hs = false
  903. for t, j in ipairs(v.place_on) do
  904. if j == nn then
  905. hs = true
  906. break
  907. end
  908. end
  909. if not hs then
  910. return
  911. end
  912. end
  913. end
  914. end
  915. -- All must be empty air!
  916. decopos.y = decopos.y - d
  917. for x = x1, x2 do
  918. for z = z1, z2 do
  919. decopos.x = x
  920. decopos.z = z
  921. nn = get_node(decopos).name
  922. if nn ~= "air" then
  923. return
  924. end
  925. end
  926. end
  927. -- Back to ground. Replace ground surface!
  928. if v.replace_surface then
  929. decopos.y = decopos.y + d
  930. for x = x1, x2 do
  931. for z = z1, z2 do
  932. decopos.x = x
  933. decopos.z = z
  934. deconode.name = v.replace_surface[dpr:next(1, #v.replace_surface)]
  935. deconode.param2 = 0
  936. set_node(decopos, deconode)
  937. if v.custom_func then
  938. v.custom_func(gennotify_data, decopos)
  939. end
  940. end
  941. end
  942. end
  943. -- Reset deco coordinates.
  944. decopos.x = x
  945. decopos.y = y
  946. decopos.z = z
  947. end
  948. if v.nodes then
  949. deconode.name = v.nodes[dpr:next(1, #v.nodes)]
  950. deconode.param2 = v.param2[dpr:next(1, #v.param2)]
  951. set_node(decopos, deconode)
  952. if v.custom_func then
  953. v.custom_func(gennotify_data, decopos)
  954. end
  955. elseif v.schematic then
  956. decopos.y = decopos.y + v.place_offset_y
  957. put_schem(decopos, v.schematic, v.rotation, v.replacements, v.force_placement, v.flags)
  958. decopos.y = decopos.y - v.place_offset_y
  959. if v.custom_func then
  960. v.custom_func(gennotify_data, decopos)
  961. end
  962. end
  963. end
  964. -- Fourth mapgen pass. Generate decorations using highlevel placement functions.
  965. -- Note: we still read the voxelmanip data! But we can't modify it.
  966. for z = z0, z1 do
  967. for x = x0, x1 do
  968. for k, v in ipairs(all_decorations) do
  969. if not (y0 > v.y_max or y1 < v.y_min) then
  970. if dpr:next(1, v.chunk_chance) == 1 and dpr:next(1, v.probability) == 1 then
  971. -- Don't bother with ground-level placement if 'all_floors' was specified.
  972. if (v.ground_level and not v.all_floors) then
  973. local g0 = heightmap[area:index(x, 0, z)]
  974. local g1 = (g0 + 1)
  975. decorate(v, x, g1, z, -1)
  976. end
  977. if (v.all_floors or v.all_ceilings) then
  978. local miny = (y0 - 1)
  979. local maxy = (y1 + 1)
  980. for y = maxy, miny, -1 do
  981. local vpa = area:index(x, y, z)
  982. local vpu = area:index(x, (y - 1), z)
  983. local cida = vm_data[vpa]
  984. local cidu = vm_data[vpu]
  985. if v.all_floors then
  986. if (cida == c_air and cidu ~= c_air) then
  987. decorate(v, x, y, z, -1)
  988. end
  989. end
  990. if v.all_ceilings then
  991. if (cida ~= c_air and cidu == c_air) then
  992. decorate(v, x, (y - 1), z, 1)
  993. end
  994. end
  995. end
  996. end
  997. end
  998. end
  999. end
  1000. end
  1001. end
  1002. end
  1003. -- Correct lighting and liquid flow.
  1004. -- This works, but for some reason I have to grab a new voxelmanip object.
  1005. -- I can't seem to fix lighting using the original mapgen object?
  1006. -- Seems to require the full overgenerated mapchunk size if non-singlenode.
  1007. --mapfix.work(emin, emax)
  1008. --vm:calc_lighting()
  1009. -- Lighting pass. Set everything dark.
  1010. for z = emin.z, emax.z do
  1011. for x = emin.x, emax.x do
  1012. --local hp = area:index(x, 0, z)
  1013. --local ground = heightmap[hp]
  1014. for y = emin.y, emax.y do
  1015. local vp = area:index(x, y, z)
  1016. if y < (jarkati.SEA_LEVEL - 10) then
  1017. vm_light[vp] = 0
  1018. else
  1019. vm_light[vp] = 15
  1020. end
  1021. end
  1022. end
  1023. end
  1024. vm:set_light_data(vm_light)
  1025. --vm:calc_lighting({x=emin.x, y=emin.y, z=emin.z}, {x=emax.x, y=maxp.y, z=emax.z}, true)
  1026. vm:calc_lighting({x=minp.x, y=minp.y, z=minp.z}, {x=maxp.x, y=maxp.y, z=maxp.z}, true)
  1027. minetest.save_gen_notify("jarkati:mapgen_info", gennotify_data)
  1028. end
  1029. -- Register the mapgen callback.
  1030. minetest.register_on_generated(function(...)
  1031. jarkati.generate_realm(...)
  1032. end)