VoxeLibre/mods/MAPGEN/mcl_mapgen_core/init.lua

1855 lines
58 KiB
Lua
Raw Normal View History

2015-06-29 20:55:56 +03:00
--
-- Aliases for map generator outputs
--
minetest.register_alias("mapgen_air", "air")
2017-02-01 01:32:56 +03:00
minetest.register_alias("mapgen_stone", "mcl_core:stone")
minetest.register_alias("mapgen_tree", "mcl_core:tree")
minetest.register_alias("mapgen_leaves", "mcl_core:leaves")
minetest.register_alias("mapgen_jungletree", "mcl_core:jungletree")
minetest.register_alias("mapgen_jungleleaves", "mcl_core:jungleleaves")
minetest.register_alias("mapgen_pine_tree", "mcl_core:sprucetree")
minetest.register_alias("mapgen_pine_needles", "mcl_core:spruceleaves")
2017-02-01 01:32:56 +03:00
minetest.register_alias("mapgen_apple", "mcl_core:leaves")
minetest.register_alias("mapgen_water_source", "mcl_core:water_source")
minetest.register_alias("mapgen_dirt", "mcl_core:dirt")
minetest.register_alias("mapgen_dirt_with_grass", "mcl_core:dirt_with_grass")
2017-04-01 07:44:02 +03:00
minetest.register_alias("mapgen_dirt_with_snow", "mcl_core:dirt_with_grass_snow")
2017-02-01 01:32:56 +03:00
minetest.register_alias("mapgen_sand", "mcl_core:sand")
minetest.register_alias("mapgen_gravel", "mcl_core:gravel")
minetest.register_alias("mapgen_clay", "mcl_core:clay")
minetest.register_alias("mapgen_lava_source", "air") -- Built-in lava generator is too unpredictable, we generate lava on our own
2017-02-01 01:32:56 +03:00
minetest.register_alias("mapgen_cobble", "mcl_core:cobble")
minetest.register_alias("mapgen_mossycobble", "mcl_core:mossycobble")
minetest.register_alias("mapgen_junglegrass", "mcl_flowers:fern")
2017-02-01 01:32:56 +03:00
minetest.register_alias("mapgen_stone_with_coal", "mcl_core:stone_with_coal")
minetest.register_alias("mapgen_stone_with_iron", "mcl_core:stone_with_iron")
minetest.register_alias("mapgen_desert_sand", "mcl_core:sand")
minetest.register_alias("mapgen_desert_stone", "mcl_core:sandstone")
minetest.register_alias("mapgen_sandstone", "mcl_core:sandstone")
minetest.register_alias("mapgen_river_water_source", "mcl_core:water_source")
minetest.register_alias("mapgen_snow", "mcl_core:snow")
minetest.register_alias("mapgen_snowblock", "mcl_core:snowblock")
minetest.register_alias("mapgen_ice", "mcl_core:ice")
2017-01-27 16:04:30 +03:00
2017-06-05 19:40:56 +03:00
minetest.register_alias("mapgen_stair_cobble", "mcl_stairs:stair_cobble")
2017-02-01 01:32:56 +03:00
minetest.register_alias("mapgen_sandstonebrick", "mcl_core:sandstonesmooth")
2017-06-05 19:40:56 +03:00
minetest.register_alias("mapgen_stair_sandstonebrick", "mcl_stairs:stair_sandstone")
minetest.register_alias("mapgen_stair_sandstone_block", "mcl_stairs:stair_sandstone")
minetest.register_alias("mapgen_stair_desert_stone", "mcl_stairs:stair_sandstone")
2017-01-27 16:04:30 +03:00
local mg_name = minetest.get_mapgen_setting("mg_name")
2017-09-10 21:16:13 +03:00
local WITCH_HUT_HEIGHT = 3 -- Exact Y level to spawn witch huts at. This height refers to the height of the floor
2017-09-11 05:24:03 +03:00
-- Content IDs
local c_bedrock = minetest.get_content_id("mcl_core:bedrock")
local c_stone = minetest.get_content_id("mcl_core:stone")
local c_dirt = minetest.get_content_id("mcl_core:dirt")
local c_dirt_with_grass = minetest.get_content_id("mcl_core:dirt_with_grass")
local c_dirt_with_grass_snow = minetest.get_content_id("mcl_core:dirt_with_grass_snow")
local c_sand = minetest.get_content_id("mcl_core:sand")
local c_sandstone = minetest.get_content_id("mcl_core:sandstone")
local c_redsand = minetest.get_content_id("mcl_core:redsand")
local c_redsandstone = minetest.get_content_id("mcl_core:redsandstone")
local c_void = minetest.get_content_id("mcl_core:void")
local c_lava = minetest.get_content_id("mcl_core:lava_source")
local c_water = minetest.get_content_id("mcl_core:water_source")
local c_soul_sand = minetest.get_content_id("mcl_nether:soul_sand")
local c_netherrack = minetest.get_content_id("mcl_nether:netherrack")
local c_nether_lava = minetest.get_content_id("mcl_nether:nether_lava_source")
local c_end_stone = minetest.get_content_id("mcl_end:end_stone")
local c_realm_barrier = minetest.get_content_id("mcl_core:realm_barrier")
local c_top_snow = minetest.get_content_id("mcl_core:snow")
local c_snow_block = minetest.get_content_id("mcl_core:snowblock")
local c_clay = minetest.get_content_id("mcl_core:clay")
local c_leaves = minetest.get_content_id("mcl_core:leaves")
local c_jungleleaves = minetest.get_content_id("mcl_core:jungleleaves")
local c_jungletree = minetest.get_content_id("mcl_core:jungletree")
local c_cocoa_1 = minetest.get_content_id("mcl_cocoas:cocoa_1")
local c_cocoa_2 = minetest.get_content_id("mcl_cocoas:cocoa_2")
local c_cocoa_3 = minetest.get_content_id("mcl_cocoas:cocoa_3")
local c_vine = minetest.get_content_id("mcl_core:vine")
2017-09-11 05:24:03 +03:00
local c_air = minetest.CONTENT_AIR
2015-06-29 20:55:56 +03:00
--
-- Ore generation
--
-- Diorite, andesite and granite
local specialstones = { "mcl_core:diorite", "mcl_core:andesite", "mcl_core:granite" }
for s=1, #specialstones do
local node = specialstones[s]
minetest.register_ore({
ore_type = "blob",
ore = node,
wherein = {"mcl_core:stone"},
clust_scarcity = 15*15*15,
clust_num_ores = 33,
clust_size = 5,
y_min = mcl_vars.mg_overworld_min,
y_max = mcl_vars.mg_overworld_max,
})
minetest.register_ore({
ore_type = "blob",
ore = node,
wherein = {"mcl_core:stone"},
clust_scarcity = 10*10*10,
clust_num_ores = 58,
clust_size = 7,
y_min = mcl_vars.mg_overworld_min,
y_max = mcl_vars.mg_overworld_max,
})
end
local stonelike = {"mcl_core:stone", "mcl_core:diorite", "mcl_core:andesite", "mcl_core:granite"}
2017-05-19 20:56:37 +03:00
-- Dirt
minetest.register_ore({
ore_type = "blob",
ore = "mcl_core:dirt",
wherein = stonelike,
2017-05-19 20:56:37 +03:00
clust_scarcity = 15*15*15,
clust_num_ores = 33,
clust_size = 4,
y_min = mcl_vars.mg_overworld_min,
y_max = mcl_vars.mg_overworld_max,
})
-- Gravel
minetest.register_ore({
ore_type = "blob",
ore = "mcl_core:gravel",
wherein = stonelike,
2017-05-19 20:56:37 +03:00
clust_scarcity = 14*14*14,
clust_num_ores = 33,
clust_size = 5,
y_min = mcl_vars.mg_overworld_min,
y_max = mcl_util.layer_to_y(111),
})
2015-06-29 20:55:56 +03:00
--
-- Coal
--
-- Common spawn
2017-01-05 04:05:22 +03:00
minetest.register_ore({
ore_type = "scatter",
2017-02-01 01:32:56 +03:00
ore = "mcl_core:stone_with_coal",
wherein = stonelike,
clust_scarcity = 525*3,
2017-01-05 04:05:22 +03:00
clust_num_ores = 5,
clust_size = 3,
y_min = mcl_vars.mg_overworld_min,
y_max = mcl_util.layer_to_y(50),
2017-01-05 04:05:22 +03:00
})
2015-06-29 20:55:56 +03:00
minetest.register_ore({
ore_type = "scatter",
2017-02-01 01:32:56 +03:00
ore = "mcl_core:stone_with_coal",
wherein = stonelike,
clust_scarcity = 510*3,
2015-06-29 20:55:56 +03:00
clust_num_ores = 8,
clust_size = 3,
y_min = mcl_vars.mg_overworld_min,
y_max = mcl_util.layer_to_y(50),
2015-06-29 20:55:56 +03:00
})
minetest.register_ore({
ore_type = "scatter",
2017-02-01 01:32:56 +03:00
ore = "mcl_core:stone_with_coal",
wherein = stonelike,
clust_scarcity = 500*3,
clust_num_ores = 12,
2015-06-29 20:55:56 +03:00
clust_size = 3,
y_min = mcl_vars.mg_overworld_min,
y_max = mcl_util.layer_to_y(50),
})
-- Medium-rare spawn
minetest.register_ore({
ore_type = "scatter",
ore = "mcl_core:stone_with_coal",
wherein = stonelike,
clust_scarcity = 550*3,
clust_num_ores = 4,
clust_size = 2,
y_min = mcl_util.layer_to_y(51),
y_max = mcl_util.layer_to_y(80),
})
minetest.register_ore({
ore_type = "scatter",
ore = "mcl_core:stone_with_coal",
wherein = stonelike,
clust_scarcity = 525*3,
clust_num_ores = 6,
clust_size = 3,
y_min = mcl_util.layer_to_y(51),
y_max = mcl_util.layer_to_y(80),
})
minetest.register_ore({
ore_type = "scatter",
ore = "mcl_core:stone_with_coal",
wherein = stonelike,
clust_scarcity = 500*3,
clust_num_ores = 8,
clust_size = 3,
y_min = mcl_util.layer_to_y(51),
y_max = mcl_util.layer_to_y(80),
})
-- Rare spawn
minetest.register_ore({
ore_type = "scatter",
ore = "mcl_core:stone_with_coal",
wherein = stonelike,
clust_scarcity = 600*3,
clust_num_ores = 3,
clust_size = 2,
y_min = mcl_util.layer_to_y(81),
y_max = mcl_util.layer_to_y(128),
})
minetest.register_ore({
ore_type = "scatter",
ore = "mcl_core:stone_with_coal",
wherein = stonelike,
clust_scarcity = 550*3,
clust_num_ores = 4,
clust_size = 3,
y_min = mcl_util.layer_to_y(81),
y_max = mcl_util.layer_to_y(128),
})
2015-06-29 20:55:56 +03:00
minetest.register_ore({
ore_type = "scatter",
2017-02-01 01:32:56 +03:00
ore = "mcl_core:stone_with_coal",
wherein = stonelike,
clust_scarcity = 500*3,
clust_num_ores = 5,
clust_size = 3,
y_min = mcl_util.layer_to_y(81),
y_max = mcl_util.layer_to_y(128),
2015-06-29 20:55:56 +03:00
})
--
-- Iron
--
minetest.register_ore({
ore_type = "scatter",
2017-02-01 01:32:56 +03:00
ore = "mcl_core:stone_with_iron",
wherein = stonelike,
2015-06-29 20:55:56 +03:00
clust_scarcity = 830,
clust_num_ores = 5,
clust_size = 3,
y_min = mcl_vars.mg_overworld_min,
y_max = mcl_util.layer_to_y(39),
2015-06-29 20:55:56 +03:00
})
minetest.register_ore({
ore_type = "scatter",
2017-02-01 01:32:56 +03:00
ore = "mcl_core:stone_with_iron",
wherein = stonelike,
2015-06-29 20:55:56 +03:00
clust_scarcity = 1660,
clust_num_ores = 4,
2015-06-29 20:55:56 +03:00
clust_size = 2,
y_min = mcl_util.layer_to_y(40),
y_max = mcl_util.layer_to_y(63),
2015-06-29 20:55:56 +03:00
})
--
-- Gold
--
-- Common spawn
2015-06-29 20:55:56 +03:00
minetest.register_ore({
ore_type = "scatter",
2017-02-01 01:32:56 +03:00
ore = "mcl_core:stone_with_gold",
wherein = stonelike,
2017-03-04 08:49:40 +03:00
clust_scarcity = 4775,
2015-06-29 20:55:56 +03:00
clust_num_ores = 5,
clust_size = 3,
y_min = mcl_vars.mg_overworld_min,
y_max = mcl_util.layer_to_y(30),
2015-06-29 20:55:56 +03:00
})
minetest.register_ore({
ore_type = "scatter",
2017-02-01 01:32:56 +03:00
ore = "mcl_core:stone_with_gold",
wherein = stonelike,
2017-03-04 08:49:40 +03:00
clust_scarcity = 6560,
clust_num_ores = 7,
clust_size = 3,
y_min = mcl_vars.mg_overworld_min,
y_max = mcl_util.layer_to_y(30),
2015-06-29 20:55:56 +03:00
})
-- Rare spawn
minetest.register_ore({
ore_type = "scatter",
ore = "mcl_core:stone_with_gold",
wherein = stonelike,
clust_scarcity = 13000,
clust_num_ores = 4,
clust_size = 2,
y_min = mcl_util.layer_to_y(31),
y_max = mcl_util.layer_to_y(33),
})
2017-03-04 08:49:40 +03:00
2015-06-29 20:55:56 +03:00
--
-- Diamond
--
-- Common spawn
2015-06-29 20:55:56 +03:00
minetest.register_ore({
ore_type = "scatter",
2017-02-01 01:32:56 +03:00
ore = "mcl_core:stone_with_diamond",
wherein = stonelike,
2015-06-29 20:55:56 +03:00
clust_scarcity = 10000,
clust_num_ores = 4,
clust_size = 3,
y_min = mcl_vars.mg_overworld_min,
y_max = mcl_util.layer_to_y(12),
2015-06-29 20:55:56 +03:00
})
minetest.register_ore({
ore_type = "scatter",
2017-02-01 01:32:56 +03:00
ore = "mcl_core:stone_with_diamond",
wherein = stonelike,
2015-06-29 20:55:56 +03:00
clust_scarcity = 5000,
clust_num_ores = 2,
clust_size = 2,
y_min = mcl_vars.mg_overworld_min,
y_max = mcl_util.layer_to_y(12),
2015-06-29 20:55:56 +03:00
})
minetest.register_ore({
ore_type = "scatter",
2017-02-01 01:32:56 +03:00
ore = "mcl_core:stone_with_diamond",
wherein = stonelike,
2015-06-29 20:55:56 +03:00
clust_scarcity = 10000,
clust_num_ores = 8,
clust_size = 3,
y_min = mcl_vars.mg_overworld_min,
y_max = mcl_util.layer_to_y(12),
})
-- Rare spawn
minetest.register_ore({
ore_type = "scatter",
ore = "mcl_core:stone_with_diamond",
wherein = stonelike,
clust_scarcity = 20000,
clust_num_ores = 1,
clust_size = 1,
y_min = mcl_util.layer_to_y(13),
y_max = mcl_util.layer_to_y(15),
})
minetest.register_ore({
ore_type = "scatter",
ore = "mcl_core:stone_with_diamond",
wherein = stonelike,
clust_scarcity = 20000,
clust_num_ores = 2,
clust_size = 2,
y_min = mcl_util.layer_to_y(13),
y_max = mcl_util.layer_to_y(15),
2015-06-29 20:55:56 +03:00
})
--
-- Redstone
--
-- Common spawn
2015-06-29 20:55:56 +03:00
minetest.register_ore({
ore_type = "scatter",
2017-02-01 01:32:56 +03:00
ore = "mcl_core:stone_with_redstone",
wherein = stonelike,
2017-03-04 08:10:41 +03:00
clust_scarcity = 500,
clust_num_ores = 4,
2015-06-29 20:55:56 +03:00
clust_size = 3,
y_min = mcl_vars.mg_overworld_min,
y_max = mcl_util.layer_to_y(13),
})
minetest.register_ore({
ore_type = "scatter",
ore = "mcl_core:stone_with_redstone",
wherein = stonelike,
clust_scarcity = 800,
clust_num_ores = 7,
clust_size = 4,
y_min = mcl_vars.mg_overworld_min,
y_max = mcl_util.layer_to_y(13),
})
-- Rare spawn
minetest.register_ore({
ore_type = "scatter",
ore = "mcl_core:stone_with_redstone",
wherein = stonelike,
clust_scarcity = 1000,
clust_num_ores = 4,
clust_size = 3,
y_min = mcl_util.layer_to_y(13),
y_max = mcl_util.layer_to_y(15),
2015-06-29 20:55:56 +03:00
})
minetest.register_ore({
ore_type = "scatter",
2017-02-01 01:32:56 +03:00
ore = "mcl_core:stone_with_redstone",
wherein = stonelike,
clust_scarcity = 1600,
2017-03-04 08:10:41 +03:00
clust_num_ores = 7,
2015-06-29 20:55:56 +03:00
clust_size = 4,
y_min = mcl_util.layer_to_y(13),
y_max = mcl_util.layer_to_y(15),
2015-06-29 20:55:56 +03:00
})
--
-- Emerald
--
if mg_name == "v6" then
-- Generate everywhere in v6, but rarely.
-- Common spawn
minetest.register_ore({
ore_type = "scatter",
ore = "mcl_core:stone_with_emerald",
wherein = stonelike,
clust_scarcity = 14340,
clust_num_ores = 1,
clust_size = 1,
y_min = mcl_vars.mg_overworld_min,
y_max = mcl_util.layer_to_y(29),
})
-- Rare spawn
minetest.register_ore({
ore_type = "scatter",
ore = "mcl_core:stone_with_emerald",
wherein = stonelike,
clust_scarcity = 21510,
clust_num_ores = 1,
clust_size = 1,
y_min = mcl_util.layer_to_y(30),
y_max = mcl_util.layer_to_y(32),
})
else
minetest.register_ore({
ore_type = "scatter",
ore = "mcl_core:stone_with_emerald",
wherein = stonelike,
clust_scarcity = 16384,
clust_num_ores = 1,
clust_size = 1,
y_min = mcl_util.layer_to_y(4),
y_max = mcl_util.layer_to_y(32),
biomes = { "ExtremeHills", "ExtremeHills_beach", "ExtremeHills_ocean", },
})
end
2015-06-29 20:55:56 +03:00
--
-- Lapis Lazuli
--
-- Common spawn (in the center)
2015-06-29 20:55:56 +03:00
minetest.register_ore({
ore_type = "scatter",
2017-02-01 01:32:56 +03:00
ore = "mcl_core:stone_with_lapis",
wherein = stonelike,
2015-06-29 20:55:56 +03:00
clust_scarcity = 10000,
clust_num_ores = 7,
clust_size = 4,
y_min = mcl_util.layer_to_y(14),
y_max = mcl_util.layer_to_y(16),
2015-06-29 20:55:56 +03:00
})
-- Rare spawn (below center)
2015-06-29 20:55:56 +03:00
minetest.register_ore({
ore_type = "scatter",
2017-02-01 01:32:56 +03:00
ore = "mcl_core:stone_with_lapis",
wherein = stonelike,
clust_scarcity = 12000,
clust_num_ores = 6,
clust_size = 3,
y_min = mcl_util.layer_to_y(10),
y_max = mcl_util.layer_to_y(13),
})
minetest.register_ore({
ore_type = "scatter",
ore = "mcl_core:stone_with_lapis",
wherein = stonelike,
clust_scarcity = 14000,
2015-06-29 20:55:56 +03:00
clust_num_ores = 5,
clust_size = 3,
y_min = mcl_util.layer_to_y(6),
y_max = mcl_util.layer_to_y(9),
})
minetest.register_ore({
ore_type = "scatter",
ore = "mcl_core:stone_with_lapis",
wherein = stonelike,
clust_scarcity = 16000,
clust_num_ores = 4,
clust_size = 3,
y_min = mcl_util.layer_to_y(2),
y_max = mcl_util.layer_to_y(5),
})
minetest.register_ore({
ore_type = "scatter",
ore = "mcl_core:stone_with_lapis",
wherein = stonelike,
clust_scarcity = 18000,
clust_num_ores = 3,
clust_size = 2,
y_min = mcl_util.layer_to_y(0),
y_max = mcl_util.layer_to_y(2),
})
-- Rare spawn (above center)
minetest.register_ore({
ore_type = "scatter",
ore = "mcl_core:stone_with_lapis",
wherein = stonelike,
clust_scarcity = 12000,
clust_num_ores = 6,
clust_size = 3,
y_min = mcl_util.layer_to_y(17),
y_max = mcl_util.layer_to_y(20),
})
minetest.register_ore({
ore_type = "scatter",
ore = "mcl_core:stone_with_lapis",
wherein = stonelike,
clust_scarcity = 14000,
clust_num_ores = 5,
clust_size = 3,
y_min = mcl_util.layer_to_y(21),
y_max = mcl_util.layer_to_y(24),
})
minetest.register_ore({
ore_type = "scatter",
ore = "mcl_core:stone_with_lapis",
wherein = stonelike,
clust_scarcity = 16000,
clust_num_ores = 4,
clust_size = 3,
y_min = mcl_util.layer_to_y(25),
y_max = mcl_util.layer_to_y(28),
})
minetest.register_ore({
ore_type = "scatter",
ore = "mcl_core:stone_with_lapis",
wherein = stonelike,
clust_scarcity = 18000,
clust_num_ores = 3,
clust_size = 2,
y_min = mcl_util.layer_to_y(29),
y_max = mcl_util.layer_to_y(32),
})
minetest.register_ore({
ore_type = "scatter",
ore = "mcl_core:stone_with_lapis",
wherein = stonelike,
clust_scarcity = 32000,
clust_num_ores = 1,
clust_size = 1,
y_min = mcl_util.layer_to_y(31),
y_max = mcl_util.layer_to_y(32),
2015-06-29 20:55:56 +03:00
})
if mg_name ~= "flat" then
-- Water and lava springs (single blocks of lava/water source)
-- Water appears at nearly every height, but not near the bottom
minetest.register_ore({
ore_type = "scatter",
ore = "mcl_core:water_source",
wherein = {"mcl_core:stone", "mcl_core:andesite", "mcl_core:diorite", "mcl_core:granite", "mcl_core:dirt"},
clust_scarcity = 9000,
clust_num_ores = 1,
clust_size = 1,
y_min = mcl_util.layer_to_y(5),
y_max = mcl_util.layer_to_y(128),
})
-- Lava springs are rather common at -31 and below
minetest.register_ore({
ore_type = "scatter",
ore = "mcl_core:lava_source",
wherein = stonelike,
clust_scarcity = 2000,
clust_num_ores = 1,
clust_size = 1,
y_min = mcl_util.layer_to_y(1),
y_max = mcl_util.layer_to_y(10),
})
minetest.register_ore({
ore_type = "scatter",
ore = "mcl_core:lava_source",
wherein = stonelike,
clust_scarcity = 9000,
clust_num_ores = 1,
clust_size = 1,
y_min = mcl_util.layer_to_y(11),
y_max = mcl_util.layer_to_y(31),
})
-- Lava springs will become gradually rarer with increasing height
minetest.register_ore({
ore_type = "scatter",
ore = "mcl_core:lava_source",
wherein = stonelike,
clust_scarcity = 32000,
clust_num_ores = 1,
clust_size = 1,
y_min = mcl_util.layer_to_y(32),
y_max = mcl_util.layer_to_y(47),
})
minetest.register_ore({
ore_type = "scatter",
ore = "mcl_core:lava_source",
wherein = stonelike,
clust_scarcity = 72000,
clust_num_ores = 1,
clust_size = 1,
y_min = mcl_util.layer_to_y(48),
y_max = mcl_util.layer_to_y(61),
})
-- Lava may even appear above surface, but this is very rare
minetest.register_ore({
ore_type = "scatter",
ore = "mcl_core:lava_source",
wherein = stonelike,
clust_scarcity = 96000,
clust_num_ores = 1,
clust_size = 1,
y_min = mcl_util.layer_to_y(62),
y_max = mcl_util.layer_to_y(127),
})
end
-- Rarely replace stone with stone monster eggs.
-- In v6 this can happen anywhere, in other mapgens only in Extreme Hills.
local monster_egg_scarcity
2017-07-06 00:48:48 +03:00
if mg_name == "v6" then
monster_egg_scarcity = 28 * 28 * 28
else
monster_egg_scarcity = 26 * 26 * 26
2017-07-06 00:48:48 +03:00
end
minetest.register_ore({
ore_type = "scatter",
ore = "mcl_monster_eggs:monster_egg_stone",
wherein = "mcl_core:stone",
clust_scarcity = monster_egg_scarcity,
clust_num_ores = 3,
clust_size = 2,
2017-08-18 00:58:35 +03:00
y_min = mcl_vars.mg_overworld_min,
y_max = mcl_util.layer_to_y(61),
biomes = { "ExtremeHills", "ExtremeHills_beach", "ExtremeHills_ocean", },
2017-07-06 00:48:48 +03:00
})
local function register_mgv6_decorations()
-- Cacti
minetest.register_decoration({
deco_type = "simple",
place_on = {"group:sand"},
sidelen = 16,
noise_params = {
offset = -0.012,
scale = 0.024,
spread = {x = 100, y = 100, z = 100},
seed = 257,
octaves = 3,
persist = 0.6
},
y_min = 4,
y_max = mcl_vars.mg_overworld_max,
decoration = "mcl_core:cactus",
height = 1,
height_max = 3,
})
-- Sugar canes
minetest.register_decoration({
2017-08-22 16:57:19 +03:00
deco_type = "simple",
place_on = {"mcl_core:dirt", "mcl_core:coarse_dirt", "mcl_core:dirt_with_grass", "group:sand", "mcl_core:podzol", "mcl_core:reeds"},
sidelen = 16,
noise_params = {
2017-08-22 16:57:19 +03:00
offset = 0.3,
scale = 0.7,
spread = {x = 100, y = 100, z = 100},
seed = 2,
octaves = 3,
persist = 0.7
},
y_min = 1,
2017-08-22 16:57:19 +03:00
y_max = mcl_vars.mg_overworld_max,
decoration = "mcl_core:reeds",
height = 1,
height_max = 3,
spawn_by = { "mcl_core:water_source", "group:frosted_ice" },
num_spawn_by = 1,
})
-- Doubletall grass
minetest.register_decoration({
deco_type = "schematic",
schematic = {
size = { x=1, y=3, z=1 },
data = {
{ name = "air", prob = 0 },
2017-08-22 18:40:54 +03:00
{ name = "mcl_flowers:double_grass", param1 = 255, },
{ name = "mcl_flowers:double_grass_top", param1 = 255, },
},
},
replacements = {
["mcl_flowers:tallgrass"] = "mcl_flowers:double_grass"
},
place_on = {"mcl_core:dirt_with_grass"},
sidelen = 16,
noise_params = {
offset = -0.01,
scale = 0.03,
spread = {x = 300, y = 300, z = 300},
seed = 420,
octaves = 2,
persist = 0.6,
},
y_min = 1,
y_max = mcl_vars.mg_overworld_max,
})
-- Large ferns
minetest.register_decoration({
deco_type = "schematic",
schematic = {
size = { x=1, y=3, z=1 },
data = {
{ name = "air", prob = 0 },
{ name = "mcl_flowers:double_fern", param1=255, },
{ name = "mcl_flowers:double_fern_top", param1=255, },
},
},
replacements = {
["mcl_flowers:fern"] = "mcl_flowers:double_fern"
},
-- v6 hack: This makes sure large ferns only appear in jungles
spawn_by = { "mcl_core:jungletree", "mcl_flowers:fern" },
num_spawn_by = 1,
place_on = {"mcl_core:podzol"},
sidelen = 16,
noise_params = {
offset = 0,
scale = 0.01,
spread = {x = 250, y = 250, z = 250},
seed = 333,
octaves = 2,
persist = 0.66,
},
y_min = 1,
y_max = mcl_vars.mg_overworld_max,
})
2017-03-15 07:03:43 +03:00
-- Large flowers
local register_large_flower = function(name, seed, offset)
minetest.register_decoration({
deco_type = "schematic",
schematic = {
size = { x=1, y=3, z=1 },
data = {
{ name = "air", prob = 0 },
{ name = "mcl_flowers:"..name, param1=255, },
{ name = "mcl_flowers:"..name.."_top", param1=255, },
},
},
place_on = {"mcl_core:dirt_with_grass"},
sidelen = 16,
noise_params = {
offset = offset,
scale = 0.01,
spread = {x = 300, y = 300, z = 300},
seed = seed,
octaves = 5,
persist = 0.62,
},
y_min = 1,
y_max = mcl_vars.overworld_max,
2017-03-15 07:03:43 +03:00
flags = "",
})
end
register_large_flower("rose_bush", 9350, -0.008)
register_large_flower("peony", 10450, -0.008)
register_large_flower("lilac", 10600, -0.007)
register_large_flower("sunflower", 2940, -0.005)
2017-03-15 05:55:08 +03:00
2017-08-22 18:40:54 +03:00
-- Lily pad
minetest.register_decoration({
deco_type = "schematic",
schematic = {
size = { x=1, y=3, z=1 },
data = {
{ name = "mcl_core:water_source", prob = 0 },
{ name = "mcl_core:water_source" },
{ name = "mcl_flowers:waterlily", param1 = 255 },
},
},
place_on = "mcl_core:dirt",
sidelen = 16,
noise_params = {
offset = -0.12,
scale = 0.3,
spread = {x = 200, y = 200, z = 200},
seed = 503,
octaves = 6,
persist = 0.7,
},
y_min = 0,
y_max = 0,
rotation = "random",
})
-- Pumpkin
minetest.register_decoration({
deco_type = "schematic",
schematic = {
size = { x=1, y=2, z=1 },
data = {
{ name = "air", prob = 0 },
2017-08-22 18:40:54 +03:00
{ name = "mcl_farming:pumpkin_face" },
},
},
place_on = {"mcl_core:dirt_with_grass"},
sidelen = 16,
noise_params = {
offset = -0.008,
scale = 0.00666,
spread = {x = 250, y = 250, z = 250},
seed = 666,
octaves = 6,
persist = 0.666
},
2017-09-10 07:06:02 +03:00
y_min = 1,
y_max = mcl_vars.overworld_max,
rotation = "random",
})
-- Tall grass
minetest.register_decoration({
deco_type = "simple",
place_on = {"mcl_core:dirt_with_grass"},
sidelen = 8,
noise_params = {
offset = 0.01,
scale = 0.3,
spread = {x = 500, y = 500, z = 500},
seed = 420,
octaves = 2,
persist = 0.6
},
y_min = 1,
y_max = mcl_vars.overworld_max,
decoration = "mcl_flowers:tallgrass",
})
-- Add a small amount of tall grass everywhere to avoid areas completely empty devoid of tall grass
minetest.register_decoration({
deco_type = "simple",
place_on = {"mcl_core:dirt_with_grass"},
sidelen = 8,
fill_ratio = 0.001,
y_min = 1,
y_max = mcl_vars.overworld_max,
decoration = "mcl_flowers:tallgrass",
})
local mushrooms = {"mcl_mushrooms:mushroom_red", "mcl_mushrooms:mushroom_brown"}
local mseeds = { 7133, 8244 }
for m=1, #mushrooms do
-- Mushrooms next to trees
minetest.register_decoration({
deco_type = "simple",
place_on = {"mcl_core:dirt_with_grass", "mcl_core:dirt", "mcl_core:podzol", "mcl_core:mycelium", "mcl_core:stone", "mcl_core:andesite", "mcl_core:diorite", "mcl_core:granite"},
sidelen = 16,
noise_params = {
2017-08-21 05:50:45 +03:00
offset = 0.04,
scale = 0.04,
spread = {x = 100, y = 100, z = 100},
seed = mseeds[m],
octaves = 3,
persist = 0.6
},
y_min = 1,
y_max = mcl_vars.mg_overworld_max,
decoration = mushrooms[m],
spawn_by = { "mcl_core:tree", "mcl_core:sprucetree", "mcl_core:darktree", "mcl_core:birchtree", },
num_spawn_by = 1,
})
end
-- Dead bushes
minetest.register_decoration({
deco_type = "simple",
place_on = {"group:sand", "mcl_core:podzol", "mcl_core:dirt", "mcl_core:coarse_dirt", "group:hardened_clay"},
sidelen = 16,
noise_params = {
offset = 0,
scale = 0.035,
spread = {x = 100, y = 100, z = 100},
seed = 1972,
octaves = 3,
persist = 0.6
},
y_min = 4,
y_max = mcl_vars.mg_overworld_max,
decoration = "mcl_core:deadbush",
})
2015-06-29 20:55:56 +03:00
local function register_mgv6_flower(name, seed, offset, y_max)
if offset == nil then
offset = 0
end
if y_max == nil then
y_max = mcl_vars.mg_overworld_max
end
minetest.register_decoration({
deco_type = "simple",
place_on = {"mcl_core:dirt_with_grass"},
sidelen = 16,
noise_params = {
offset = offset,
scale = 0.006,
spread = {x = 100, y = 100, z = 100},
seed = seed,
octaves = 3,
persist = 0.6
},
y_min = 1,
y_max = y_max,
decoration = "mcl_flowers:"..name,
})
end
register_mgv6_flower("tulip_red", 436)
register_mgv6_flower("tulip_orange", 536)
register_mgv6_flower("tulip_pink", 636)
register_mgv6_flower("tulip_white", 736)
register_mgv6_flower("azure_bluet", 800)
register_mgv6_flower("dandelion", 8)
-- Allium is supposed to only appear in flower forest in MC. There are no flower forests in v6.
-- We compensate by making it slightly rarer in v6.
register_mgv6_flower("allium", 0, -0.001)
--[[ Blue orchid is supposed to appear in swamplands. There are no swamplands in v6.
We emulate swamplands by limiting the height to 5 levels above sea level,
which should be close to the water. ]]
register_mgv6_flower("blue_orchid", 64500, nil, mcl_util.layer_to_y(67))
register_mgv6_flower("oxeye_daisy", 3490)
register_mgv6_flower("poppy", 9439)
2015-06-29 20:55:56 +03:00
end
-- Apply mapgen-specific mapgen code
if mg_name == "v6" then
register_mgv6_decorations()
2017-09-05 23:55:36 +03:00
minetest.set_mapgen_setting("mg_flags", "caves,nodungeons,decorations,light", true)
2017-08-18 22:29:25 +03:00
elseif mg_name == "flat" then
local classic = minetest.get_mapgen_setting("mcl_superflat_classic")
if classic == nil then
classic = minetest.settings:get_bool("mcl_superflat_classic")
minetest.set_mapgen_setting("mcl_superflat_classic", "true", true)
end
if classic ~= "false" then
-- Enforce superflat-like mapgen: No hills, lakes or caves
minetest.set_mapgen_setting("mg_flags", "nocaves,nodungeons,nodecorations,light", true)
minetest.set_mapgen_setting("mgflat_spflags", "nolakes,nohills", true)
else
-- If superflat mode is disabled, mapgen is way more liberal
minetest.set_mapgen_setting("mg_flags", "caves,nodungeons,nodecorations,light", true)
end
else
minetest.set_mapgen_setting("mg_flags", "caves,nodungeons,decorations,light", true)
end
-- Helper function for converting a MC probability to MT, with
-- regards to MapBlocks.
-- Some MC generated structures are generated on per-chunk
-- probability.
-- The MC probability is 1/x per Minecraft chunk (16×16).
-- x: The MC probability is 1/x.
-- minp, maxp: MapBlock limits
-- returns: Probability (1/return_value) for a single MT mapblock
local function minecraft_chunk_probability(x, minp, maxp)
-- 256 is the MC chunk height
return x * (((maxp.x-minp.x+1)*(maxp.z-minp.z+1)) / 256)
end
2017-09-11 01:28:52 +03:00
-- Takes an index of a biomemap table (from minetest.get_mapgen_object),
-- minp and maxp (from an on_generated callback) and returns the real world coordinates
-- as X, Z.
-- Inverse function of xz_to_biomemap
local biomemap_to_xz = function(index, minp, maxp)
local xwidth = maxp.x - minp.x + 1
local zwidth = maxp.z - minp.z + 1
local x = ((index-1) % xwidth) + minp.x
local z = ((index-1) / zwidth) + minp.z
return x, z
end
-- Takes x and z coordinates and minp and maxp of a generated chunk
-- (in on_generated callback) and returns a biomemap index)
-- Inverse function of biomemap_to_xz
local xz_to_biomemap_index = function(x, z, minp, maxp)
local xwidth = maxp.x - minp.x + 1
local zwidth = maxp.z - minp.z + 1
local minix = x % xwidth
local miniz = z % zwidth
return (minix + miniz * zwidth) + 1
end
-- Perlin noise objects
2017-05-27 04:19:19 +03:00
local perlin_structures
2017-05-27 04:50:35 +03:00
local perlin_vines, perlin_vines_fine, perlin_vines_upwards, perlin_vines_length, perlin_vines_density
local perlin_clay
2017-09-11 05:24:03 +03:00
local function generate_clay(minp, maxp, seed, voxelmanip_data, voxelmanip_area, lvm_used)
-- TODO: Make clay generation reproducible for same seed.
if maxp.y < -5 or minp.y > 0 then
return lvm_used
end
perlin_clay = perlin_clay or minetest.get_perlin({
offset = 0.5,
scale = 0.2,
spread = {x = 5, y = 5, z = 5},
seed = -316,
octaves = 1,
persist = 0.0
})
for y=math.max(minp.y, 0), math.min(maxp.y, -8), -1 do
2015-06-29 20:55:56 +03:00
-- Assume X and Z lengths are equal
local divlen = 4
local divs = (maxp.x-minp.x)/divlen+1;
for divx=0+1,divs-2 do
for divz=0+1,divs-2 do
-- Get position and shift it a bit randomly so the clay do not obviously appear in a grid
local cx = minp.x + math.floor((divx+0.5)*divlen) + math.random(-1,1)
local cz = minp.z + math.floor((divz+0.5)*divlen) + math.random(-1,1)
2017-09-11 05:24:03 +03:00
local water_pos = voxelmanip_area:index(cx, y+1, cz)
local waternode = voxelmanip_data[water_pos]
2017-09-11 05:24:03 +03:00
local surface_pos = voxelmanip_area:index(cx, y, cz)
local surfacenode = voxelmanip_data[surface_pos]
2017-09-11 05:24:03 +03:00
local genrnd = math.random(1, 20)
2017-09-11 05:24:03 +03:00
if genrnd == 1 and perlin_clay:get3d({x=cx,y=y,z=cz}) > 0 and waternode == c_water and
(surfacenode == c_dirt or minetest.get_item_group(minetest.get_name_from_content_id(surfacenode), "sand") == 1) then
local diamondsize = math.random(1, 3)
for x1 = -diamondsize, diamondsize do
for z1 = -(diamondsize - math.abs(x1)), diamondsize - math.abs(x1) do
2017-09-11 05:24:03 +03:00
local ccpos = voxelmanip_area:index(cx+x1, y, cz+z1)
local claycandidate = voxelmanip_data[ccpos]
if ccname == c_dirt or minetest.get_item_group(minetest.get_name_from_content_id(claycandidate), "sand") == 1 then
voxelmanip_data[ccpos] = c_clay
lvm_used = true
2015-06-29 20:55:56 +03:00
end
end
end
2015-06-29 20:55:56 +03:00
end
end
end
end
2017-09-11 05:24:03 +03:00
return lvm_used
end
-- TODO: Try to use more efficient structure generating code
local function generate_structures(minp, maxp, seed, biomemap)
local chunk_has_desert_well = false
local chunk_has_desert_temple = false
local chunk_has_igloo = false
2017-09-11 02:34:37 +03:00
local struct_min, struct_max = -3, 64
2017-09-11 01:28:52 +03:00
if maxp.y >= struct_min and minp.y <= struct_max then
2017-09-08 01:38:55 +03:00
-- Generate structures
2017-05-27 04:19:19 +03:00
perlin_structures = perlin_structures or minetest.get_perlin(329, 3, 0.6, 100)
2015-06-29 20:55:56 +03:00
-- Assume X and Z lengths are equal
local divlen = 5
local divs = (maxp.x-minp.x)/divlen+1;
for divx=0,divs-1 do
for divz=0,divs-1 do
local x0 = minp.x + math.floor((divx+0)*divlen)
local z0 = minp.z + math.floor((divz+0)*divlen)
local x1 = minp.x + math.floor((divx+1)*divlen)
local z1 = minp.z + math.floor((divz+1)*divlen)
-- Determine amount from perlin noise
2017-05-27 04:19:19 +03:00
local amount = math.floor(perlin_structures:get2d({x=x0, y=z0}) * 9)
-- Find random positions based on this random
2015-06-29 20:55:56 +03:00
local pr = PseudoRandom(seed+1)
for i=0, amount do
2015-06-29 20:55:56 +03:00
local x = pr:next(x0, x1)
local z = pr:next(z0, z1)
-- Find ground level
2015-06-29 20:55:56 +03:00
local ground_y = nil
2017-09-11 01:28:52 +03:00
for y = struct_max, struct_min, -1 do
local checknode = minetest.get_node({x=x,y=y,z=z}).name
if minetest.registered_nodes[checknode].walkable then
2015-06-29 20:55:56 +03:00
ground_y = y
break
end
end
2015-06-29 20:55:56 +03:00
if ground_y then
local p = {x=x,y=ground_y+1,z=z}
local nn = minetest.get_node(p).name
2015-06-29 20:55:56 +03:00
-- Check if the node can be replaced
if minetest.registered_nodes[nn] and
minetest.registered_nodes[nn].buildable_to then
nn = minetest.get_node({x=x,y=ground_y,z=z}).name
2017-05-20 07:47:42 +03:00
local struct = false
2017-09-08 01:38:55 +03:00
2017-05-20 07:47:42 +03:00
-- Desert temples and desert wells
if nn == "mcl_core:sand" or (nn == "mcl_core:sandstone") then
2017-09-08 06:06:42 +03:00
if not chunk_has_desert_temple and not chunk_has_desert_well and ground_y > 3 then
-- Spawn desert temple
2017-05-20 07:47:42 +03:00
-- TODO: Check surface
if math.random(1,12000) == 1 then
mcl_structures.call_struct(p, "desert_temple")
chunk_has_desert_temple = true
end
end
if not chunk_has_desert_temple and not chunk_has_desert_well and ground_y > 3 then
local desert_well_prob = minecraft_chunk_probability(1000, minp, maxp)
2017-05-20 07:47:42 +03:00
-- Spawn desert well
if math.random(1, desert_well_prob) == 1 then
-- Check surface
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")
if #surface >= 25 then
mcl_structures.call_struct(p, "desert_well")
chunk_has_desert_well = true
end
end
2015-07-04 05:56:02 +03:00
end
2017-09-08 01:38:55 +03:00
-- Igloos
elseif not chunk_has_igloo and (nn == "mcl_core:snowblock" or nn == "mcl_core:snow" or nn == "mcl_core:dirt_with_grass_snow") then
2017-05-20 08:59:10 +03:00
if math.random(1, 4400) == 1 then
-- Check surface
local floor = {x=p.x+9, y=p.y-1, z=p.z+9}
local surface = minetest.find_nodes_in_area({x=p.x,y=p.y-1,z=p.z}, floor, "mcl_core:snowblock")
local surface2 = minetest.find_nodes_in_area({x=p.x,y=p.y-1,z=p.z}, floor, "mcl_core:dirt_with_grass_snow")
if #surface + #surface2 >= 63 then
2017-05-20 08:59:10 +03:00
mcl_structures.call_struct(p, "igloo")
chunk_has_igloo = true
end
end
2015-06-29 20:55:56 +03:00
end
2017-09-08 01:38:55 +03:00
2017-09-08 06:06:42 +03:00
-- Fossil
if nn == "mcl_core:sandstone" or nn == "mcl_core:sand" and not chunk_has_desert_temple and ground_y > 3 then
local fossil_prob = minecraft_chunk_probability(64, minp, maxp)
2017-09-08 06:06:42 +03:00
if math.random(1, fossil_prob) == 1 then
2017-09-08 06:49:24 +03:00
-- Spawn fossil below desert surface between layers 40 and 49
local p1 = {x=p.x, y=math.random(mcl_util.layer_to_y(40), mcl_util.layer_to_y(49)), z=p.z}
2017-09-08 06:06:42 +03:00
-- Very rough check of the environment (we expect to have enough stonelike nodes).
-- Fossils may still appear partially exposed in caves, but this is O.K.
local p2 = vector.add(p1, 4)
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"})
if #nodes >= 100 then -- >= 80%
mcl_structures.call_struct(p1, "fossil")
end
end
end
-- Witch hut
2017-09-10 22:01:06 +03:00
if ground_y <= 0 and nn == "mcl_core:dirt" then
2017-09-11 01:28:52 +03:00
local prob = minecraft_chunk_probability(48, minp, maxp)
local swampland = minetest.get_biome_id("JungleEdge")
local swampland_shore = minetest.get_biome_id("JungleEdge_ocean")
2017-09-11 01:28:52 +03:00
-- Where do witches live?
local here_be_witches = false
if mg_name == "v6" then
-- In ye good ol' landes of v6, witches will settle at any
-- shores of dirt.
here_be_witches = true
else
-- The townsfolk told me that witches live in the swamplands!
local bi = xz_to_biomemap_index(p.x, p.z, minp, maxp)
if biomemap[bi] == swampland or biomemap[bi] == swampland_shore then
here_be_witches = true
end
end
2017-09-10 21:16:13 +03:00
2017-09-11 01:28:52 +03:00
-- We still need a bit of luck!
if here_be_witches and math.random(1, prob) == 1 then
2017-09-10 21:16:13 +03:00
local r = tostring(math.random(0, 3) * 90) -- "0", "90", "180" or 270"
local p1 = {x=p.x-1, y=WITCH_HUT_HEIGHT+2, z=p.z-1}
local size
2017-09-10 21:16:13 +03:00
if r == "0" or r == "180" then
size = {x=10, y=4, z=8}
else
size = {x=8, y=4, z=10}
end
local p2 = vector.add(p1, size)
2017-09-11 01:28:52 +03:00
2017-09-10 21:16:13 +03:00
-- This checks free space at the “body” of the hut and a bit around.
-- ALL nodes must be free for the placement to succeed.
local free_nodes = minetest.find_nodes_in_area(p1, p2, {"air", "mcl_core:water_source", "mcl_flowers:waterlily"})
2017-09-10 21:16:13 +03:00
if #free_nodes >= ((size.x+1)*(size.y+1)*(size.z+1)) then
local place = {x=p.x, y=WITCH_HUT_HEIGHT-1, z=p.z}
-- FIXME: For some mysterious reason (black magic?) this
-- function does sometimes NOT spawn the witch hut. One can only see the
-- oak wood nodes in the water, but no hut. :-/
2017-09-10 21:16:13 +03:00
mcl_structures.call_struct(place, "witch_hut", r)
-- TODO: Spawn witch in or around hut when the mob sucks less.
local place_tree_if_free = function(pos, prev_result)
local nn = minetest.get_node(pos).name
if nn == "mcl_flowers:waterlily" or nn == "mcl_core:water_source" or nn == "mcl_core:water_flowing" or nn == "air" then
minetest.set_node(pos, {name="mcl_core:tree", param2=0})
return prev_result
else
return false
end
end
2017-09-10 21:16:13 +03:00
local offsets
if r == "0" then
offsets = {
{x=1, y=0, z=1},
{x=1, y=0, z=5},
{x=6, y=0, z=1},
{x=6, y=0, z=5},
}
elseif r == "180" then
offsets = {
{x=2, y=0, z=1},
{x=2, y=0, z=5},
{x=7, y=0, z=1},
{x=7, y=0, z=5},
}
elseif r == "270" then
offsets = {
{x=1, y=0, z=1},
{x=5, y=0, z=1},
{x=1, y=0, z=6},
{x=5, y=0, z=6},
}
elseif r == "90" then
offsets = {
{x=1, y=0, z=2},
{x=5, y=0, z=2},
{x=1, y=0, z=7},
{x=5, y=0, z=7},
}
end
for o=1, #offsets do
local ok = true
for y=place.y-1, place.y-64, -1 do
local tpos = vector.add(place, offsets[o])
tpos.y = y
ok = place_tree_if_free(tpos, ok)
if not ok then
break
end
end
end
end
end
end
2017-09-08 06:06:42 +03:00
-- Ice spikes in v6
-- In other mapgens, ice spikes are generated as decorations.
2017-09-08 01:38:55 +03:00
if mg_name == "v6" and not chunk_has_igloo and nn == "mcl_core:snowblock" then
local spike = math.random(1, 3000)
if spike < 3 then
-- Check surface
local floor = {x=p.x+4, y=p.y-1, z=p.z+4}
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"})
-- Check for collision with spruce
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"})
if #surface >= 9 and #spruce_collisions == 0 then
mcl_structures.call_struct(p, "ice_spike_large")
end
elseif spike < 100 then
-- Check surface
local floor = {x=p.x+6, y=p.y-1, z=p.z+6}
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"})
-- Check for collision with spruce
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"})
if #surface >= 25 and #spruce_collisions == 0 then
mcl_structures.call_struct(p, "ice_spike_small")
end
end
end
2015-06-29 20:55:56 +03:00
end
end
2015-06-29 20:55:56 +03:00
end
end
end
end
end
2015-06-29 20:55:56 +03:00
-- Buffers for LuaVoxelManip
local lvm_buffer = {}
local lvm_buffer_param2 = {}
2017-02-20 08:10:49 +03:00
-- Generate tree decorations in the bounding box. This adds:
-- * Cocoa at jungle trees
-- * Jungle tree vines
-- * Oak vines in swamplands
local function generate_tree_decorations(minp, maxp, seed, data, param2_data, area, biomemap, lvm_used)
if maxp.y < 0 then
return lvm_used
end
local oaktree, oakleaves, jungletree, jungleleaves = {}, {}, {}, {}
local swampland = minetest.get_biome_id("Swampland")
local swampland_shore = minetest.get_biome_id("Swampland_shore")
local jungle = minetest.get_biome_id("Jungle")
local jungle_shore = minetest.get_biome_id("Jungle_shore")
local jungle_m = minetest.get_biome_id("JungleM")
local jungle_m_shore = minetest.get_biome_id("JungleM_shore")
local jungle_edge = minetest.get_biome_id("JungleEdge")
local jungle_edge_shore = minetest.get_biome_id("JungleEdge_shore")
local jungle_edge_m = minetest.get_biome_id("JungleEdgeM")
local jungle_edge_m_shore = minetest.get_biome_id("JungleEdgeM_shore")
2017-09-12 06:20:03 +03:00
-- Modifier for Jungle M biome: More vines and cocoas
local dense_vegetation = false
if biomemap then
-- Biome map available: Check if the required biome (jungle or swampland)
-- is in this mapchunk. We are only interested in trees in the correct biome.
-- The nodes are added if the correct biome is *anywhere* in the mapchunk.
-- TODO: Strictly generate vines in the correct biomes only.
local swamp_biome_found, jungle_biome_found = false, false
for b=1, #biomemap do
local id = biomemap[b]
2017-09-11 01:28:52 +03:00
if not swamp_biome_found and (id == swampland or id == swampland_shore) then
oaktree = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:tree"})
oakleaves = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:leaves"})
swamp_biome_found = true
2017-09-12 06:20:03 +03:00
end
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
jungletree = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:jungletree"})
jungleleaves = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:jungleleaves"})
jungle_biome_found = true
end
2017-09-12 06:20:03 +03:00
if not dense_vegetation and (id == jungle_m or id == jungle_m_shore) then
dense_vegetation = true
end
if swamp_biome_found and jungle_biome_found and dense_vegetation then
break
end
end
else
-- If there is no biome map, we just count all jungle things we can find.
-- Oak vines will not be generated.
jungletree = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:jungletree"})
jungleleaves = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:jungleleaves"})
end
local pos, treepos, dir
local cocoachance = 40
2017-09-12 06:20:03 +03:00
if dense_vegetation then
cocoachance = 32
end
-- Pass 1: Generate cocoas at jungle trees
for n = 1, #jungletree do
pos = jungletree[n]
treepos = table.copy(pos)
if minetest.find_node_near(pos, 1, {"mcl_core:jungleleaves"}) then
2017-09-12 06:20:03 +03:00
dir = math.random(1, cocoachance)
if dir == 1 then
pos.z = pos.z + 1
elseif dir == 2 then
pos.z = pos.z - 1
elseif dir == 3 then
pos.x = pos.x + 1
elseif dir == 4 then
pos.x = pos.x -1
end
local p_pos = area:index(pos.x, pos.y, pos.z)
if dir < 5
and data[p_pos] == c_air
and minetest.get_node_light(pos) > 12 then
local c = math.random(1, 3)
if c == 1 then
data[p_pos] = c_cocoa_1
elseif c == 2 then
data[p_pos] = c_cocoa_2
else
data[p_pos] = c_cocoa_3
end
param2_data[p_pos] = minetest.dir_to_facedir(vector.subtract(treepos, pos))
lvm_used = true
end
end
end
-- Pass 2: Generate vines at jungle wood, jungle leaves in jungle and oak wood, oak leaves in swampland
perlin_vines = perlin_vines or minetest.get_perlin(555, 4, 0.6, 500)
perlin_vines_fine = perlin_vines_fine or minetest.get_perlin(43000, 3, 0.6, 1)
perlin_vines_length = perlin_vines_length or minetest.get_perlin(435, 4, 0.6, 75)
perlin_vines_upwards = perlin_vines_upwards or minetest.get_perlin(436, 3, 0.6, 10)
perlin_vines_density = perlin_vines_density or minetest.get_perlin(436, 3, 0.6, 500)
2017-09-12 06:20:03 +03:00
-- Extra long vines in Jungle M
local maxvinelength = 7
if dense_vegetation then
maxvinelength = 14
end
local treething
for i=1, 4 do
if i==1 then
treething = jungletree
elseif i == 2 then
treething = jungleleaves
elseif i == 3 then
treething = oaktree
elseif i == 4 then
treething = oakleaves
end
for n = 1, #treething do
pos = treething[n]
treepos = table.copy(pos)
local dirs = {
{x=1,y=0,z=0},
{x=-1,y=0,z=0},
{x=0,y=0,z=1},
{x=0,y=0,z=-1},
}
2017-05-27 04:19:19 +03:00
for d = 1, #dirs do
local pos = vector.add(pos, dirs[d])
local p_pos = area:index(pos.x, pos.y, pos.z)
local vine_threshold = math.max(0.33333, perlin_vines_density:get2d(pos))
if dense_vegetation then
vine_threshold = vine_threshold * (2/3)
end
if perlin_vines:get2d(pos) > -1.0 and perlin_vines_fine:get3d(pos) > vine_threshold and data[p_pos] == c_air then
local param2 = minetest.dir_to_wallmounted(vector.subtract(treepos, pos))
-- Determine growth direction
local grow_upwards = false
-- Only possible on the wood, not on the leaves
if i == 1 then
grow_upwards = perlin_vines_upwards:get3d(pos) > 0.8
end
if grow_upwards then
-- Grow vines up 1-4 nodes, even through jungleleaves.
-- This may give climbing access all the way to the top of the tree :-)
-- But this will be fairly rare.
local length = math.ceil(math.abs(perlin_vines_length:get3d(pos)) * 4)
for l=0, length-1 do
local t_pos = area:index(treepos.x, treepos.y, treepos.z)
if (data[p_pos] == c_air or data[p_pos] == c_jungeleaves or data[p_pos] == c_leaves) and mcl_core.supports_vines(minetest.get_name_from_content_id(data[t_pos])) then
data[p_pos] = c_vine
param2_data[p_pos] = param2
lvm_used = true
else
break
end
pos.y = pos.y + 1
p_pos = area:index(pos.x, pos.y, pos.z)
treepos.y = treepos.y + 1
end
else
2017-09-12 06:20:03 +03:00
-- Grow vines down, length between 1 and maxvinelength
local length = math.ceil(math.abs(perlin_vines_length:get3d(pos)) * maxvinelength)
for l=0, length-1 do
if data[p_pos] == c_air then
data[p_pos] = c_vine
param2_data[p_pos] = param2
lvm_used = true
else
break
end
pos.y = pos.y - 1
p_pos = area:index(pos.x, pos.y, pos.z)
end
end
end
end
end
end
return lvm_used
end
local pr_shroom = PseudoRandom(os.time()-24359)
-- Generate mushrooms in caves manually.
-- Minetest's API does not support decorations in caves yet. :-(
local generate_underground_mushrooms = function(minp, maxp, seed)
-- Generate rare underground mushrooms
-- TODO: Make them appear in groups, use Perlin noise
local min, max = mcl_vars.mg_lava_overworld_max + 4, 0
if minp.y > max or maxp.y < min then
return
end
local bpos
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"})
for n = 1, #stone do
bpos = {x = stone[n].x, y = stone[n].y + 1, z = stone[n].z }
if bpos.y >= min and bpos.y <= max and minetest.get_node_light(bpos, 0.5) <= 12 and pr_shroom:next(1,1000) < 4 then
if pr_shroom:next(1,2) == 1 then
minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_brown"})
else
minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_red"})
end
end
end
end
local pr_nether = PseudoRandom(os.time()+667)
-- Generate Nether decorations manually: Eternal fire, mushrooms, nether wart
-- Minetest's API does not support decorations in caves yet. :-(
local generate_nether_decorations = function(minp, maxp, seed)
if minp.y > mcl_vars.mg_nether_max or maxp.y < mcl_vars.mg_nether_min then
return
end
-- TODO: Generate everything based on Perlin noise instead of PseudoRandom
local bpos
local rack = minetest.find_nodes_in_area_under_air(minp, maxp, {"mcl_nether:netherrack"})
local magma = minetest.find_nodes_in_area_under_air(minp, maxp, {"mcl_nether:magma"})
local ssand = minetest.find_nodes_in_area_under_air(minp, maxp, {"mcl_nether:soul_sand"})
-- Helper function to spawn “fake” decoration
local special_deco = function(nodes, spawn_func)
for n = 1, #nodes do
bpos = {x = nodes[n].x, y = nodes[n].y + 1, z = nodes[n].z }
spawn_func(bpos)
end
end
2017-08-21 20:48:27 +03:00
-- Eternal fire on netherrack
special_deco(rack, function(bpos)
-- Eternal fire on netherrack
2017-08-21 20:48:27 +03:00
if pr_nether:next(1,100) <= 3 then
minetest.set_node(bpos, {name = "mcl_fire:eternal_fire"})
end
end)
-- Eternal fire on magma cubes
special_deco(magma, function(bpos)
if pr_nether:next(1,150) == 1 then
minetest.set_node(bpos, {name = "mcl_fire:eternal_fire"})
end
end)
2017-08-21 20:48:27 +03:00
-- Mushrooms on netherrack
-- Note: Spawned *after* the fire because of light level checks
special_deco(rack, function(bpos)
if bpos.y > mcl_vars.mg_lava_nether_max + 6 and minetest.get_node_light(bpos, 0.5) <= 12 and pr_nether:next(1,1000) <= 4 then
-- TODO: Make mushrooms appear in groups, use Perlin noise
if pr_nether:next(1,2) == 1 then
minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_brown"})
else
minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_red"})
end
end
end)
-- Nether wart on soul sand
-- TODO: Spawn in Nether fortresses
special_deco(ssand, function(bpos)
if pr_nether:next(1,170) == 1 then
minetest.set_node(bpos, {name = "mcl_nether:nether_wart"})
end
end)
end
-- Below the bedrock, generate air/void
minetest.register_on_generated(function(minp, maxp, seed)
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local data = vm:get_data(lvm_buffer)
local param2_data = vm:get_param2_data(lvm_buffer_param2)
local area = VoxelArea:new({MinEdge=emin, MaxEdge=emax})
local lvm_used = false
local ymin, ymax
-- Generate basic layer-based nodes: void, bedrock, realm barrier, lava seas, etc.
-- Also perform some basic node replacements.
-- Helper function to set all nodes in the layers between min and max.
-- content_id: Node to set
-- check: optional.
-- If content_id, node will be set only if it is equal to check.
-- If function(pos_to_check, content_id_at_this_pos), will set node only if returns true.
-- min, max: Minimum and maximum Y levels of the layers to set
-- minp, maxp: minp, maxp of the on_generated
-- lvm_used: Set to true if any node in this on_generated has been set before.
--
-- returns true if any node was set and lvm_used otherwise
local function set_layers(content_id, check, min, max, minp, maxp, lvm_used)
if (maxp.y >= min and minp.y <= max) then
for y = math.max(min, minp.y), math.min(max, maxp.y) do
for x = minp.x, maxp.x do
for z = minp.z, maxp.z do
local p_pos = area:index(x, y, z)
if check then
if type(check) == "function" and check({x=x,y=y,z=z}, data[p_pos]) then
data[p_pos] = content_id
lvm_used = true
elseif check == data[p_pos] then
data[p_pos] = content_id
lvm_used = true
2017-08-16 16:29:05 +03:00
end
else
data[p_pos] = content_id
lvm_used = true
end
end
end
end
end
return lvm_used
end
-- The Void
lvm_used = set_layers(c_void, nil, -31000, mcl_vars.mg_nether_min-1, minp, maxp, lvm_used)
lvm_used = set_layers(c_void, nil, mcl_vars.mg_nether_max+1, mcl_vars.mg_end_min-1, minp, maxp, lvm_used)
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)
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)
-- Realm barrier between the Overworld void and the End
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)
-- Bedrock
local bedrock_check
if mcl_vars.mg_bedrock_is_rough then
bedrock_check = function(pos)
local y = pos.y
-- Bedrock layers with increasing levels of roughness, until a perfecly flat bedrock later at the bottom layer
-- This code assumes a bedrock height of 5 layers.
local diff = mcl_vars.mg_bedrock_overworld_max - y -- Overworld bedrock
local ndiff1 = mcl_vars.mg_bedrock_nether_bottom_max - y -- Nether bedrock, bottom
local ndiff2 = mcl_vars.mg_bedrock_nether_top_max - y -- Nether bedrock, ceiling
local top
if diff == 0 or ndiff1 == 0 or ndiff2 == 4 then
-- 50% bedrock chance
top = 2
elseif diff == 1 or ndiff1 == 1 or ndiff2 == 3 then
-- 66.666...%
top = 3
elseif diff == 2 or ndiff1 == 2 or ndiff2 == 2 then
-- 75%
top = 4
elseif diff == 3 or ndiff1 == 3 or ndiff2 == 1 then
-- 90%
top = 10
elseif diff == 4 or ndiff1 == 4 or ndiff2 == 0 then
-- 100%
return true
else
-- Not in bedrock layer
return false
end
return math.random(1, top) <= top-1
end
else
bedrock_check = nil
end
lvm_used = set_layers(c_bedrock, bedrock_check, mcl_vars.mg_bedrock_overworld_min, mcl_vars.mg_bedrock_overworld_max, minp, maxp, lvm_used)
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)
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)
-- Flat Nether
if mg_name == "flat" then
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)
end
-- Big lava seas by replacing air below a certain height
if mcl_vars.mg_lava then
lvm_used = set_layers(c_lava, c_air, mcl_vars.mg_overworld_min, mcl_vars.mg_lava_overworld_max, minp, maxp, lvm_used)
lvm_used = set_layers(c_nether_lava, c_air, mcl_vars.mg_nether_min, mcl_vars.mg_lava_nether_max, minp, maxp, lvm_used)
end
-- Clay, vines, cocoas
2017-09-11 05:24:03 +03:00
lvm_used = generate_clay(minp, maxp, seed, data, area, lvm_used)
local biomemap = minetest.get_mapgen_object("biomemap")
lvm_used = generate_tree_decorations(minp, maxp, seed, data, param2_data, area, biomemap, lvm_used)
2017-09-06 08:10:11 +03:00
----- Interactive block fixing section -----
----- The section to perform basic block overrides of the core mapgen generated world. -----
-- Snow and sand fixes. This code implements snow consistency
-- and fixes floating sand.
2017-09-06 08:10:11 +03:00
-- A snowy grass block must be below a top snow or snow block at all times.
if minp.y <= mcl_vars.mg_overworld_max and maxp.y >= mcl_vars.mg_overworld_min then
-- v6 mapgen:
-- Put top snow on snowy grass blocks. The mapgen does not generate the top snow on its own.
if mg_name == "v6" then
local snowdirt = minetest.find_nodes_in_area_under_air(minp, maxp, "mcl_core:dirt_with_grass_snow")
for n = 1, #snowdirt do
-- CHECKME: What happens at chunk borders?
local p_pos = area:index(snowdirt[n].x, snowdirt[n].y + 1, snowdirt[n].z)
if p_pos then
data[p_pos] = c_top_snow
end
end
if #snowdirt > 1 then
lvm_used = true
end
2017-09-08 01:38:55 +03:00
2017-09-06 08:10:11 +03:00
-- Non-v6 mapgens:
-- Clear snowy grass blocks without snow above to ensure consistency.
-- Solidify floating sand to sandstone (both colors).
2017-09-06 08:10:11 +03:00
else
--local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:dirt_with_grass_snow"})
local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:dirt_with_grass_snow", "mcl_core:sand", "mcl_core:redsand"})
2017-09-06 08:10:11 +03:00
for n=1, #nodes do
local p_pos = area:index(nodes[n].x, nodes[n].y, nodes[n].z)
local p_pos_above = area:index(nodes[n].x, nodes[n].y+1, nodes[n].z)
local p_pos_below = area:index(nodes[n].x, nodes[n].y-1, nodes[n].z)
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
2017-09-06 08:10:11 +03:00
data[p_pos] = c_dirt_with_grass
lvm_used = true
elseif p_pos_below and data[p_pos_below] == c_air or data[p_pos_below] == c_water then
if data[p_pos] == c_sand then
data[p_pos] = c_sandstone
lvm_used = true
elseif data[p_pos] == c_redsand then
-- Note: This is the only place in which red sandstone is generatd
data[p_pos] = c_redsandstone
lvm_used = true
end
2017-09-06 08:10:11 +03:00
end
end
end
-- Nether block fixes:
-- * Replace water with Nether lava.
-- * Replace stone, sand dirt in v6 so the Nether works in v6.
elseif minp.y <= mcl_vars.mg_nether_max and maxp.y >= mcl_vars.mg_nether_min then
local nodes
if mg_name == "v6" then
nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"})
else
nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source"})
end
for n=1, #nodes do
local p_pos = area:index(nodes[n].x, nodes[n].y, nodes[n].z)
if data[p_pos] == c_water then
data[p_pos] = c_nether_lava
lvm_used = true
elseif data[p_pos] == c_stone then
data[p_pos] = c_netherrack
lvm_used = true
elseif data[p_pos] == c_sand or data[p_pos] == c_dirt then
data[p_pos] = c_soul_sand
lvm_used = true
end
end
2017-09-06 08:10:11 +03:00
-- End block fixes:
-- * Replace water with end stone or air (depending on height).
-- * Remove stone, sand, dirt in v6 so our End map generator works in v6.
elseif minp.y <= mcl_vars.mg_end_max and maxp.y >= mcl_vars.mg_end_min then
local nodes
2017-09-06 08:10:11 +03:00
if mg_name == "v6" then
nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"})
else
nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source"})
end
for n=1, #nodes do
local y = nodes[n].y
local p_pos = area:index(nodes[n].x, y, nodes[n].z)
if data[p_pos] == c_water then
if y <= mcl_vars.mg_end_min + 104 and y >= mcl_vars.mg_end_min + 40 then
data[p_pos] = c_end_stone
lvm_used = true
else
data[p_pos] = c_air
lvm_used = true
end
elseif data[p_pos] == c_stone or data[p_pos] == c_dirt or data[p_pos] == c_sand then
data[p_pos] = c_air
lvm_used = true
end
end
end
2017-09-06 08:10:11 +03:00
-- Final hackery: Set sun light level in the End.
-- -26912 is at a mapchunk border.
2017-08-22 01:22:53 +03:00
local shadow
if minp.y >= -26912 and maxp.y <= mcl_vars.mg_end_max then
vm:set_lighting({day=15, night=15})
lvm_used = true
end
if minp.y >= mcl_vars.mg_end_min and maxp.y <= -26911 then
shadow = false
2017-08-18 14:56:26 +03:00
lvm_used = true
end
2017-09-06 08:10:11 +03:00
-- Write stuff
if lvm_used then
vm:set_data(data)
vm:set_param2_data(param2_data)
2017-08-22 01:22:53 +03:00
vm:calc_lighting(nil, nil, shadow)
vm:write_to_map()
vm:update_liquids()
end
2017-09-06 08:10:11 +03:00
-- Generate special decorations
generate_underground_mushrooms(minp, maxp, seed)
generate_nether_decorations(minp, maxp, seed)
generate_structures(minp, maxp, seed, biomemap)
2017-02-20 07:56:44 +03:00
end)