Fix possible crash in mcl_mapgen_core
[MineClone/MineClone2.git] / mods / MAPGEN / mcl_mapgen_core / init.lua
blob8eee6b132fbbf3adbc0d6e64c354755df6eb82a7
1 --
2 -- Aliases for map generator outputs
3 --
5 minetest.register_alias("mapgen_air", "air")
6 minetest.register_alias("mapgen_stone", "mcl_core:stone")
7 minetest.register_alias("mapgen_tree", "mcl_core:tree")
8 minetest.register_alias("mapgen_leaves", "mcl_core:leaves")
9 minetest.register_alias("mapgen_jungletree", "mcl_core:jungletree")
10 minetest.register_alias("mapgen_jungleleaves", "mcl_core:jungleleaves")
11 minetest.register_alias("mapgen_pine_tree", "mcl_core:sprucetree")
12 minetest.register_alias("mapgen_pine_needles", "mcl_core:spruceleaves")
14 minetest.register_alias("mapgen_apple", "mcl_core:leaves")
15 minetest.register_alias("mapgen_water_source", "mcl_core:water_source")
16 minetest.register_alias("mapgen_dirt", "mcl_core:dirt")
17 minetest.register_alias("mapgen_dirt_with_grass", "mcl_core:dirt_with_grass")
18 minetest.register_alias("mapgen_dirt_with_snow", "mcl_core:dirt_with_grass_snow")
19 minetest.register_alias("mapgen_sand", "mcl_core:sand")
20 minetest.register_alias("mapgen_gravel", "mcl_core:gravel")
21 minetest.register_alias("mapgen_clay", "mcl_core:clay")
22 minetest.register_alias("mapgen_lava_source", "air") -- Built-in lava generator is too unpredictable, we generate lava on our own
23 minetest.register_alias("mapgen_cobble", "mcl_core:cobble")
24 minetest.register_alias("mapgen_mossycobble", "mcl_core:mossycobble")
25 minetest.register_alias("mapgen_junglegrass", "mcl_flowers:fern")
26 minetest.register_alias("mapgen_stone_with_coal", "mcl_core:stone_with_coal")
27 minetest.register_alias("mapgen_stone_with_iron", "mcl_core:stone_with_iron")
28 minetest.register_alias("mapgen_desert_sand", "mcl_core:sand")
29 minetest.register_alias("mapgen_desert_stone", "mcl_core:sandstone")
30 minetest.register_alias("mapgen_sandstone", "mcl_core:sandstone")
31 if minetest.get_modpath("mclx_core") then
32 minetest.register_alias("mapgen_river_water_source", "mclx_core:river_water_source")
33 else
34 minetest.register_alias("mapgen_river_water_source", "mcl_core:water_source")
35 end
36 minetest.register_alias("mapgen_snow", "mcl_core:snow")
37 minetest.register_alias("mapgen_snowblock", "mcl_core:snowblock")
38 minetest.register_alias("mapgen_ice", "mcl_core:ice")
40 minetest.register_alias("mapgen_stair_cobble", "mcl_stairs:stair_cobble")
41 minetest.register_alias("mapgen_sandstonebrick", "mcl_core:sandstonesmooth")
42 minetest.register_alias("mapgen_stair_sandstonebrick", "mcl_stairs:stair_sandstone")
43 minetest.register_alias("mapgen_stair_sandstone_block", "mcl_stairs:stair_sandstone")
44 minetest.register_alias("mapgen_stair_desert_stone", "mcl_stairs:stair_sandstone")
46 local mg_name = minetest.get_mapgen_setting("mg_name")
48 local WITCH_HUT_HEIGHT = 3 -- Exact Y level to spawn witch huts at. This height refers to the height of the floor
50 -- End exit portal position. This is temporary.
51 -- TODO: Remove the exit portal generation when the ender dragon has been implemented.
52 local END_EXIT_PORTAL_POS = table.copy(mcl_vars.mg_end_platform_pos)
53 END_EXIT_PORTAL_POS.x = END_EXIT_PORTAL_POS.x - 30
54 END_EXIT_PORTAL_POS.z = END_EXIT_PORTAL_POS.z - 3
55 END_EXIT_PORTAL_POS.y = END_EXIT_PORTAL_POS.y - 3
57 -- Content IDs
58 local c_bedrock = minetest.get_content_id("mcl_core:bedrock")
59 local c_obsidian = minetest.get_content_id("mcl_core:obsidian")
60 local c_stone = minetest.get_content_id("mcl_core:stone")
61 local c_dirt = minetest.get_content_id("mcl_core:dirt")
62 local c_dirt_with_grass = minetest.get_content_id("mcl_core:dirt_with_grass")
63 local c_dirt_with_grass_snow = minetest.get_content_id("mcl_core:dirt_with_grass_snow")
64 local c_sand = minetest.get_content_id("mcl_core:sand")
65 local c_sandstone = minetest.get_content_id("mcl_core:sandstone")
66 local c_redsand = minetest.get_content_id("mcl_core:redsand")
67 local c_redsandstone = minetest.get_content_id("mcl_core:redsandstone")
68 local c_void = minetest.get_content_id("mcl_core:void")
69 local c_lava = minetest.get_content_id("mcl_core:lava_source")
70 local c_water = minetest.get_content_id("mcl_core:water_source")
71 local c_soul_sand = minetest.get_content_id("mcl_nether:soul_sand")
72 local c_netherrack = minetest.get_content_id("mcl_nether:netherrack")
73 local c_nether_lava = minetest.get_content_id("mcl_nether:nether_lava_source")
74 local c_end_stone = minetest.get_content_id("mcl_end:end_stone")
75 local c_realm_barrier = minetest.get_content_id("mcl_core:realm_barrier")
76 local c_top_snow = minetest.get_content_id("mcl_core:snow")
77 local c_snow_block = minetest.get_content_id("mcl_core:snowblock")
78 local c_clay = minetest.get_content_id("mcl_core:clay")
79 local c_leaves = minetest.get_content_id("mcl_core:leaves")
80 local c_jungleleaves = minetest.get_content_id("mcl_core:jungleleaves")
81 local c_jungletree = minetest.get_content_id("mcl_core:jungletree")
82 local c_cocoa_1 = minetest.get_content_id("mcl_cocoas:cocoa_1")
83 local c_cocoa_2 = minetest.get_content_id("mcl_cocoas:cocoa_2")
84 local c_cocoa_3 = minetest.get_content_id("mcl_cocoas:cocoa_3")
85 local c_vine = minetest.get_content_id("mcl_core:vine")
86 local c_air = minetest.CONTENT_AIR
89 -- Ore generation
92 -- Diorite, andesite and granite
93 local specialstones = { "mcl_core:diorite", "mcl_core:andesite", "mcl_core:granite" }
94 for s=1, #specialstones do
95 local node = specialstones[s]
96 minetest.register_ore({
97 ore_type = "blob",
98 ore = node,
99 wherein = {"mcl_core:stone"},
100 clust_scarcity = 15*15*15,
101 clust_num_ores = 33,
102 clust_size = 5,
103 y_min = mcl_vars.mg_overworld_min,
104 y_max = mcl_vars.mg_overworld_max,
106 minetest.register_ore({
107 ore_type = "blob",
108 ore = node,
109 wherein = {"mcl_core:stone"},
110 clust_scarcity = 10*10*10,
111 clust_num_ores = 58,
112 clust_size = 7,
113 y_min = mcl_vars.mg_overworld_min,
114 y_max = mcl_vars.mg_overworld_max,
118 local stonelike = {"mcl_core:stone", "mcl_core:diorite", "mcl_core:andesite", "mcl_core:granite"}
120 -- Dirt
121 minetest.register_ore({
122 ore_type = "blob",
123 ore = "mcl_core:dirt",
124 wherein = stonelike,
125 clust_scarcity = 15*15*15,
126 clust_num_ores = 33,
127 clust_size = 4,
128 y_min = mcl_vars.mg_overworld_min,
129 y_max = mcl_vars.mg_overworld_max,
132 -- Gravel
133 minetest.register_ore({
134 ore_type = "blob",
135 ore = "mcl_core:gravel",
136 wherein = stonelike,
137 clust_scarcity = 14*14*14,
138 clust_num_ores = 33,
139 clust_size = 5,
140 y_min = mcl_vars.mg_overworld_min,
141 y_max = mcl_worlds.layer_to_y(111),
145 -- Coal
148 -- Common spawn
149 minetest.register_ore({
150 ore_type = "scatter",
151 ore = "mcl_core:stone_with_coal",
152 wherein = stonelike,
153 clust_scarcity = 525*3,
154 clust_num_ores = 5,
155 clust_size = 3,
156 y_min = mcl_vars.mg_overworld_min,
157 y_max = mcl_worlds.layer_to_y(50),
159 minetest.register_ore({
160 ore_type = "scatter",
161 ore = "mcl_core:stone_with_coal",
162 wherein = stonelike,
163 clust_scarcity = 510*3,
164 clust_num_ores = 8,
165 clust_size = 3,
166 y_min = mcl_vars.mg_overworld_min,
167 y_max = mcl_worlds.layer_to_y(50),
169 minetest.register_ore({
170 ore_type = "scatter",
171 ore = "mcl_core:stone_with_coal",
172 wherein = stonelike,
173 clust_scarcity = 500*3,
174 clust_num_ores = 12,
175 clust_size = 3,
176 y_min = mcl_vars.mg_overworld_min,
177 y_max = mcl_worlds.layer_to_y(50),
180 -- Medium-rare spawn
181 minetest.register_ore({
182 ore_type = "scatter",
183 ore = "mcl_core:stone_with_coal",
184 wherein = stonelike,
185 clust_scarcity = 550*3,
186 clust_num_ores = 4,
187 clust_size = 2,
188 y_min = mcl_worlds.layer_to_y(51),
189 y_max = mcl_worlds.layer_to_y(80),
191 minetest.register_ore({
192 ore_type = "scatter",
193 ore = "mcl_core:stone_with_coal",
194 wherein = stonelike,
195 clust_scarcity = 525*3,
196 clust_num_ores = 6,
197 clust_size = 3,
198 y_min = mcl_worlds.layer_to_y(51),
199 y_max = mcl_worlds.layer_to_y(80),
201 minetest.register_ore({
202 ore_type = "scatter",
203 ore = "mcl_core:stone_with_coal",
204 wherein = stonelike,
205 clust_scarcity = 500*3,
206 clust_num_ores = 8,
207 clust_size = 3,
208 y_min = mcl_worlds.layer_to_y(51),
209 y_max = mcl_worlds.layer_to_y(80),
212 -- Rare spawn
213 minetest.register_ore({
214 ore_type = "scatter",
215 ore = "mcl_core:stone_with_coal",
216 wherein = stonelike,
217 clust_scarcity = 600*3,
218 clust_num_ores = 3,
219 clust_size = 2,
220 y_min = mcl_worlds.layer_to_y(81),
221 y_max = mcl_worlds.layer_to_y(128),
223 minetest.register_ore({
224 ore_type = "scatter",
225 ore = "mcl_core:stone_with_coal",
226 wherein = stonelike,
227 clust_scarcity = 550*3,
228 clust_num_ores = 4,
229 clust_size = 3,
230 y_min = mcl_worlds.layer_to_y(81),
231 y_max = mcl_worlds.layer_to_y(128),
233 minetest.register_ore({
234 ore_type = "scatter",
235 ore = "mcl_core:stone_with_coal",
236 wherein = stonelike,
237 clust_scarcity = 500*3,
238 clust_num_ores = 5,
239 clust_size = 3,
240 y_min = mcl_worlds.layer_to_y(81),
241 y_max = mcl_worlds.layer_to_y(128),
245 -- Iron
247 minetest.register_ore({
248 ore_type = "scatter",
249 ore = "mcl_core:stone_with_iron",
250 wherein = stonelike,
251 clust_scarcity = 830,
252 clust_num_ores = 5,
253 clust_size = 3,
254 y_min = mcl_vars.mg_overworld_min,
255 y_max = mcl_worlds.layer_to_y(39),
257 minetest.register_ore({
258 ore_type = "scatter",
259 ore = "mcl_core:stone_with_iron",
260 wherein = stonelike,
261 clust_scarcity = 1660,
262 clust_num_ores = 4,
263 clust_size = 2,
264 y_min = mcl_worlds.layer_to_y(40),
265 y_max = mcl_worlds.layer_to_y(63),
269 -- Gold
272 -- Common spawn
273 minetest.register_ore({
274 ore_type = "scatter",
275 ore = "mcl_core:stone_with_gold",
276 wherein = stonelike,
277 clust_scarcity = 4775,
278 clust_num_ores = 5,
279 clust_size = 3,
280 y_min = mcl_vars.mg_overworld_min,
281 y_max = mcl_worlds.layer_to_y(30),
283 minetest.register_ore({
284 ore_type = "scatter",
285 ore = "mcl_core:stone_with_gold",
286 wherein = stonelike,
287 clust_scarcity = 6560,
288 clust_num_ores = 7,
289 clust_size = 3,
290 y_min = mcl_vars.mg_overworld_min,
291 y_max = mcl_worlds.layer_to_y(30),
294 -- Rare spawn
295 minetest.register_ore({
296 ore_type = "scatter",
297 ore = "mcl_core:stone_with_gold",
298 wherein = stonelike,
299 clust_scarcity = 13000,
300 clust_num_ores = 4,
301 clust_size = 2,
302 y_min = mcl_worlds.layer_to_y(31),
303 y_max = mcl_worlds.layer_to_y(33),
307 -- Diamond
310 -- Common spawn
311 minetest.register_ore({
312 ore_type = "scatter",
313 ore = "mcl_core:stone_with_diamond",
314 wherein = stonelike,
315 clust_scarcity = 10000,
316 clust_num_ores = 4,
317 clust_size = 3,
318 y_min = mcl_vars.mg_overworld_min,
319 y_max = mcl_worlds.layer_to_y(12),
321 minetest.register_ore({
322 ore_type = "scatter",
323 ore = "mcl_core:stone_with_diamond",
324 wherein = stonelike,
325 clust_scarcity = 5000,
326 clust_num_ores = 2,
327 clust_size = 2,
328 y_min = mcl_vars.mg_overworld_min,
329 y_max = mcl_worlds.layer_to_y(12),
331 minetest.register_ore({
332 ore_type = "scatter",
333 ore = "mcl_core:stone_with_diamond",
334 wherein = stonelike,
335 clust_scarcity = 10000,
336 clust_num_ores = 8,
337 clust_size = 3,
338 y_min = mcl_vars.mg_overworld_min,
339 y_max = mcl_worlds.layer_to_y(12),
342 -- Rare spawn
343 minetest.register_ore({
344 ore_type = "scatter",
345 ore = "mcl_core:stone_with_diamond",
346 wherein = stonelike,
347 clust_scarcity = 20000,
348 clust_num_ores = 1,
349 clust_size = 1,
350 y_min = mcl_worlds.layer_to_y(13),
351 y_max = mcl_worlds.layer_to_y(15),
353 minetest.register_ore({
354 ore_type = "scatter",
355 ore = "mcl_core:stone_with_diamond",
356 wherein = stonelike,
357 clust_scarcity = 20000,
358 clust_num_ores = 2,
359 clust_size = 2,
360 y_min = mcl_worlds.layer_to_y(13),
361 y_max = mcl_worlds.layer_to_y(15),
365 -- Redstone
368 -- Common spawn
369 minetest.register_ore({
370 ore_type = "scatter",
371 ore = "mcl_core:stone_with_redstone",
372 wherein = stonelike,
373 clust_scarcity = 500,
374 clust_num_ores = 4,
375 clust_size = 3,
376 y_min = mcl_vars.mg_overworld_min,
377 y_max = mcl_worlds.layer_to_y(13),
379 minetest.register_ore({
380 ore_type = "scatter",
381 ore = "mcl_core:stone_with_redstone",
382 wherein = stonelike,
383 clust_scarcity = 800,
384 clust_num_ores = 7,
385 clust_size = 4,
386 y_min = mcl_vars.mg_overworld_min,
387 y_max = mcl_worlds.layer_to_y(13),
390 -- Rare spawn
391 minetest.register_ore({
392 ore_type = "scatter",
393 ore = "mcl_core:stone_with_redstone",
394 wherein = stonelike,
395 clust_scarcity = 1000,
396 clust_num_ores = 4,
397 clust_size = 3,
398 y_min = mcl_worlds.layer_to_y(13),
399 y_max = mcl_worlds.layer_to_y(15),
401 minetest.register_ore({
402 ore_type = "scatter",
403 ore = "mcl_core:stone_with_redstone",
404 wherein = stonelike,
405 clust_scarcity = 1600,
406 clust_num_ores = 7,
407 clust_size = 4,
408 y_min = mcl_worlds.layer_to_y(13),
409 y_max = mcl_worlds.layer_to_y(15),
413 -- Emerald
416 if mg_name == "v6" then
417 -- Generate everywhere in v6, but rarely.
419 -- Common spawn
420 minetest.register_ore({
421 ore_type = "scatter",
422 ore = "mcl_core:stone_with_emerald",
423 wherein = stonelike,
424 clust_scarcity = 14340,
425 clust_num_ores = 1,
426 clust_size = 1,
427 y_min = mcl_vars.mg_overworld_min,
428 y_max = mcl_worlds.layer_to_y(29),
430 -- Rare spawn
431 minetest.register_ore({
432 ore_type = "scatter",
433 ore = "mcl_core:stone_with_emerald",
434 wherein = stonelike,
435 clust_scarcity = 21510,
436 clust_num_ores = 1,
437 clust_size = 1,
438 y_min = mcl_worlds.layer_to_y(30),
439 y_max = mcl_worlds.layer_to_y(32),
444 -- Lapis Lazuli
447 -- Common spawn (in the center)
448 minetest.register_ore({
449 ore_type = "scatter",
450 ore = "mcl_core:stone_with_lapis",
451 wherein = stonelike,
452 clust_scarcity = 10000,
453 clust_num_ores = 7,
454 clust_size = 4,
455 y_min = mcl_worlds.layer_to_y(14),
456 y_max = mcl_worlds.layer_to_y(16),
459 -- Rare spawn (below center)
460 minetest.register_ore({
461 ore_type = "scatter",
462 ore = "mcl_core:stone_with_lapis",
463 wherein = stonelike,
464 clust_scarcity = 12000,
465 clust_num_ores = 6,
466 clust_size = 3,
467 y_min = mcl_worlds.layer_to_y(10),
468 y_max = mcl_worlds.layer_to_y(13),
470 minetest.register_ore({
471 ore_type = "scatter",
472 ore = "mcl_core:stone_with_lapis",
473 wherein = stonelike,
474 clust_scarcity = 14000,
475 clust_num_ores = 5,
476 clust_size = 3,
477 y_min = mcl_worlds.layer_to_y(6),
478 y_max = mcl_worlds.layer_to_y(9),
480 minetest.register_ore({
481 ore_type = "scatter",
482 ore = "mcl_core:stone_with_lapis",
483 wherein = stonelike,
484 clust_scarcity = 16000,
485 clust_num_ores = 4,
486 clust_size = 3,
487 y_min = mcl_worlds.layer_to_y(2),
488 y_max = mcl_worlds.layer_to_y(5),
490 minetest.register_ore({
491 ore_type = "scatter",
492 ore = "mcl_core:stone_with_lapis",
493 wherein = stonelike,
494 clust_scarcity = 18000,
495 clust_num_ores = 3,
496 clust_size = 2,
497 y_min = mcl_worlds.layer_to_y(0),
498 y_max = mcl_worlds.layer_to_y(2),
501 -- Rare spawn (above center)
502 minetest.register_ore({
503 ore_type = "scatter",
504 ore = "mcl_core:stone_with_lapis",
505 wherein = stonelike,
506 clust_scarcity = 12000,
507 clust_num_ores = 6,
508 clust_size = 3,
509 y_min = mcl_worlds.layer_to_y(17),
510 y_max = mcl_worlds.layer_to_y(20),
512 minetest.register_ore({
513 ore_type = "scatter",
514 ore = "mcl_core:stone_with_lapis",
515 wherein = stonelike,
516 clust_scarcity = 14000,
517 clust_num_ores = 5,
518 clust_size = 3,
519 y_min = mcl_worlds.layer_to_y(21),
520 y_max = mcl_worlds.layer_to_y(24),
522 minetest.register_ore({
523 ore_type = "scatter",
524 ore = "mcl_core:stone_with_lapis",
525 wherein = stonelike,
526 clust_scarcity = 16000,
527 clust_num_ores = 4,
528 clust_size = 3,
529 y_min = mcl_worlds.layer_to_y(25),
530 y_max = mcl_worlds.layer_to_y(28),
532 minetest.register_ore({
533 ore_type = "scatter",
534 ore = "mcl_core:stone_with_lapis",
535 wherein = stonelike,
536 clust_scarcity = 18000,
537 clust_num_ores = 3,
538 clust_size = 2,
539 y_min = mcl_worlds.layer_to_y(29),
540 y_max = mcl_worlds.layer_to_y(32),
542 minetest.register_ore({
543 ore_type = "scatter",
544 ore = "mcl_core:stone_with_lapis",
545 wherein = stonelike,
546 clust_scarcity = 32000,
547 clust_num_ores = 1,
548 clust_size = 1,
549 y_min = mcl_worlds.layer_to_y(31),
550 y_max = mcl_worlds.layer_to_y(32),
553 if mg_name ~= "flat" then
555 -- Water and lava springs (single blocks of lava/water source)
556 -- Water appears at nearly every height, but not near the bottom
557 minetest.register_ore({
558 ore_type = "scatter",
559 ore = "mcl_core:water_source",
560 wherein = {"mcl_core:stone", "mcl_core:andesite", "mcl_core:diorite", "mcl_core:granite", "mcl_core:dirt"},
561 clust_scarcity = 9000,
562 clust_num_ores = 1,
563 clust_size = 1,
564 y_min = mcl_worlds.layer_to_y(5),
565 y_max = mcl_worlds.layer_to_y(128),
568 -- Lava springs are rather common at -31 and below
569 minetest.register_ore({
570 ore_type = "scatter",
571 ore = "mcl_core:lava_source",
572 wherein = stonelike,
573 clust_scarcity = 2000,
574 clust_num_ores = 1,
575 clust_size = 1,
576 y_min = mcl_worlds.layer_to_y(1),
577 y_max = mcl_worlds.layer_to_y(10),
580 minetest.register_ore({
581 ore_type = "scatter",
582 ore = "mcl_core:lava_source",
583 wherein = stonelike,
584 clust_scarcity = 9000,
585 clust_num_ores = 1,
586 clust_size = 1,
587 y_min = mcl_worlds.layer_to_y(11),
588 y_max = mcl_worlds.layer_to_y(31),
591 -- Lava springs will become gradually rarer with increasing height
592 minetest.register_ore({
593 ore_type = "scatter",
594 ore = "mcl_core:lava_source",
595 wherein = stonelike,
596 clust_scarcity = 32000,
597 clust_num_ores = 1,
598 clust_size = 1,
599 y_min = mcl_worlds.layer_to_y(32),
600 y_max = mcl_worlds.layer_to_y(47),
603 minetest.register_ore({
604 ore_type = "scatter",
605 ore = "mcl_core:lava_source",
606 wherein = stonelike,
607 clust_scarcity = 72000,
608 clust_num_ores = 1,
609 clust_size = 1,
610 y_min = mcl_worlds.layer_to_y(48),
611 y_max = mcl_worlds.layer_to_y(61),
614 -- Lava may even appear above surface, but this is very rare
615 minetest.register_ore({
616 ore_type = "scatter",
617 ore = "mcl_core:lava_source",
618 wherein = stonelike,
619 clust_scarcity = 96000,
620 clust_num_ores = 1,
621 clust_size = 1,
622 y_min = mcl_worlds.layer_to_y(62),
623 y_max = mcl_worlds.layer_to_y(127),
632 local function register_mgv6_decorations()
634 -- Cacti
635 minetest.register_decoration({
636 deco_type = "simple",
637 place_on = {"group:sand"},
638 sidelen = 16,
639 noise_params = {
640 offset = -0.012,
641 scale = 0.024,
642 spread = {x = 100, y = 100, z = 100},
643 seed = 257,
644 octaves = 3,
645 persist = 0.6
647 y_min = 4,
648 y_max = mcl_vars.mg_overworld_max,
649 decoration = "mcl_core:cactus",
650 height = 1,
651 height_max = 3,
654 -- Sugar canes
655 minetest.register_decoration({
656 deco_type = "simple",
657 place_on = {"mcl_core:dirt", "mcl_core:coarse_dirt", "group:grass_block_no_snow", "group:sand", "mcl_core:podzol", "mcl_core:reeds"},
658 sidelen = 16,
659 noise_params = {
660 offset = -0.3,
661 scale = 0.7,
662 spread = {x = 100, y = 100, z = 100},
663 seed = 465,
664 octaves = 3,
665 persist = 0.7
667 y_min = 1,
668 y_max = mcl_vars.mg_overworld_max,
669 decoration = "mcl_core:reeds",
670 height = 1,
671 height_max = 3,
672 spawn_by = { "mcl_core:water_source", "group:frosted_ice" },
673 num_spawn_by = 1,
676 -- Doubletall grass
677 minetest.register_decoration({
678 deco_type = "schematic",
679 schematic = {
680 size = { x=1, y=3, z=1 },
681 data = {
682 { name = "air", prob = 0 },
683 { name = "mcl_flowers:double_grass", param1 = 255, },
684 { name = "mcl_flowers:double_grass_top", param1 = 255, },
687 replacements = {
688 ["mcl_flowers:tallgrass"] = "mcl_flowers:double_grass"
690 place_on = {"group:grass_block_no_snow"},
691 sidelen = 8,
692 noise_params = {
693 offset = -0.0025,
694 scale = 0.03,
695 spread = {x = 100, y = 100, z = 100},
696 seed = 420,
697 octaves = 3,
698 persist = 0.0,
700 y_min = 1,
701 y_max = mcl_vars.mg_overworld_max,
704 -- Large ferns
705 minetest.register_decoration({
706 deco_type = "schematic",
707 schematic = {
708 size = { x=1, y=3, z=1 },
709 data = {
710 { name = "air", prob = 0 },
711 { name = "mcl_flowers:double_fern", param1=255, },
712 { name = "mcl_flowers:double_fern_top", param1=255, },
715 replacements = {
716 ["mcl_flowers:fern"] = "mcl_flowers:double_fern"
718 -- v6 hack: This makes sure large ferns only appear in jungles
719 spawn_by = { "mcl_core:jungletree", "mcl_flowers:fern" },
720 num_spawn_by = 1,
721 place_on = {"group:grass_block_no_snow"},
723 sidelen = 16,
724 noise_params = {
725 offset = 0,
726 scale = 0.01,
727 spread = {x = 250, y = 250, z = 250},
728 seed = 333,
729 octaves = 2,
730 persist = 0.66,
732 y_min = 1,
733 y_max = mcl_vars.mg_overworld_max,
736 -- Large flowers
737 local register_large_flower = function(name, seed, offset)
738 minetest.register_decoration({
739 deco_type = "schematic",
740 schematic = {
741 size = { x=1, y=3, z=1 },
742 data = {
743 { name = "air", prob = 0 },
744 { name = "mcl_flowers:"..name, param1=255, },
745 { name = "mcl_flowers:"..name.."_top", param1=255, },
748 place_on = {"group:grass_block_no_snow"},
750 sidelen = 16,
751 noise_params = {
752 offset = offset,
753 scale = 0.01,
754 spread = {x = 300, y = 300, z = 300},
755 seed = seed,
756 octaves = 5,
757 persist = 0.62,
759 y_min = 1,
760 y_max = mcl_vars.overworld_max,
761 flags = "",
765 register_large_flower("rose_bush", 9350, -0.008)
766 register_large_flower("peony", 10450, -0.008)
767 register_large_flower("lilac", 10600, -0.007)
768 register_large_flower("sunflower", 2940, -0.005)
770 -- Lily pad
771 minetest.register_decoration({
772 deco_type = "schematic",
773 schematic = {
774 size = { x=1, y=3, z=1 },
775 data = {
776 { name = "mcl_core:water_source", prob = 0 },
777 { name = "mcl_core:water_source" },
778 { name = "mcl_flowers:waterlily", param1 = 255 },
781 place_on = "mcl_core:dirt",
782 sidelen = 16,
783 noise_params = {
784 offset = -0.12,
785 scale = 0.3,
786 spread = {x = 200, y = 200, z = 200},
787 seed = 503,
788 octaves = 6,
789 persist = 0.7,
791 y_min = 0,
792 y_max = 0,
793 rotation = "random",
796 -- Pumpkin
797 minetest.register_decoration({
798 deco_type = "schematic",
799 schematic = {
800 size = { x=1, y=2, z=1 },
801 data = {
802 { name = "air", prob = 0 },
803 { name = "mcl_farming:pumpkin_face" },
806 place_on = {"group:grass_block_no_snow"},
807 sidelen = 16,
808 noise_params = {
809 offset = -0.008,
810 scale = 0.00666,
811 spread = {x = 250, y = 250, z = 250},
812 seed = 666,
813 octaves = 6,
814 persist = 0.666
816 y_min = 1,
817 y_max = mcl_vars.overworld_max,
818 rotation = "random",
821 -- Tall grass
822 minetest.register_decoration({
823 deco_type = "simple",
824 place_on = {"group:grass_block_no_snow"},
825 sidelen = 8,
826 noise_params = {
827 offset = 0.01,
828 scale = 0.3,
829 spread = {x = 100, y = 100, z = 100},
830 seed = 420,
831 octaves = 3,
832 persist = 0.6
834 y_min = 1,
835 y_max = mcl_vars.overworld_max,
836 decoration = "mcl_flowers:tallgrass",
838 minetest.register_decoration({
839 deco_type = "simple",
840 place_on = {"group:grass_block_no_snow"},
841 sidelen = 8,
842 noise_params = {
843 offset = 0.04,
844 scale = 0.03,
845 spread = {x = 100, y = 100, z = 100},
846 seed = 420,
847 octaves = 3,
848 persist = 0.6
850 y_min = 1,
851 y_max = mcl_vars.overworld_max,
852 decoration = "mcl_flowers:tallgrass",
854 -- Add a small amount of tall grass everywhere to avoid areas completely empty devoid of tall grass
855 minetest.register_decoration({
856 deco_type = "simple",
857 place_on = {"group:grass_block_no_snow"},
858 sidelen = 8,
859 fill_ratio = 0.004,
860 y_min = 1,
861 y_max = mcl_vars.overworld_max,
862 decoration = "mcl_flowers:tallgrass",
865 local mushrooms = {"mcl_mushrooms:mushroom_red", "mcl_mushrooms:mushroom_brown"}
866 local mseeds = { 7133, 8244 }
867 for m=1, #mushrooms do
868 -- Mushrooms next to trees
869 minetest.register_decoration({
870 deco_type = "simple",
871 place_on = {"group:grass_block_no_snow", "mcl_core:dirt", "mcl_core:podzol", "mcl_core:mycelium", "mcl_core:stone", "mcl_core:andesite", "mcl_core:diorite", "mcl_core:granite"},
872 sidelen = 16,
873 noise_params = {
874 offset = 0.04,
875 scale = 0.04,
876 spread = {x = 100, y = 100, z = 100},
877 seed = mseeds[m],
878 octaves = 3,
879 persist = 0.6
881 y_min = 1,
882 y_max = mcl_vars.mg_overworld_max,
883 decoration = mushrooms[m],
884 spawn_by = { "mcl_core:tree", "mcl_core:sprucetree", "mcl_core:darktree", "mcl_core:birchtree", },
885 num_spawn_by = 1,
889 -- Dead bushes
890 minetest.register_decoration({
891 deco_type = "simple",
892 place_on = {"group:sand", "mcl_core:podzol", "mcl_core:dirt", "mcl_core:coarse_dirt", "group:hardened_clay"},
893 sidelen = 16,
894 noise_params = {
895 offset = 0,
896 scale = 0.035,
897 spread = {x = 100, y = 100, z = 100},
898 seed = 1972,
899 octaves = 3,
900 persist = 0.6
902 y_min = 4,
903 y_max = mcl_vars.mg_overworld_max,
904 decoration = "mcl_core:deadbush",
907 local function register_mgv6_flower(name, seed, offset, y_max)
908 if offset == nil then
909 offset = 0
911 if y_max == nil then
912 y_max = mcl_vars.mg_overworld_max
914 minetest.register_decoration({
915 deco_type = "simple",
916 place_on = {"group:grass_block_no_snow"},
917 sidelen = 16,
918 noise_params = {
919 offset = offset,
920 scale = 0.006,
921 spread = {x = 100, y = 100, z = 100},
922 seed = seed,
923 octaves = 3,
924 persist = 0.6
926 y_min = 1,
927 y_max = y_max,
928 decoration = "mcl_flowers:"..name,
932 register_mgv6_flower("tulip_red", 436)
933 register_mgv6_flower("tulip_orange", 536)
934 register_mgv6_flower("tulip_pink", 636)
935 register_mgv6_flower("tulip_white", 736)
936 register_mgv6_flower("azure_bluet", 800)
937 register_mgv6_flower("dandelion", 8)
938 -- Allium is supposed to only appear in flower forest in MC. There are no flower forests in v6.
939 -- We compensate by making it slightly rarer in v6.
940 register_mgv6_flower("allium", 0, -0.001)
941 --[[ Blue orchid is supposed to appear in swamplands. There are no swamplands in v6.
942 We emulate swamplands by limiting the height to 5 levels above sea level,
943 which should be close to the water. ]]
944 register_mgv6_flower("blue_orchid", 64500, nil, mcl_worlds.layer_to_y(67))
945 register_mgv6_flower("oxeye_daisy", 3490)
946 register_mgv6_flower("poppy", 9439)
950 -- Apply mapgen-specific mapgen code
951 if mg_name == "v6" then
952 register_mgv6_decorations()
953 minetest.set_mapgen_setting("mg_flags", "caves,nodungeons,decorations,light", true)
954 elseif mg_name == "flat" then
955 local classic = minetest.get_mapgen_setting("mcl_superflat_classic")
956 if classic == nil then
957 classic = minetest.settings:get_bool("mcl_superflat_classic")
958 minetest.set_mapgen_setting("mcl_superflat_classic", "true", true)
960 if classic ~= "false" then
961 -- Enforce superflat-like mapgen: No hills, lakes or caves
962 minetest.set_mapgen_setting("mg_flags", "nocaves,nodungeons,nodecorations,light", true)
963 minetest.set_mapgen_setting("mgflat_spflags", "nolakes,nohills", true)
964 else
965 -- If superflat mode is disabled, mapgen is way more liberal
966 minetest.set_mapgen_setting("mg_flags", "caves,nodungeons,nodecorations,light", true)
968 else
969 minetest.set_mapgen_setting("mg_flags", "caves,nodungeons,decorations,light", true)
972 -- Helper function for converting a MC probability to MT, with
973 -- regards to MapBlocks.
974 -- Some MC generated structures are generated on per-chunk
975 -- probability.
976 -- The MC probability is 1/x per Minecraft chunk (16×16).
978 -- x: The MC probability is 1/x.
979 -- minp, maxp: MapBlock limits
980 -- returns: Probability (1/return_value) for a single MT mapblock
981 local function minecraft_chunk_probability(x, minp, maxp)
982 -- 256 is the MC chunk height
983 return x * (((maxp.x-minp.x+1)*(maxp.z-minp.z+1)) / 256)
986 -- Takes an index of a biomemap table (from minetest.get_mapgen_object),
987 -- minp and maxp (from an on_generated callback) and returns the real world coordinates
988 -- as X, Z.
989 -- Inverse function of xz_to_biomemap
990 local biomemap_to_xz = function(index, minp, maxp)
991 local xwidth = maxp.x - minp.x + 1
992 local zwidth = maxp.z - minp.z + 1
993 local x = ((index-1) % xwidth) + minp.x
994 local z = ((index-1) / zwidth) + minp.z
995 return x, z
998 -- Takes x and z coordinates and minp and maxp of a generated chunk
999 -- (in on_generated callback) and returns a biomemap index)
1000 -- Inverse function of biomemap_to_xz
1001 local xz_to_biomemap_index = function(x, z, minp, maxp)
1002 local xwidth = maxp.x - minp.x + 1
1003 local zwidth = maxp.z - minp.z + 1
1004 local minix = x % xwidth
1005 local miniz = z % zwidth
1007 return (minix + miniz * zwidth) + 1
1010 -- Perlin noise objects
1011 local perlin_structures
1012 local perlin_vines, perlin_vines_fine, perlin_vines_upwards, perlin_vines_length, perlin_vines_density
1013 local perlin_clay
1015 local function generate_clay(minp, maxp, seed, voxelmanip_data, voxelmanip_area, lvm_used)
1016 -- TODO: Make clay generation reproducible for same seed.
1017 if maxp.y < -5 or minp.y > 0 then
1018 return lvm_used
1021 perlin_clay = perlin_clay or minetest.get_perlin({
1022 offset = 0.5,
1023 scale = 0.2,
1024 spread = {x = 5, y = 5, z = 5},
1025 seed = -316,
1026 octaves = 1,
1027 persist = 0.0
1030 for y=math.max(minp.y, 0), math.min(maxp.y, -8), -1 do
1031 -- Assume X and Z lengths are equal
1032 local divlen = 4
1033 local divs = (maxp.x-minp.x)/divlen+1;
1034 for divx=0+1,divs-2 do
1035 for divz=0+1,divs-2 do
1036 -- Get position and shift it a bit randomly so the clay do not obviously appear in a grid
1037 local cx = minp.x + math.floor((divx+0.5)*divlen) + math.random(-1,1)
1038 local cz = minp.z + math.floor((divz+0.5)*divlen) + math.random(-1,1)
1040 local water_pos = voxelmanip_area:index(cx, y+1, cz)
1041 local waternode = voxelmanip_data[water_pos]
1042 local surface_pos = voxelmanip_area:index(cx, y, cz)
1043 local surfacenode = voxelmanip_data[surface_pos]
1045 local genrnd = math.random(1, 20)
1046 if genrnd == 1 and perlin_clay:get3d({x=cx,y=y,z=cz}) > 0 and waternode == c_water and
1047 (surfacenode == c_dirt or minetest.get_item_group(minetest.get_name_from_content_id(surfacenode), "sand") == 1) then
1048 local diamondsize = math.random(1, 3)
1049 for x1 = -diamondsize, diamondsize do
1050 for z1 = -(diamondsize - math.abs(x1)), diamondsize - math.abs(x1) do
1051 local ccpos = voxelmanip_area:index(cx+x1, y, cz+z1)
1052 local claycandidate = voxelmanip_data[ccpos]
1053 if voxelmanip_data[ccpos] == c_dirt or minetest.get_item_group(minetest.get_name_from_content_id(claycandidate), "sand") == 1 then
1054 voxelmanip_data[ccpos] = c_clay
1055 lvm_used = true
1063 return lvm_used
1066 -- TODO: Try to use more efficient structure generating code
1067 local function generate_structures(minp, maxp, seed, biomemap)
1068 local chunk_has_desert_well = false
1069 local chunk_has_desert_temple = false
1070 local chunk_has_igloo = false
1071 local struct_min, struct_max = -3, 64
1072 if maxp.y >= struct_min and minp.y <= struct_max then
1073 -- Generate structures
1075 perlin_structures = perlin_structures or minetest.get_perlin(329, 3, 0.6, 100)
1076 -- Assume X and Z lengths are equal
1077 local divlen = 5
1078 local divs = (maxp.x-minp.x)/divlen+1;
1079 for divx=0,divs-1 do
1080 for divz=0,divs-1 do
1081 local x0 = minp.x + math.floor((divx+0)*divlen)
1082 local z0 = minp.z + math.floor((divz+0)*divlen)
1083 local x1 = minp.x + math.floor((divx+1)*divlen)
1084 local z1 = minp.z + math.floor((divz+1)*divlen)
1085 -- Determine amount from perlin noise
1086 local amount = math.floor(perlin_structures:get2d({x=x0, y=z0}) * 9)
1087 -- Find random positions based on this random
1088 local pr = PseudoRandom(seed+1)
1089 for i=0, amount do
1090 local x = pr:next(x0, x1)
1091 local z = pr:next(z0, z1)
1092 -- Find ground level
1093 local ground_y = nil
1094 for y = struct_max, struct_min, -1 do
1095 local checknode = minetest.get_node_or_nil({x=x,y=y,z=z})
1096 if checknode and minetest.registered_nodes[checknode.name].walkable then
1097 ground_y = y
1098 break
1102 if ground_y then
1103 local p = {x=x,y=ground_y+1,z=z}
1104 local nn = minetest.get_node(p).name
1105 -- Check if the node can be replaced
1106 if minetest.registered_nodes[nn] and
1107 minetest.registered_nodes[nn].buildable_to then
1108 nn = minetest.get_node({x=x,y=ground_y,z=z}).name
1109 local struct = false
1111 -- Desert temples and desert wells
1112 if nn == "mcl_core:sand" or (nn == "mcl_core:sandstone") then
1113 if not chunk_has_desert_temple and not chunk_has_desert_well and ground_y > 3 then
1114 -- Spawn desert temple
1115 -- TODO: Check surface
1116 if math.random(1,12000) == 1 then
1117 mcl_structures.call_struct(p, "desert_temple")
1118 chunk_has_desert_temple = true
1121 if not chunk_has_desert_temple and not chunk_has_desert_well and ground_y > 3 then
1122 local desert_well_prob = minecraft_chunk_probability(1000, minp, maxp)
1124 -- Spawn desert well
1125 if math.random(1, desert_well_prob) == 1 then
1126 -- Check surface
1127 local surface = minetest.find_nodes_in_area({x=p.x,y=p.y-1,z=p.z}, {x=p.x+5, y=p.y-1, z=p.z+5}, "mcl_core:sand")
1128 if #surface >= 25 then
1129 mcl_structures.call_struct(p, "desert_well")
1130 chunk_has_desert_well = true
1135 -- Igloos
1136 elseif not chunk_has_igloo and (nn == "mcl_core:snowblock" or nn == "mcl_core:snow" or (minetest.get_item_group(nn, "grass_block_snow") == 1)) then
1137 if math.random(1, 4400) == 1 then
1138 -- Check surface
1139 local floor = {x=p.x+9, y=p.y-1, z=p.z+9}
1140 local surface = minetest.find_nodes_in_area({x=p.x,y=p.y-1,z=p.z}, floor, "mcl_core:snowblock")
1141 local surface2 = minetest.find_nodes_in_area({x=p.x,y=p.y-1,z=p.z}, floor, "mcl_core:dirt_with_grass_snow")
1142 if #surface + #surface2 >= 63 then
1143 mcl_structures.call_struct(p, "igloo")
1144 chunk_has_igloo = true
1149 -- Fossil
1150 if nn == "mcl_core:sandstone" or nn == "mcl_core:sand" and not chunk_has_desert_temple and ground_y > 3 then
1151 local fossil_prob = minecraft_chunk_probability(64, minp, maxp)
1153 if math.random(1, fossil_prob) == 1 then
1154 -- Spawn fossil below desert surface between layers 40 and 49
1155 local p1 = {x=p.x, y=math.random(mcl_worlds.layer_to_y(40), mcl_worlds.layer_to_y(49)), z=p.z}
1156 -- Very rough check of the environment (we expect to have enough stonelike nodes).
1157 -- Fossils may still appear partially exposed in caves, but this is O.K.
1158 local p2 = vector.add(p1, 4)
1159 local nodes = minetest.find_nodes_in_area(p1, p2, {"mcl_core:sandstone", "mcl_core:stone", "mcl_core:diorite", "mcl_core:andesite", "mcl_core:granite", "mcl_core:stone_with_coal", "mcl_core:dirt", "mcl_core:gravel"})
1161 if #nodes >= 100 then -- >= 80%
1162 mcl_structures.call_struct(p1, "fossil")
1167 -- Witch hut
1168 if ground_y <= 0 and nn == "mcl_core:dirt" then
1169 local prob = minecraft_chunk_probability(48, minp, maxp)
1171 local swampland = minetest.get_biome_id("Swampland")
1172 local swampland_shore = minetest.get_biome_id("Swampland_shore")
1174 -- Where do witches live?
1176 local here_be_witches = false
1177 if mg_name == "v6" then
1178 -- In ye good ol' landes of v6, witches will settle at any
1179 -- shores of dirt.
1180 here_be_witches = true
1181 else
1182 -- The townsfolk told me that witches live in the swamplands!
1183 local bi = xz_to_biomemap_index(p.x, p.z, minp, maxp)
1184 if biomemap[bi] == swampland or biomemap[bi] == swampland_shore then
1185 here_be_witches = true
1189 -- We still need a bit of luck!
1190 if here_be_witches and math.random(1, prob) == 1 then
1191 local r = tostring(math.random(0, 3) * 90) -- "0", "90", "180" or 270"
1192 local p1 = {x=p.x-1, y=WITCH_HUT_HEIGHT+2, z=p.z-1}
1193 local size
1194 if r == "0" or r == "180" then
1195 size = {x=10, y=4, z=8}
1196 else
1197 size = {x=8, y=4, z=10}
1199 local p2 = vector.add(p1, size)
1201 -- This checks free space at the “body” of the hut and a bit around.
1202 -- ALL nodes must be free for the placement to succeed.
1203 local free_nodes = minetest.find_nodes_in_area(p1, p2, {"air", "mcl_core:water_source", "mcl_flowers:waterlily"})
1204 if #free_nodes >= ((size.x+1)*(size.y+1)*(size.z+1)) then
1205 local place = {x=p.x, y=WITCH_HUT_HEIGHT-1, z=p.z}
1207 -- FIXME: For some mysterious reason (black magic?) this
1208 -- function does sometimes NOT spawn the witch hut. One can only see the
1209 -- oak wood nodes in the water, but no hut. :-/
1210 mcl_structures.call_struct(place, "witch_hut", r)
1212 -- TODO: Spawn witch in or around hut when the mob sucks less.
1214 local place_tree_if_free = function(pos, prev_result)
1215 local nn = minetest.get_node(pos).name
1216 if nn == "mcl_flowers:waterlily" or nn == "mcl_core:water_source" or nn == "mcl_core:water_flowing" or nn == "air" then
1217 minetest.set_node(pos, {name="mcl_core:tree", param2=0})
1218 return prev_result
1219 else
1220 return false
1223 local offsets
1224 if r == "0" then
1225 offsets = {
1226 {x=1, y=0, z=1},
1227 {x=1, y=0, z=5},
1228 {x=6, y=0, z=1},
1229 {x=6, y=0, z=5},
1231 elseif r == "180" then
1232 offsets = {
1233 {x=2, y=0, z=1},
1234 {x=2, y=0, z=5},
1235 {x=7, y=0, z=1},
1236 {x=7, y=0, z=5},
1238 elseif r == "270" then
1239 offsets = {
1240 {x=1, y=0, z=1},
1241 {x=5, y=0, z=1},
1242 {x=1, y=0, z=6},
1243 {x=5, y=0, z=6},
1245 elseif r == "90" then
1246 offsets = {
1247 {x=1, y=0, z=2},
1248 {x=5, y=0, z=2},
1249 {x=1, y=0, z=7},
1250 {x=5, y=0, z=7},
1253 for o=1, #offsets do
1254 local ok = true
1255 for y=place.y-1, place.y-64, -1 do
1256 local tpos = vector.add(place, offsets[o])
1257 tpos.y = y
1258 ok = place_tree_if_free(tpos, ok)
1259 if not ok then
1260 break
1268 -- Ice spikes in v6
1269 -- In other mapgens, ice spikes are generated as decorations.
1270 if mg_name == "v6" and not chunk_has_igloo and nn == "mcl_core:snowblock" then
1271 local spike = math.random(1, 3000)
1272 if spike < 3 then
1273 -- Check surface
1274 local floor = {x=p.x+4, y=p.y-1, z=p.z+4}
1275 local surface = minetest.find_nodes_in_area({x=p.x+1,y=p.y-1,z=p.z+1}, floor, {"mcl_core:snowblock", "mcl_core:dirt_with_grass_snow"})
1276 -- Check for collision with spruce
1277 local spruce_collisions = minetest.find_nodes_in_area({x=p.x+1,y=p.y+2,z=p.z+1}, {x=p.x+4, y=p.y+6, z=p.z+4}, {"mcl_core:sprucetree", "mcl_core:spruceleaves"})
1279 if #surface >= 9 and #spruce_collisions == 0 then
1280 mcl_structures.call_struct(p, "ice_spike_large")
1282 elseif spike < 100 then
1283 -- Check surface
1284 local floor = {x=p.x+6, y=p.y-1, z=p.z+6}
1285 local surface = minetest.find_nodes_in_area({x=p.x+1,y=p.y-1,z=p.z+1}, floor, {"mcl_core:snowblock", "mcl_core:dirt_with_grass_snow"})
1287 -- Check for collision with spruce
1288 local spruce_collisions = minetest.find_nodes_in_area({x=p.x+1,y=p.y+1,z=p.z+1}, {x=p.x+6, y=p.y+6, z=p.z+6}, {"mcl_core:sprucetree", "mcl_core:spruceleaves"})
1290 if #surface >= 25 and #spruce_collisions == 0 then
1291 mcl_structures.call_struct(p, "ice_spike_small")
1301 -- End exit portal
1302 elseif minp.y <= END_EXIT_PORTAL_POS.y and maxp.y >= END_EXIT_PORTAL_POS.y and
1303 minp.x <= END_EXIT_PORTAL_POS.x and maxp.x >= END_EXIT_PORTAL_POS.x and
1304 minp.z <= END_EXIT_PORTAL_POS.z and maxp.z >= END_EXIT_PORTAL_POS.z then
1305 local built = false
1306 for y=maxp.y, minp.y, -1 do
1307 local p = {x=END_EXIT_PORTAL_POS.x, y=y, z=END_EXIT_PORTAL_POS.z}
1308 if minetest.get_node(p).name == "mcl_end:end_stone" then
1309 mcl_structures.call_struct(p, "end_exit_portal")
1310 built = true
1311 break
1314 if not built then
1315 mcl_structures.call_struct(END_EXIT_PORTAL_POS, "end_exit_portal")
1320 -- Buffers for LuaVoxelManip
1321 local lvm_buffer = {}
1322 local lvm_buffer_param2 = {}
1324 -- Generate tree decorations in the bounding box. This adds:
1325 -- * Cocoa at jungle trees
1326 -- * Jungle tree vines
1327 -- * Oak vines in swamplands
1328 local function generate_tree_decorations(minp, maxp, seed, data, param2_data, area, biomemap, lvm_used)
1329 if maxp.y < 0 then
1330 return lvm_used
1333 local oaktree, oakleaves, jungletree, jungleleaves = {}, {}, {}, {}
1334 local swampland = minetest.get_biome_id("Swampland")
1335 local swampland_shore = minetest.get_biome_id("Swampland_shore")
1336 local jungle = minetest.get_biome_id("Jungle")
1337 local jungle_shore = minetest.get_biome_id("Jungle_shore")
1338 local jungle_m = minetest.get_biome_id("JungleM")
1339 local jungle_m_shore = minetest.get_biome_id("JungleM_shore")
1340 local jungle_edge = minetest.get_biome_id("JungleEdge")
1341 local jungle_edge_shore = minetest.get_biome_id("JungleEdge_shore")
1342 local jungle_edge_m = minetest.get_biome_id("JungleEdgeM")
1343 local jungle_edge_m_shore = minetest.get_biome_id("JungleEdgeM_shore")
1345 -- Modifier for Jungle M biome: More vines and cocoas
1346 local dense_vegetation = false
1348 if biomemap then
1349 -- Biome map available: Check if the required biome (jungle or swampland)
1350 -- is in this mapchunk. We are only interested in trees in the correct biome.
1351 -- The nodes are added if the correct biome is *anywhere* in the mapchunk.
1352 -- TODO: Strictly generate vines in the correct biomes only.
1353 local swamp_biome_found, jungle_biome_found = false, false
1354 for b=1, #biomemap do
1355 local id = biomemap[b]
1357 if not swamp_biome_found and (id == swampland or id == swampland_shore) then
1358 oaktree = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:tree"})
1359 oakleaves = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:leaves"})
1360 swamp_biome_found = true
1362 if not jungle_biome_found and (id == jungle or id == jungle_shore or id == jungle_m or id == jungle_m_shore or id == jungle_edge or id == jungle_edge_shore or id == jungle_edge_m or id == jungle_edge_m_shore) then
1363 jungletree = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:jungletree"})
1364 jungleleaves = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:jungleleaves"})
1365 jungle_biome_found = true
1367 if not dense_vegetation and (id == jungle_m or id == jungle_m_shore) then
1368 dense_vegetation = true
1370 if swamp_biome_found and jungle_biome_found and dense_vegetation then
1371 break
1374 else
1375 -- If there is no biome map, we just count all jungle things we can find.
1376 -- Oak vines will not be generated.
1377 jungletree = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:jungletree"})
1378 jungleleaves = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:jungleleaves"})
1381 local pos, treepos, dir
1383 local cocoachance = 40
1384 if dense_vegetation then
1385 cocoachance = 32
1388 -- Pass 1: Generate cocoas at jungle trees
1389 for n = 1, #jungletree do
1391 pos = jungletree[n]
1392 treepos = table.copy(pos)
1394 if minetest.find_node_near(pos, 1, {"mcl_core:jungleleaves"}) then
1396 dir = math.random(1, cocoachance)
1398 if dir == 1 then
1399 pos.z = pos.z + 1
1400 elseif dir == 2 then
1401 pos.z = pos.z - 1
1402 elseif dir == 3 then
1403 pos.x = pos.x + 1
1404 elseif dir == 4 then
1405 pos.x = pos.x -1
1408 local p_pos = area:index(pos.x, pos.y, pos.z)
1409 local l = minetest.get_node_light(pos)
1411 if dir < 5
1412 and data[p_pos] == c_air
1413 and l ~= nil and l > 12 then
1414 local c = math.random(1, 3)
1415 if c == 1 then
1416 data[p_pos] = c_cocoa_1
1417 elseif c == 2 then
1418 data[p_pos] = c_cocoa_2
1419 else
1420 data[p_pos] = c_cocoa_3
1422 param2_data[p_pos] = minetest.dir_to_facedir(vector.subtract(treepos, pos))
1423 lvm_used = true
1429 -- Pass 2: Generate vines at jungle wood, jungle leaves in jungle and oak wood, oak leaves in swampland
1430 perlin_vines = perlin_vines or minetest.get_perlin(555, 4, 0.6, 500)
1431 perlin_vines_fine = perlin_vines_fine or minetest.get_perlin(43000, 3, 0.6, 1)
1432 perlin_vines_length = perlin_vines_length or minetest.get_perlin(435, 4, 0.6, 75)
1433 perlin_vines_upwards = perlin_vines_upwards or minetest.get_perlin(436, 3, 0.6, 10)
1434 perlin_vines_density = perlin_vines_density or minetest.get_perlin(436, 3, 0.6, 500)
1436 -- Extra long vines in Jungle M
1437 local maxvinelength = 7
1438 if dense_vegetation then
1439 maxvinelength = 14
1441 local treething
1442 for i=1, 4 do
1443 if i==1 then
1444 treething = jungletree
1445 elseif i == 2 then
1446 treething = jungleleaves
1447 elseif i == 3 then
1448 treething = oaktree
1449 elseif i == 4 then
1450 treething = oakleaves
1453 for n = 1, #treething do
1454 pos = treething[n]
1456 treepos = table.copy(pos)
1458 local dirs = {
1459 {x=1,y=0,z=0},
1460 {x=-1,y=0,z=0},
1461 {x=0,y=0,z=1},
1462 {x=0,y=0,z=-1},
1465 for d = 1, #dirs do
1466 local pos = vector.add(pos, dirs[d])
1467 local p_pos = area:index(pos.x, pos.y, pos.z)
1469 local vine_threshold = math.max(0.33333, perlin_vines_density:get2d(pos))
1470 if dense_vegetation then
1471 vine_threshold = vine_threshold * (2/3)
1474 if perlin_vines:get2d(pos) > -1.0 and perlin_vines_fine:get3d(pos) > vine_threshold and data[p_pos] == c_air then
1476 local rdir = {}
1477 rdir.x = -dirs[d].x
1478 rdir.y = dirs[d].y
1479 rdir.z = -dirs[d].z
1480 local param2 = minetest.dir_to_wallmounted(rdir)
1482 -- Determine growth direction
1483 local grow_upwards = false
1484 -- Only possible on the wood, not on the leaves
1485 if i == 1 then
1486 grow_upwards = perlin_vines_upwards:get3d(pos) > 0.8
1488 if grow_upwards then
1489 -- Grow vines up 1-4 nodes, even through jungleleaves.
1490 -- This may give climbing access all the way to the top of the tree :-)
1491 -- But this will be fairly rare.
1492 local length = math.ceil(math.abs(perlin_vines_length:get3d(pos)) * 4)
1493 for l=0, length-1 do
1494 local t_pos = area:index(treepos.x, treepos.y, treepos.z)
1496 if (data[p_pos] == c_air or data[p_pos] == c_jungleleaves or data[p_pos] == c_leaves) and mcl_core.supports_vines(minetest.get_name_from_content_id(data[t_pos])) then
1497 data[p_pos] = c_vine
1498 param2_data[p_pos] = param2
1499 lvm_used = true
1501 else
1502 break
1504 pos.y = pos.y + 1
1505 p_pos = area:index(pos.x, pos.y, pos.z)
1506 treepos.y = treepos.y + 1
1508 else
1509 -- Grow vines down, length between 1 and maxvinelength
1510 local length = math.ceil(math.abs(perlin_vines_length:get3d(pos)) * maxvinelength)
1511 for l=0, length-1 do
1512 if data[p_pos] == c_air then
1513 data[p_pos] = c_vine
1514 param2_data[p_pos] = param2
1515 lvm_used = true
1517 else
1518 break
1520 pos.y = pos.y - 1
1521 p_pos = area:index(pos.x, pos.y, pos.z)
1529 return lvm_used
1532 local pr_shroom = PseudoRandom(os.time()-24359)
1533 -- Generate mushrooms in caves manually.
1534 -- Minetest's API does not support decorations in caves yet. :-(
1535 local generate_underground_mushrooms = function(minp, maxp, seed)
1536 -- Generate rare underground mushrooms
1537 -- TODO: Make them appear in groups, use Perlin noise
1538 local min, max = mcl_vars.mg_lava_overworld_max + 4, 0
1539 if minp.y > max or maxp.y < min then
1540 return
1543 local bpos
1544 local stone = minetest.find_nodes_in_area_under_air(minp, maxp, {"mcl_core:stone", "mcl_core:dirt", "mcl_core:mycelium", "mcl_core:podzol", "mcl_core:andesite", "mcl_core:diorite", "mcl_core:granite", "mcl_core:stone_with_coal", "mcl_core:stone_with_iron", "mcl_core:stone_with_gold"})
1546 for n = 1, #stone do
1547 bpos = {x = stone[n].x, y = stone[n].y + 1, z = stone[n].z }
1549 local l = minetest.get_node_light(bpos, 0.5)
1550 if bpos.y >= min and bpos.y <= max and l ~= nil and l <= 12 and pr_shroom:next(1,1000) < 4 then
1551 if pr_shroom:next(1,2) == 1 then
1552 minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_brown"})
1553 else
1554 minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_red"})
1560 local pr_nether = PseudoRandom(os.time()+667)
1561 local nether_wart_chance
1562 if mg_name == "v6" then
1563 nether_wart_chance = 85
1564 else
1565 nether_wart_chance = 170
1567 -- Generate Nether decorations manually: Eternal fire, mushrooms, nether wart
1568 -- Minetest's API does not support decorations in caves yet. :-(
1569 local generate_nether_decorations = function(minp, maxp, seed)
1570 if minp.y > mcl_vars.mg_nether_max or maxp.y < mcl_vars.mg_nether_min then
1571 return
1574 -- TODO: Generate everything based on Perlin noise instead of PseudoRandom
1576 local bpos
1577 local rack = minetest.find_nodes_in_area_under_air(minp, maxp, {"mcl_nether:netherrack"})
1578 local magma = minetest.find_nodes_in_area_under_air(minp, maxp, {"mcl_nether:magma"})
1579 local ssand = minetest.find_nodes_in_area_under_air(minp, maxp, {"mcl_nether:soul_sand"})
1581 -- Helper function to spawn “fake” decoration
1582 local special_deco = function(nodes, spawn_func)
1583 for n = 1, #nodes do
1584 bpos = {x = nodes[n].x, y = nodes[n].y + 1, z = nodes[n].z }
1586 spawn_func(bpos)
1591 -- Eternal fire on netherrack
1592 special_deco(rack, function(bpos)
1593 -- Eternal fire on netherrack
1594 if pr_nether:next(1,100) <= 3 then
1595 minetest.set_node(bpos, {name = "mcl_fire:eternal_fire"})
1597 end)
1599 -- Eternal fire on magma cubes
1600 special_deco(magma, function(bpos)
1601 if pr_nether:next(1,150) == 1 then
1602 minetest.set_node(bpos, {name = "mcl_fire:eternal_fire"})
1604 end)
1606 -- Mushrooms on netherrack
1607 -- Note: Spawned *after* the fire because of light level checks
1608 special_deco(rack, function(bpos)
1609 local l = minetest.get_node_light(bpos, 0.5)
1610 if bpos.y > mcl_vars.mg_lava_nether_max + 6 and l ~= nil and l <= 12 and pr_nether:next(1,1000) <= 4 then
1611 -- TODO: Make mushrooms appear in groups, use Perlin noise
1612 if pr_nether:next(1,2) == 1 then
1613 minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_brown"})
1614 else
1615 minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_red"})
1618 end)
1620 -- Nether wart on soul sand
1621 -- TODO: Spawn in Nether fortresses
1622 special_deco(ssand, function(bpos)
1623 if pr_nether:next(1, nether_wart_chance) == 1 then
1624 minetest.set_node(bpos, {name = "mcl_nether:nether_wart"})
1626 end)
1630 -- Below the bedrock, generate air/void
1631 minetest.register_on_generated(function(minp, maxp, seed)
1632 local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
1633 local data = vm:get_data(lvm_buffer)
1634 local param2_data = vm:get_param2_data(lvm_buffer_param2)
1635 local area = VoxelArea:new({MinEdge=emin, MaxEdge=emax})
1636 local lvm_used = false
1637 local biomemap
1639 local ymin, ymax
1641 -- Generate basic layer-based nodes: void, bedrock, realm barrier, lava seas, etc.
1642 -- Also perform some basic node replacements.
1644 -- Helper function to set all nodes in the layers between min and max.
1645 -- content_id: Node to set
1646 -- check: optional.
1647 -- If content_id, node will be set only if it is equal to check.
1648 -- If function(pos_to_check, content_id_at_this_pos), will set node only if returns true.
1649 -- min, max: Minimum and maximum Y levels of the layers to set
1650 -- minp, maxp: minp, maxp of the on_generated
1651 -- lvm_used: Set to true if any node in this on_generated has been set before.
1653 -- returns true if any node was set and lvm_used otherwise
1654 local function set_layers(content_id, check, min, max, minp, maxp, lvm_used)
1655 if (maxp.y >= min and minp.y <= max) then
1656 for y = math.max(min, minp.y), math.min(max, maxp.y) do
1657 for x = minp.x, maxp.x do
1658 for z = minp.z, maxp.z do
1659 local p_pos = area:index(x, y, z)
1660 if check then
1661 if type(check) == "function" and check({x=x,y=y,z=z}, data[p_pos]) then
1662 data[p_pos] = content_id
1663 lvm_used = true
1664 elseif check == data[p_pos] then
1665 data[p_pos] = content_id
1666 lvm_used = true
1668 else
1669 data[p_pos] = content_id
1670 lvm_used = true
1676 return lvm_used
1679 -- The Void
1680 lvm_used = set_layers(c_void, nil, -31000, mcl_vars.mg_nether_min-1, minp, maxp, lvm_used)
1681 lvm_used = set_layers(c_void, nil, mcl_vars.mg_nether_max+1, mcl_vars.mg_end_min-1, minp, maxp, lvm_used)
1682 lvm_used = set_layers(c_void, nil, mcl_vars.mg_end_max+1, mcl_vars.mg_realm_barrier_overworld_end_min-1, minp, maxp, lvm_used)
1683 lvm_used = set_layers(c_void, nil, mcl_vars.mg_realm_barrier_overworld_end_max+1, mcl_vars.mg_overworld_min-1, minp, maxp, lvm_used)
1685 -- Realm barrier between the Overworld void and the End
1686 lvm_used = set_layers(c_realm_barrier, nil, mcl_vars.mg_realm_barrier_overworld_end_min, mcl_vars.mg_realm_barrier_overworld_end_max, minp, maxp, lvm_used)
1688 if mg_name ~= "singlenode" then
1689 -- Bedrock
1690 local bedrock_check
1691 if mcl_vars.mg_bedrock_is_rough then
1692 bedrock_check = function(pos)
1693 local y = pos.y
1694 -- Bedrock layers with increasing levels of roughness, until a perfecly flat bedrock later at the bottom layer
1695 -- This code assumes a bedrock height of 5 layers.
1697 local diff = mcl_vars.mg_bedrock_overworld_max - y -- Overworld bedrock
1698 local ndiff1 = mcl_vars.mg_bedrock_nether_bottom_max - y -- Nether bedrock, bottom
1699 local ndiff2 = mcl_vars.mg_bedrock_nether_top_max - y -- Nether bedrock, ceiling
1701 local top
1702 if diff == 0 or ndiff1 == 0 or ndiff2 == 4 then
1703 -- 50% bedrock chance
1704 top = 2
1705 elseif diff == 1 or ndiff1 == 1 or ndiff2 == 3 then
1706 -- 66.666...%
1707 top = 3
1708 elseif diff == 2 or ndiff1 == 2 or ndiff2 == 2 then
1709 -- 75%
1710 top = 4
1711 elseif diff == 3 or ndiff1 == 3 or ndiff2 == 1 then
1712 -- 90%
1713 top = 10
1714 elseif diff == 4 or ndiff1 == 4 or ndiff2 == 0 then
1715 -- 100%
1716 return true
1717 else
1718 -- Not in bedrock layer
1719 return false
1722 return math.random(1, top) <= top-1
1724 else
1725 bedrock_check = nil
1728 lvm_used = set_layers(c_bedrock, bedrock_check, mcl_vars.mg_bedrock_overworld_min, mcl_vars.mg_bedrock_overworld_max, minp, maxp, lvm_used)
1729 lvm_used = set_layers(c_bedrock, bedrock_check, mcl_vars.mg_bedrock_nether_bottom_min, mcl_vars.mg_bedrock_nether_bottom_max, minp, maxp, lvm_used)
1730 lvm_used = set_layers(c_bedrock, bedrock_check, mcl_vars.mg_bedrock_nether_top_min, mcl_vars.mg_bedrock_nether_top_max, minp, maxp, lvm_used)
1732 -- Flat Nether
1733 if mg_name == "flat" then
1734 lvm_used = set_layers(c_air, nil, mcl_vars.mg_bedrock_nether_bottom_max + 4, mcl_vars.mg_bedrock_nether_bottom_max + 52, minp, maxp, lvm_used)
1737 -- Big lava seas by replacing air below a certain height
1738 if mcl_vars.mg_lava then
1739 lvm_used = set_layers(c_lava, c_air, mcl_vars.mg_overworld_min, mcl_vars.mg_lava_overworld_max, minp, maxp, lvm_used)
1740 lvm_used = set_layers(c_nether_lava, c_air, mcl_vars.mg_nether_min, mcl_vars.mg_lava_nether_max, minp, maxp, lvm_used)
1743 -- Clay, vines, cocoas
1744 lvm_used = generate_clay(minp, maxp, seed, data, area, lvm_used)
1746 biomemap = minetest.get_mapgen_object("biomemap")
1747 lvm_used = generate_tree_decorations(minp, maxp, seed, data, param2_data, area, biomemap, lvm_used)
1749 ----- Interactive block fixing section -----
1750 ----- The section to perform basic block overrides of the core mapgen generated world. -----
1752 -- Snow and sand fixes. This code implements snow consistency
1753 -- and fixes floating sand.
1754 -- A snowy grass block must be below a top snow or snow block at all times.
1755 if minp.y <= mcl_vars.mg_overworld_max and maxp.y >= mcl_vars.mg_overworld_min then
1756 -- v6 mapgen:
1757 -- Put top snow on snowy grass blocks. The mapgen does not generate the top snow on its own.
1758 if mg_name == "v6" then
1759 local snowdirt = minetest.find_nodes_in_area_under_air(minp, maxp, "mcl_core:dirt_with_grass_snow")
1760 for n = 1, #snowdirt do
1761 -- CHECKME: What happens at chunk borders?
1762 local p_pos = area:index(snowdirt[n].x, snowdirt[n].y + 1, snowdirt[n].z)
1763 if p_pos then
1764 data[p_pos] = c_top_snow
1767 if #snowdirt > 1 then
1768 lvm_used = true
1772 -- Non-v6 mapgens:
1773 -- Clear snowy grass blocks without snow above to ensure consistency.
1774 -- Solidify floating sand to sandstone (both colors).
1775 else
1776 local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:dirt_with_grass_snow", "mcl_core:sand", "mcl_core:redsand"})
1777 for n=1, #nodes do
1778 local p_pos = area:index(nodes[n].x, nodes[n].y, nodes[n].z)
1779 local p_pos_above = area:index(nodes[n].x, nodes[n].y+1, nodes[n].z)
1780 local p_pos_below = area:index(nodes[n].x, nodes[n].y-1, nodes[n].z)
1781 if data[p_pos] == c_dirt_with_grass_snow and p_pos_above and data[p_pos_above] ~= c_top_snow and data[p_pos_above] ~= c_snow_block then
1782 data[p_pos] = c_dirt_with_grass
1783 lvm_used = true
1784 elseif p_pos_below and data[p_pos_below] == c_air or data[p_pos_below] == c_water then
1785 if data[p_pos] == c_sand then
1786 data[p_pos] = c_sandstone
1787 lvm_used = true
1788 elseif data[p_pos] == c_redsand then
1789 -- Note: This is the only place in which red sandstone is generatd
1790 data[p_pos] = c_redsandstone
1791 lvm_used = true
1797 -- Nether block fixes:
1798 -- * Replace water with Nether lava.
1799 -- * Replace stone, sand dirt in v6 so the Nether works in v6.
1800 elseif minp.y <= mcl_vars.mg_nether_max and maxp.y >= mcl_vars.mg_nether_min then
1801 local nodes
1802 if mg_name == "v6" then
1803 nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"})
1804 else
1805 nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source"})
1807 for n=1, #nodes do
1808 local p_pos = area:index(nodes[n].x, nodes[n].y, nodes[n].z)
1809 if data[p_pos] == c_water then
1810 data[p_pos] = c_nether_lava
1811 lvm_used = true
1812 elseif data[p_pos] == c_stone then
1813 data[p_pos] = c_netherrack
1814 lvm_used = true
1815 elseif data[p_pos] == c_sand or data[p_pos] == c_dirt then
1816 data[p_pos] = c_soul_sand
1817 lvm_used = true
1821 -- End block fixes:
1822 -- * Replace water with end stone or air (depending on height).
1823 -- * Remove stone, sand, dirt in v6 so our End map generator works in v6.
1824 -- * Generate spawn platform (End portal destination)
1825 elseif minp.y <= mcl_vars.mg_end_max and maxp.y >= mcl_vars.mg_end_min then
1826 local nodes
1827 if mg_name == "v6" then
1828 nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"})
1829 else
1830 nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source"})
1832 for n=1, #nodes do
1833 local y = nodes[n].y
1834 local p_pos = area:index(nodes[n].x, y, nodes[n].z)
1836 if data[p_pos] == c_water then
1837 if y <= mcl_vars.mg_end_min + 104 and y >= mcl_vars.mg_end_min + 40 then
1838 data[p_pos] = c_end_stone
1839 lvm_used = true
1840 else
1841 data[p_pos] = c_air
1842 lvm_used = true
1844 elseif data[p_pos] == c_stone or data[p_pos] == c_dirt or data[p_pos] == c_sand then
1845 data[p_pos] = c_air
1846 lvm_used = true
1851 -- Obsidian spawn platform
1852 if minp.y <= mcl_vars.mg_end_platform_pos.y and maxp.y >= mcl_vars.mg_end_platform_pos.y and
1853 minp.x <= mcl_vars.mg_end_platform_pos.x and maxp.x >= mcl_vars.mg_end_platform_pos.z and
1854 minp.z <= mcl_vars.mg_end_platform_pos.z and maxp.z >= mcl_vars.mg_end_platform_pos.z then
1855 for x=math.max(minp.x, mcl_vars.mg_end_platform_pos.x-2), math.min(maxp.x, mcl_vars.mg_end_platform_pos.x+2) do
1856 for z=math.max(minp.z, mcl_vars.mg_end_platform_pos.z-2), math.min(maxp.z, mcl_vars.mg_end_platform_pos.z+2) do
1857 for y=math.max(minp.y, mcl_vars.mg_end_platform_pos.y), math.min(maxp.y, mcl_vars.mg_end_platform_pos.y+2) do
1858 local p_pos = area:index(x, y, z)
1859 if y == mcl_vars.mg_end_platform_pos.y then
1860 data[p_pos] = c_obsidian
1861 else
1862 data[p_pos] = c_air
1867 lvm_used = true
1872 -- Final hackery: Set sun light level in the End.
1873 -- -26912 is at a mapchunk border.
1874 local shadow
1875 if minp.y >= -26912 and maxp.y <= mcl_vars.mg_end_max then
1876 vm:set_lighting({day=15, night=15})
1877 lvm_used = true
1879 if minp.y >= mcl_vars.mg_end_min and maxp.y <= -26911 then
1880 shadow = false
1881 lvm_used = true
1884 -- Write stuff
1885 if lvm_used then
1886 vm:set_data(data)
1887 vm:set_param2_data(param2_data)
1888 vm:calc_lighting(nil, nil, shadow)
1889 vm:write_to_map()
1890 vm:update_liquids()
1893 if mg_name ~= "singlenode" then
1894 -- Generate special decorations
1895 generate_underground_mushrooms(minp, maxp, seed)
1896 generate_nether_decorations(minp, maxp, seed)
1897 generate_structures(minp, maxp, seed, biomemap)
1899 end)