mapgen.lua 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649
  1. -- Mapgen Environment ONLY.
  2. -- Not reloadable!
  3. cw = {}
  4. cw.modpath = minetest.get_modpath("cw")
  5. cw.worldpath = minetest.get_worldpath()
  6. -- Localize for performance.
  7. local math_random = math.random
  8. -- Disable for testing terrain shapes without all that foliage.
  9. local ENABLE_TREES = true
  10. local TREE_HEIGHT_MOD = 13
  11. -- Param2 horizontal branch rotations.
  12. local branch_rotations = {4, 8, 12, 16}
  13. local branch_directions = {2, 0, 3, 1}
  14. cw.REALM_START = 3050
  15. cw.BEDROCK_DEPTH = 4
  16. cw.OCEAN_DEPTH = 16
  17. cw.GROUND_DEPTH = 11
  18. cw.GROUND_HEIGHT_VARIATION = 4
  19. -- Controls land height.
  20. cw.noise1param2d = {
  21. offset = 0,
  22. scale = 1,
  23. spread = {x=128, y=128, z=128},
  24. seed = 3717,
  25. octaves = 5,
  26. persist = 0.5,
  27. lacunarity = 2,
  28. }
  29. -- Large scale land height.
  30. local LAND_SCALE = 2048
  31. cw.noise3param2d = {
  32. offset = 0,
  33. scale = 1,
  34. spread = {x=LAND_SCALE, y=LAND_SCALE, z=LAND_SCALE},
  35. seed = 8872,
  36. octaves = 7,
  37. persist = 0.6,
  38. lacunarity = 1.8,
  39. }
  40. -- Rivers.
  41. local RIVER_SCALE = 1024
  42. local RIVER_WIDTH = 0.03
  43. local RIVER_DEPTH = 8
  44. local RIVER_OCEAN_LIMIT = 6
  45. cw.noise4param2d = {
  46. offset = 0,
  47. scale = 1,
  48. spread = {x=RIVER_SCALE, y=RIVER_SCALE, z=RIVER_SCALE},
  49. seed = 7718,
  50. octaves = 2,
  51. persist = 0.5,
  52. lacunarity = 2.0,
  53. }
  54. cw.noise2param2d = {
  55. offset = 0,
  56. scale = 1,
  57. spread = {x=32, y=32, z=32},
  58. seed = 5817,
  59. octaves = 4,
  60. persist = 0.8,
  61. lacunarity = 2,
  62. }
  63. -- Content IDs used with the voxel manipulator.
  64. local c_air = minetest.get_content_id("air")
  65. local c_ignore = minetest.get_content_id("ignore")
  66. local c_stone = minetest.get_content_id("default:stone")
  67. local c_bedrock = minetest.get_content_id("bedrock:bedrock")
  68. local c_water = minetest.get_content_id("cw:water_source")
  69. local c_dirt = minetest.get_content_id("darkage:darkdirt")
  70. local c_silt = minetest.get_content_id("darkage:silt")
  71. local c_mud = minetest.get_content_id("darkage:mud")
  72. local c_clay = minetest.get_content_id("default:clay")
  73. local c_lily = minetest.get_content_id("flowers:waterlily")
  74. local c_tree = minetest.get_content_id("basictrees:jungletree_cube")
  75. local c_tree2 = minetest.get_content_id("basictrees:jungletree_trunk")
  76. local c_leaves = minetest.get_content_id("basictrees:jungletree_leaves2")
  77. local c_soil = minetest.get_content_id("default:dirt_with_rainforest_litter")
  78. local c_junglegrass = minetest.get_content_id("default:junglegrass")
  79. local c_grass = minetest.get_content_id("default:grass_5")
  80. local c_grass2 = minetest.get_content_id("default:dry_grass2_5")
  81. local c_grass3 = minetest.get_content_id("default:marram_grass_3")
  82. local c_papyrus2 = minetest.get_content_id("default:papyrus2")
  83. local c_sand = minetest.get_content_id("default:sand")
  84. -- Externally located tables for performance.
  85. local data = {}
  86. local param2_data = {}
  87. local noisemap1 = {}
  88. local noisemap2 = {}
  89. local noisemap3 = {}
  90. local noisemap4 = {}
  91. local JUNGLETREE_REPLACEMENTS = {
  92. ["default:jungletree"] = "basictrees:jungletree_cube",
  93. ["default:jungleleaves"] = "basictrees:jungletree_leaves2",
  94. }
  95. -- Offsets for tall trees (tree has a chance to lean, be not perfectly straight).
  96. local RANDPOS = {
  97. {x=1, y=0, z=0},
  98. {x=-1, y=0, z=0},
  99. {x=0, y=0, z=1},
  100. {x=0, y=0, z=-1},
  101. -- 3 times to increase probability.
  102. {x=0, y=0, z=0},
  103. {x=0, y=0, z=0},
  104. {x=0, y=0, z=0},
  105. }
  106. local DRY_LEAVES_LIST = {
  107. minetest.get_content_id("dryleaves:leaves"),
  108. minetest.get_content_id("dryleaves:jungleleaves"),
  109. minetest.get_content_id("dryleaves:dry_leaves"),
  110. minetest.get_content_id("dryleaves:plantlike"),
  111. }
  112. cw.generate_realm = function(vm, minp, maxp, seed)
  113. local nstart = cw.REALM_START
  114. --minp = table.copy(minp)
  115. --maxp = table.copy(maxp)
  116. -- Don't run for out-of-bounds mapchunks.
  117. local nfinish = nstart + 100
  118. if minp.y > nfinish or maxp.y < nstart then
  119. return
  120. end
  121. -- Generate the full column all at once.
  122. --[[
  123. if minp.y > nstart then
  124. minp.y = nstart
  125. end
  126. if maxp.y < nfinish then
  127. maxp.y = nfinish
  128. end
  129. --]]
  130. -- Grab the voxel manipulator.
  131. -- Read current map data.
  132. --local vm = VoxelManip()
  133. --local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
  134. --vm:read_from_map(vector.subtract(minp, 16), vector.add(maxp, 16))
  135. local emin, emax = vm:get_emerged_area()
  136. vm:get_data(data)
  137. local area = VoxelArea:new({MinEdge=emin, MaxEdge=emax})
  138. local pr = PseudoRandom(seed + 381)
  139. -- Special PRNG which MUST ensure the SAME output for all chunks in a column!
  140. -- This is required for the tall trees, which cross mapchunk boundaries.
  141. local column_pr = PseudoRandom(minetest.hash_node_position({x=minp.x, y=0, z=minp.z}))
  142. --local column_pr = pr
  143. local x1 = maxp.x
  144. local y1 = maxp.y
  145. local z1 = maxp.z
  146. local x0 = minp.x
  147. local y0 = minp.y
  148. local z0 = minp.z
  149. -- Compute side lengths.
  150. local side_len_x = ((x1-x0)+1)
  151. local side_len_z = ((z1-z0)+1)
  152. local sides2D = {x=side_len_x, y=side_len_z}
  153. local bp2d = {x=x0, y=z0}
  154. -- Get noisemaps.
  155. local perlin1 = minetest.get_perlin_map(cw.noise1param2d, sides2D)
  156. perlin1:get_2d_map_flat(bp2d, noisemap1)
  157. local perlin2 = minetest.get_perlin_map(cw.noise2param2d, sides2D)
  158. perlin2:get_2d_map_flat(bp2d, noisemap2)
  159. local perlin3 = minetest.get_perlin_map(cw.noise3param2d, sides2D)
  160. perlin3:get_2d_map_flat(bp2d, noisemap3)
  161. local perlin4 = minetest.get_perlin_map(cw.noise4param2d, sides2D)
  162. perlin4:get_2d_map_flat(bp2d, noisemap4)
  163. -- Localize commonly used functions.
  164. local floor = math.floor
  165. local ceil = math.ceil
  166. local abs = math.abs
  167. local od = cw.OCEAN_DEPTH
  168. local bd = cw.BEDROCK_DEPTH
  169. local gd = cw.GROUND_DEPTH
  170. local ghv = cw.GROUND_HEIGHT_VARIATION
  171. local tree_positions1 = {}
  172. local lily_positions1 = {}
  173. -- First mapgen pass.
  174. for z = z0, z1 do
  175. for x = x0, x1 do
  176. -- Get index into 2D noise arrays.
  177. local nx = (x-x0)
  178. local nz = (z-z0)
  179. local ni2 = (side_len_z*nz+nx)
  180. -- Lua arrays start indexing at 1, not 0. Urrrrgh.
  181. ni2 = ni2 + 1
  182. local n1 = noisemap1[ni2]
  183. local n2 = noisemap2[ni2]
  184. local n3 = noisemap3[ni2]
  185. local n4 = noisemap4[ni2]
  186. -- Randomize height of the bedrock a bit.
  187. local bedrock_adjust = (nstart + bd + pr:next(0, pr:next(1, 2)))
  188. local clay_depth = (nstart + bd + pr:next(1, 2))
  189. -- Fixed ocean height.
  190. local ocean_depth = (nstart + od)
  191. local ocean_surface = ocean_depth + 1
  192. -- Ground height.
  193. local an1 = abs(n1) + ((n3 + 0.25) * 2)
  194. local ground_depth = (nstart + gd + floor(an1 * ghv))
  195. -- As land climbs above sea level, deepen rivers to compensate.
  196. local r_depth = RIVER_DEPTH
  197. if ground_depth > ocean_depth then
  198. r_depth = r_depth + (ground_depth - ocean_depth)
  199. end
  200. -- Large rivers.
  201. local r4 = abs(n4)
  202. if r4 <= RIVER_WIDTH then
  203. -- Don't forget to floor it, otherwise we get glitches.
  204. r4 = math.floor((((r4 / RIVER_WIDTH) * -1) + 1) * r_depth)
  205. else
  206. r4 = 0
  207. end
  208. -- Prevent rivers from digging too deep in the ocean.
  209. if (ground_depth - r4) < (ocean_depth - RIVER_OCEAN_LIMIT) then
  210. ground_depth = (ocean_depth - RIVER_OCEAN_LIMIT)
  211. else
  212. ground_depth = ground_depth - r4
  213. end
  214. local water_depth = (ocean_depth - ground_depth)
  215. local lily_chance = 1000
  216. if water_depth <= 2 then
  217. if column_pr:next(1, 10) == 1 then
  218. tree_positions1[#tree_positions1+1] = {x=x, y=ground_depth, z=z, w=an1}
  219. end
  220. lily_chance = 50
  221. elseif water_depth == 3 then
  222. if column_pr:next(1, 40) == 1 then
  223. tree_positions1[#tree_positions1+1] = {x=x, y=ground_depth, z=z, w=an1}
  224. end
  225. lily_chance = 150
  226. elseif water_depth == 4 then
  227. if column_pr:next(1, 300) == 1 then
  228. tree_positions1[#tree_positions1+1] = {x=x, y=ground_depth, z=z, w=an1}
  229. end
  230. lily_chance = 200
  231. end
  232. -- Enable waterlilies.
  233. local want_waterlily = false
  234. if pr:next(1, lily_chance) == 1 then
  235. want_waterlily = true
  236. end
  237. -- First pass through column.
  238. for y = y0, y1 do
  239. local vp = area:index(x, y, z)
  240. if y >= nstart and y <= nfinish then
  241. -- Get what's already here.
  242. local cid = data[vp]
  243. if cid == c_air or cid == c_ignore then
  244. -- Place bedrock layer.
  245. if y <= bedrock_adjust then
  246. data[vp] = c_bedrock
  247. elseif y <= clay_depth and water_depth >= 5 then
  248. data[vp] = c_clay
  249. elseif y < ground_depth then
  250. data[vp] = c_dirt
  251. elseif y == ground_depth then
  252. if ground_depth >= (ocean_depth + 3) then
  253. -- Mud turns to sand when ground is high enough.
  254. data[vp] = c_sand
  255. elseif ground_depth >= (ocean_depth - 1) then
  256. -- Mud appears when silt rises to water surface and above.
  257. data[vp] = c_mud
  258. else
  259. data[vp] = c_silt
  260. end
  261. elseif y <= ocean_depth then
  262. data[vp] = c_water
  263. elseif y == ocean_surface then
  264. if want_waterlily then
  265. data[vp] = c_lily
  266. end
  267. end
  268. end
  269. end
  270. end
  271. end
  272. end
  273. vm:set_data(data)
  274. if ENABLE_TREES then
  275. local JP = JUNGLETREE_REPLACEMENTS
  276. local FP = false -- Force place
  277. local strrnd = "random"
  278. local function PUT_SCHEM(vm, pos, schem, rot, replace, fp)
  279. -- Don't place trees intersecting chunk borders in the X,Z directions.
  280. local b = 5
  281. if pos.x >= (emin.x + b) and pos.x <= (emax.x - b) and
  282. pos.z >= (emin.z + b) and pos.z <= (emax.z - b) then
  283. minetest.place_schematic_on_vmanip(vm, pos, schem, rot, replace, fp)
  284. end
  285. end
  286. local treebase = cw.worldpath .. "/cw_jungletree_base.mts"
  287. local treetop = cw.worldpath .. "/cw_jungletree_top.mts"
  288. local notrunk = cw.worldpath .. "/cw_jungletree_notrunk.mts"
  289. --local treebase = cw.worldpath .. "/cw_jungletree_base.mts"
  290. --local treetop = cw.worldpath .. "/cw_jungletree_base.mts"
  291. --local notrunk = cw.worldpath .. "/cw_jungletree_base.mts"
  292. for k, v_orig in ipairs(tree_positions1) do
  293. local v = table.copy(v_orig)
  294. local bottom = v.y
  295. local w = v.w
  296. if w > 1.0 then
  297. w = 1.0
  298. end
  299. local h = math.floor(TREE_HEIGHT_MOD * w)
  300. v.w = nil
  301. -- Schematic horizontal offset.
  302. v.x = v.x - 2
  303. v.z = v.z - 2
  304. -- Tree base.
  305. PUT_SCHEM(vm, v, treebase, strrnd, JP, FP)
  306. ---[[
  307. local midleveltree = treetop
  308. if h >= (TREE_HEIGHT_MOD - 1) then
  309. -- Remove 1/3 of the trunks.
  310. if column_pr:next(1, 3) == 1 then
  311. midleveltree = notrunk
  312. end
  313. elseif h >= TREE_HEIGHT_MOD then
  314. -- Remove 2/3 of the trunks.
  315. if column_pr:next(1, 3) <= 2 then
  316. midleveltree = notrunk
  317. end
  318. elseif h > 10 then
  319. midleveltree = treebase
  320. end
  321. -- Require a minimum height step of 7 for taller trees.
  322. if column_pr:next(1, 5) <= 4 and h >= 7 then
  323. v.y = v.y + h
  324. if h > 10 then
  325. local rp = vector.add(v, RANDPOS[math_random(1, #RANDPOS)])
  326. PUT_SCHEM(vm, rp, midleveltree, strrnd, JP, FP)
  327. else
  328. PUT_SCHEM(vm, v, midleveltree, strrnd, JP, FP)
  329. end
  330. if column_pr:next(1, 3) <= 2 then
  331. v.y = v.y + h
  332. if h > 10 then
  333. local rp = vector.add(v, RANDPOS[math_random(1, #RANDPOS)])
  334. PUT_SCHEM(vm, rp, midleveltree, strrnd, JP, FP)
  335. else
  336. PUT_SCHEM(vm, v, midleveltree, strrnd, JP, FP)
  337. end
  338. -- Treetops.
  339. if h >= 10 then
  340. if column_pr:next(1, 2) == 1 then
  341. v.y = v.y + 13
  342. PUT_SCHEM(vm, v, treetop, strrnd, JP, FP)
  343. if h > 10 and column_pr:next(1, 3) == 1 then
  344. v.y = v.y + 13
  345. PUT_SCHEM(vm, v, treetop, strrnd, JP, FP)
  346. end
  347. end
  348. elseif h >= 8 then
  349. if column_pr:next(1, 3) == 1 then
  350. v.y = v.y + 12
  351. PUT_SCHEM(vm, v, treetop, strrnd, JP, FP)
  352. end
  353. end
  354. end
  355. end
  356. --]]
  357. -- Store tree bottom/top.
  358. v_orig.b = bottom
  359. v_orig.t = v.y + 17
  360. end
  361. end -- ENABLE_TREES
  362. -- Shall return true if ID is anything the mapgen places as part of forests.
  363. local function farsig(id)
  364. return (id == c_leaves or id == c_tree or id == c_tree2 or id == c_soil
  365. or id == c_junglegrass or id == c_grass)
  366. end
  367. -- Shall return true if ID is a supporting structural node.
  368. local function nearsup(id)
  369. return (id == c_leaves or id == c_soil or id == c_tree or id == c_tree2)
  370. end
  371. -- Final mapgen pass, for finding floors and ceilings in the forest.
  372. -- Have to "get_data" again because we placed a bunch of schematics on the vmanip.
  373. vm:get_data(data)
  374. vm:get_param2_data(param2_data)
  375. for x = x0, x1 do
  376. for z = z0, z1 do
  377. for y = y0, y1 do
  378. local center = area:index(x, y, z)
  379. local under = area:index(x, y-1, z)
  380. local above = area:index(x, y+1, z)
  381. local north = area:index(x, y, z+1)
  382. local south = area:index(x, y, z-1)
  383. local east = area:index(x+1, y, z)
  384. local west = area:index(x-1, y, z)
  385. local sevenup = area:index(x, y+7, z)
  386. local farnorth = area:index(x, y, z+7)
  387. local farsouth = area:index(x, y, z-7)
  388. local fareast = area:index(x+7, y, z)
  389. local farwest = area:index(x-7, y, z)
  390. local center_id = data[center]
  391. local above_id = data[above]
  392. local under_id = data[under]
  393. local north_id = data[north]
  394. local south_id = data[south]
  395. local west_id = data[west]
  396. local east_id = data[east]
  397. local sevenup_id = data[sevenup]
  398. local farnorth_id = data[farnorth]
  399. local farsouth_id = data[farsouth]
  400. local farwest_id = data[farwest]
  401. local fareast_id = data[fareast]
  402. -- Decorations not to be placed in the tops of forests.
  403. if y < (nstart + 60) then
  404. -- Check if we have neighboring supports directly adjacent to us.
  405. local border_count = 0
  406. if nearsup(north_id) then
  407. border_count = border_count + 1
  408. end
  409. if nearsup(south_id) then
  410. border_count = border_count + 1
  411. end
  412. if nearsup(west_id) then
  413. border_count = border_count + 1
  414. end
  415. if nearsup(east_id) then
  416. border_count = border_count + 1
  417. end
  418. -- Check if we have neighboring trees at a distance.
  419. -- This reduces border count at the edges of forest clusters, and
  420. -- at altitude where the trees are thinner.
  421. local far_count = 0
  422. if farsig(farnorth_id) then
  423. far_count = far_count + 1
  424. end
  425. if farsig(farsouth_id) then
  426. far_count = far_count + 1
  427. end
  428. if farsig(farwest_id) then
  429. far_count = far_count + 1
  430. end
  431. if farsig(fareast_id) then
  432. far_count = far_count + 1
  433. end
  434. local water_count = 0
  435. if north_id == c_water then
  436. water_count = water_count + 1
  437. end
  438. if south_id == c_water then
  439. water_count = water_count + 1
  440. end
  441. if west_id == c_water then
  442. water_count = water_count + 1
  443. end
  444. if east_id == c_water then
  445. water_count = water_count + 1
  446. end
  447. local roofed = (sevenup_id == c_tree or sevenup_id == c_tree2 or sevenup_id == c_leaves or sevenup_id == c_junglegrass)
  448. local support = (under_id == c_leaves or under_id == c_tree or under_id == c_tree2)
  449. local fillable = (center_id == c_air or (center_id == c_leaves and above_id == c_air))
  450. local grassable = (center_id == c_air)
  451. if roofed and fillable and support and border_count >= 4 and far_count >= 4 then
  452. data[center] = c_soil
  453. -- Put a horizontal branch peice underneath the soil.
  454. data[under] = c_tree2
  455. param2_data[under] = branch_rotations[math_random(1, 4)]
  456. elseif roofed and support and grassable and far_count >= 3 then
  457. -- Randomly place grass or junglegrass.
  458. if math_random(1, 3) == 1 then
  459. data[center] = c_grass
  460. else
  461. data[center] = c_junglegrass
  462. end
  463. param2_data[center] = 2
  464. elseif above_id == c_air and center_id == c_tree and water_count >= 2 then
  465. -- Place grass on trunks near water.
  466. if math_random(1, 3) == 1 then
  467. data[above] = c_grass
  468. else
  469. data[above] = c_grass2
  470. end
  471. param2_data[above] = 2
  472. elseif center_id == c_water and above_id == c_air and border_count >= 1 then
  473. -- Place lilies around tree trunks on water.
  474. if math_random(1, 4) == 1 then
  475. data[above] = c_lily
  476. param2_data[above] = math_random(0, 3)
  477. end
  478. elseif center_id == c_sand and above_id == c_air and border_count >= 1 then
  479. if math_random(1, 2) == 1 then
  480. data[above] = c_grass3
  481. param2_data[above] = 2
  482. end
  483. end
  484. -- Horizontal branch placement.
  485. if center_id == c_tree and roofed and (under_id == c_leaves or above_id == c_leaves) then
  486. if param2_data[center] == 0 then
  487. local diridx = math_random(1, 4)
  488. local facedir = branch_directions[diridx]
  489. data[center] = c_tree2
  490. param2_data[center] = branch_rotations[diridx]
  491. -- Extend branches horizontally.
  492. -- Branches get longer (2 + far_count) if trees are denser.
  493. local dir = minetest.facedir_to_dir(facedir)
  494. local n = math_random(0, 2 + far_count)
  495. local pos = {x=x, y=y, z=z}
  496. for k = 1, n, 1 do
  497. pos = vector.add(pos, dir)
  498. local idx = area:index(pos.x, pos.y, pos.z)
  499. data[idx] = c_tree2
  500. param2_data[idx] = branch_rotations[diridx]
  501. -- Place leaves at end of branch.
  502. local p2 = vector.add(pos, dir)
  503. local i2 = area:index(p2.x, p2.y, p2.z)
  504. if data[i2] == c_air then
  505. data[i2] = c_leaves
  506. end
  507. -- Place leaves hanging from branch.
  508. local p3 = vector.add(pos, {x=0, y=-1, z=0})
  509. local i3 = area:index(p3.x, p3.y, p3.z)
  510. if data[i3] == c_air then
  511. data[i3] = c_leaves
  512. end
  513. end
  514. end
  515. end
  516. end -- Y below (nstart + 60).
  517. -- Hanging papyrus.
  518. if center_id == c_air and above_id == c_leaves and under_id == c_air then
  519. if math_random(1, 50) == 1 then
  520. local pos = {x=x, y=y, z=z}
  521. local n = math_random(2, 8)
  522. for k = 1, n, 1 do
  523. local idx = area:index(pos.x, pos.y, pos.z)
  524. pos.y = pos.y - 1
  525. if data[idx] == c_air then
  526. data[idx] = c_papyrus2
  527. else
  528. break
  529. end
  530. end
  531. end
  532. end
  533. -- Convert a percentage of leaves into dry leaves.
  534. if center_id == c_leaves and under_id == c_leaves then
  535. if math_random(1, 100) <= 5 then
  536. data[center] = DRY_LEAVES_LIST[math_random(1, #DRY_LEAVES_LIST)]
  537. param2_data[center] = 2
  538. end
  539. end
  540. end
  541. end
  542. end
  543. vm:set_data(data)
  544. vm:set_param2_data(param2_data)
  545. -- Finalize voxel manipulator.
  546. -- Note: we specifically do not generate ores! The value of this realm is in
  547. -- its trees.
  548. vm:set_lighting({day=0, night=0})
  549. vm:calc_lighting()
  550. -- Liquid is never added in a way that would require flowing update.
  551. --vm:update_liquids()
  552. --vm:write_to_map()
  553. --[[
  554. for k, v in ipairs(tree_positions1) do
  555. local bottom = v.y
  556. local top = v.t
  557. -- This is somewhat intensive, so don't run for every single tree.
  558. if math_random(1, 5) == 1 then
  559. local minp = {x=v.x - 2, y=bottom, z=v.z - 2}
  560. local maxp = {x=v.x + 2, y=top, z=v.z + 2}
  561. dryleaves.replace_leaves(minp, maxp, 5)
  562. end
  563. end
  564. --]]
  565. end
  566. minetest.register_on_generated(function(...)
  567. cw.generate_realm(...)
  568. end)