local mg_name = minetest.get_mapgen_setting("mg_name")

-- Some mapgen settings
local imitate = minetest.settings:get("mcl_imitation_mode")

local generate_fallen_logs = false

-- Jungle bush type. Default (PC/Java Edition) is Jungle Wood + Oak Leaves
local jungle_bush_schematic = minetest.get_modpath("mcl_core").."/schematics/mcl_core_jungle_bush_oak_leaves.mts"
if imitate == "pocket_edition" then
	-- Simple fallen tree trunk logs (not very good yet)
	generate_fallen_logs = true
	-- Jungle bush: Jungle Wood + Jungle Leaves
	jungle_bush_schematic = minetest.get_modpath("mcl_core").."/schematics/mcl_core_jungle_bush_jungle_leaves.mts"
end

--
-- Register biomes
--

local function register_classic_superflat_biome()
	-- Classic Superflat: bedrock (not part of biome), 2 dirt, 1 grass block
	minetest.register_biome({
		name = "flat",
		node_top = "mcl_core:dirt_with_grass",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_stone = "mcl_core:dirt",
		y_min = mcl_vars.mg_overworld_min - 512,
		y_max = mcl_vars.mg_overworld_max,
		humidity_point = 50,
		heat_point = 50,
	})
end

-- All mapgens except mgv6, flat and singlenode
local function register_biomes()
	--[[ OVERWORLD ]]

	--[[ These biomes try to resemble MC as good as possible. This means especially the floor cover and
	the type of plants and structures (shapes might differ). The terrain itself will be of course different
	and depends on the mapgen.
	Important: MC also takes the terrain into account while MT biomes don't care about the terrain at all
	(except height).
	MC has many “M” and “Hills” variants, most of which only differ in terrain compared to their original
	counterpart.
	In MT, any biome can occour in any terrain, so these variants are implied and are therefore
	not explicitly implmented in MCL2. “M” variants are only included if they have another unique feature,
	such as a different land cover.
	In MCL2, the MC Overworld biomes are split in multiple more parts (stacked by height):
	* The main part, this represents the land. It begins at around sea level and usually goes all the way up
	* _ocean: For the area covered by ocean water. The y_max may vary for various beach effects.
	          Has sand or dirt as floor.
	* _deep_ocean: Like _ocean, but deeper and has gravel as floor
	* _underground:
	* Other modifiers: Some complex biomes require more layers to improve the landscape.

	The following naming conventions apply:
	* The land biome name is equal to the MC biome name (in camel case)
	* Height modifiers and sub-biomes are appended with underscores and in lowercase. Example: “_ocean”
	* Non-MC biomes are written in lowercase
	* MC dimension biomes are named after their MC dimension

	Intentionally missing biomes:
	* River (generated by valleys and v7)
	* Frozen River (generated by valleys and v7)
	* Mesa (Bryce)
	* Hills biomes
	* Plateau
	* Plateau M
	* Cold Taiga M
	* Taiga M
	* Roofed Forest M
	* Swampland M
	* Mesa Plateau F M
	* Extreme Hills Edge

	TODO:
	* Better beaches
	* Improve Extreme Hills M
	* Desert M

	Tricky biomes:
	* Mushroom Island (must be on island)
	* Stone Beach (must be at beaches only)
	TODO: Find a way to position these biomes accordingly.

	]]

	-- List of Overworld biomes without modifiers.
	-- IMPORTANT: Don't forget to add new Overworld biomes to this list!
	local overworld_biomes = {
		"IcePlains",
		"IcePlainsSpikes",
		"ColdTaiga",
		"ExtremeHills",
		"ExtremeHillsM",
		"ExtremeHills+",
		"Taiga",
		"MegaTaiga",
		"MegaSpruceTaiga",
		"StoneBeach",
		"Plains",
		"SunflowerPlains",
		"Forest",
		"FlowerForest",
		"BirchForest",
		"BirchForestM",
		"RoofedForest",
		"Swampland",
		"Jungle",
		"JungleM",
		"JungleEdge",
		"JungleEdgeM",
		"MushroomIsland",
		"Desert",
		"Savanna",
		"SavannaM",
		"Mesa",
		"MesaPlateauF",
	}

	local OCEAN_MIN = -15
	local DEEP_OCEAN_MAX = OCEAN_MIN - 1
	local DEEP_OCEAN_MIN = -31

	-- Ice Plains Spikes (rare)
	minetest.register_biome({
		name = "IcePlainsSpikes",
		node_top = "mcl_core:snowblock",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 2,
		node_river_water = "mcl_core:ice",
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		humidity_point = 24,
		heat_point = -5,
	})
	minetest.register_biome({
		name = "IcePlainsSpikes_ocean",
		node_top = "mcl_core:sand",
		depth_top = 2,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_water_top = "mcl_core:ice",
		depth_water_top = 2,
		node_river_water = "mcl_core:ice",
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = 0,
		humidity_point = 24,
		heat_point = -5,
	})

	-- Cold Taiga
	minetest.register_biome({
		name = "ColdTaiga",
		node_dust = "mcl_core:snow",
		node_top = "mcl_core:dirt_with_grass_snow",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 2,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = 3,
		y_max = mcl_vars.mg_overworld_max,
		humidity_point = 58,
		heat_point = 8,
	})

	-- A cold beach-like biome, implemented as low part of Cold Taiga
	minetest.register_biome({
		name = "ColdTaiga_beach",
		node_dust = "mcl_core:snow",
		node_top = "mcl_core:sand",
		depth_top = 2,
		node_water_top = "mcl_core:ice",
		depth_water_top = 1,
		node_filler = "mcl_core:sandstone",
		depth_filler = 2,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = 1,
		y_max = 2,
		humidity_point = 58,
		heat_point = 8,
	})
	-- Water part of the beach. Added to prevent snow being on the ice.
	minetest.register_biome({
		name = "ColdTaiga_beach_water",
		node_top = "mcl_core:sand",
		depth_top = 2,
		node_water_top = "mcl_core:ice",
		depth_water_top = 1,
		node_filler = "mcl_core:sandstone",
		depth_filler = 2,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = -3,
		y_max = 0,
		humidity_point = 58,
		heat_point = 8,
	})
	minetest.register_biome({
		name = "ColdTaiga_ocean",
		node_top = "mcl_core:dirt",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = -4,
		humidity_point = 58,
		heat_point = 8,
	})

	-- Mega Taiga
	minetest.register_biome({
		name = "MegaTaiga",
		node_top = "mcl_core:podzol",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		humidity_point = 76,
		heat_point = 10,
	})
	minetest.register_biome({
		name = "MegaTaiga_ocean",
		node_top = "mcl_core:dirt",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = 0,
		humidity_point = 76,
		heat_point = 10,
	})

	-- Mega Spruce Taiga
	minetest.register_biome({
		name = "MegaSpruceTaiga",
		node_top = "mcl_core:podzol",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		humidity_point = 100,
		heat_point = 8,
	})
	minetest.register_biome({
		name = "MegaSpruceTaiga_ocean",
		node_top = "mcl_core:dirt",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = 0,
		humidity_point = 100,
		heat_point = 8,
	})

	-- Extreme Hills
	minetest.register_biome({
		name = "ExtremeHills",
		node_top = "mcl_core:dirt_with_grass",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 4,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 4,
		y_min = 4,
		y_max = mcl_vars.mg_overworld_max,
		humidity_point = 10,
		heat_point = 45,
	})
	minetest.register_biome({
		name = "ExtremeHills_beach",
		node_top = "mcl_core:sand",
		depth_top = 2,
		depth_water_top = 1,
		node_filler = "mcl_core:sandstone",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 4,
		y_min = -3,
		y_max = 3,
		humidity_point = 10,
		heat_point = 45,
	})
	minetest.register_biome({
		name = "ExtremeHills_ocean",
		node_top = "mcl_core:dirt",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 4,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 4,
		y_min = OCEAN_MIN,
		y_max = -4,
		humidity_point = 10,
		heat_point = 45,
	})

	-- Extreme Hills M
	minetest.register_biome({
		name = "ExtremeHillsM",
		node_top = "mcl_core:gravel",
		depth_top = 1,
		node_filler = "mcl_core:gravel",
		depth_filler = 3,
		node_riverbed = "mcl_core:gravel",
		depth_riverbed = 3,
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		humidity_point = 0,
		heat_point = 25,
	})
	minetest.register_biome({
		name = "ExtremeHillsM_ocean",
		node_top = "mcl_core:dirt",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 3,
		y_min = OCEAN_MIN,
		y_max = 0,
		humidity_point = 0,
		heat_point = 25,
	})

	-- Extreme Hills+
	-- This biome is identical to Extreme Hills on the surface but has snow-covered mountains with spruce/oak
	-- Forests above a certain height.
	minetest.register_biome({
		name = "ExtremeHills+",
		node_top = "mcl_core:dirt_with_grass",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 4,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 4,
		y_min = 1,
		y_max = 44,
		humidity_point = 24,
		heat_point = 25,
	})
	---- Sub-biome for Extreme Hills+ for those snow Forests
	minetest.register_biome({
		name = "ExtremeHills+_snowtop",
		node_dust = "mcl_core:snow",
		node_top = "mcl_core:dirt_with_grass_snow",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 4,
		node_river_water = "mcl_core:ice",
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 4,
		y_min = 45,
		y_max = mcl_vars.mg_overworld_max,
		humidity_point = 24,
		heat_point = 25,
	})
	minetest.register_biome({
		name = "ExtremeHills+_ocean",
		node_top = "mcl_core:dirt",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 4,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 4,
		y_min = OCEAN_MIN,
		y_max = 0,
		humidity_point = 24,
		heat_point = 25,
	})

	-- Stone beach
	-- TODO: Should occour only at real beaches.
	minetest.register_biome({
		name = "StoneBeach",
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 1,
		y_min = -6,
		y_max = mcl_vars.mg_overworld_max,
		humidity_point = 0,
		heat_point = 8,
	})

	minetest.register_biome({
		name = "StoneBeach_ocean",
		node_top = "mcl_core:dirt",
		depth_top = 1,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 1,
		y_min = OCEAN_MIN,
		y_max = -7,
		humidity_point = 0,
		heat_point = 8,
	})

	-- Ice Plains
	minetest.register_biome({
		name = "IcePlains",
		node_dust = "mcl_core:snow",
		node_top = "mcl_core:dirt_with_grass_snow",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 2,
		node_water_top = "mcl_core:ice",
		depth_water_top = 2,
		node_river_water = "mcl_core:ice",
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		humidity_point = 24,
		heat_point = 8,
	})
	minetest.register_biome({
		name = "IcePlains_ocean",
		node_top = "mcl_core:dirt",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = 0,
		humidity_point = 24,
		heat_point = 8,
	})

	-- Plains
	minetest.register_biome({
		name = "Plains",
		node_top = "mcl_core:dirt_with_grass",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 2,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = 3,
		y_max = mcl_vars.mg_overworld_max,
		humidity_point = 39,
		heat_point = 58,
	})
	minetest.register_biome({
		name = "Plains_beach",
		node_top = "mcl_core:sand",
		depth_top = 2,
		node_filler = "mcl_core:sandstone",
		depth_filler = 2,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = 0,
		y_max = 2,
		humidity_point = 39,
		heat_point = 58,
	})
	minetest.register_biome({
		name = "Plains_ocean",
		node_top = "mcl_core:dirt",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = -1,
		humidity_point = 39,
		heat_point = 58,
	})

	-- Sunflower Plains
	minetest.register_biome({
		name = "SunflowerPlains",
		node_top = "mcl_core:dirt_with_grass",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = 4,
		y_max = mcl_vars.mg_overworld_max,
		humidity_point = 28,
		heat_point = 45,
	})
	minetest.register_biome({
		name = "SunflowerPlains_ocean",
		node_top = "mcl_core:dirt",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:dirt",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = 0,
		humidity_point = 28,
		heat_point = 45,
	})

	-- Taiga
	minetest.register_biome({
		name = "Taiga",
		node_top = "mcl_core:dirt_with_grass",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = 4,
		y_max = mcl_vars.mg_overworld_max,
		humidity_point = 58,
		heat_point = 22,
	})
	minetest.register_biome({
		name = "Taiga_beach",
		node_top = "mcl_core:sand",
		depth_top = 2,
		node_filler = "mcl_core:sandstone",
		depth_filler = 1,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = 1,
		y_max = 3,
		humidity_point = 58,
		heat_point = 22,
	})
	minetest.register_biome({
		name = "Taiga_ocean",
		node_top = "mcl_core:sand",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = 0,
		humidity_point = 58,
		heat_point = 22,
	})

	-- Forest
	minetest.register_biome({
		name = "Forest",
		node_top = "mcl_core:dirt_with_grass",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		humidity_point = 61,
		heat_point = 45,
	})
	minetest.register_biome({
		name = "Forest_beach",
		node_top = "mcl_core:sand",
		depth_top = 2,
		node_filler = "mcl_core:sandstone",
		depth_filler = 1,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = -1,
		y_max = 0,
		humidity_point = 61,
		heat_point = 45,
	})
	minetest.register_biome({
		name = "Forest_ocean",
		node_top = "mcl_core:dirt",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = -2,
		humidity_point = 61,
		heat_point = 45,
	})

	-- Flower Forest
	minetest.register_biome({
		name = "FlowerForest",
		node_top = "mcl_core:dirt_with_grass",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = 3,
		y_max = mcl_vars.mg_overworld_max,
		humidity_point = 44,
		heat_point = 32,
	})
	minetest.register_biome({
		name = "FlowerForest_beach",
		node_top = "mcl_core:sand",
		depth_top = 2,
		node_filler = "mcl_core:sandstone",
		depth_filler = 1,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = -2,
		y_max = 2,
		humidity_point = 44,
		heat_point = 32,
	})
	minetest.register_biome({
		name = "FlowerForest_ocean",
		node_top = "mcl_core:dirt",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = -3,
		humidity_point = 44,
		heat_point = 32,
	})

	-- Birch Forest
	minetest.register_biome({
		name = "BirchForest",
		node_top = "mcl_core:dirt_with_grass",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		humidity_point = 78,
		heat_point = 31,
	})
	minetest.register_biome({
		name = "BirchForest_ocean",
		node_top = "mcl_core:dirt",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = 0,
		humidity_point = 78,
		heat_point = 31,
	})

	-- Birch Forest M
	minetest.register_biome({
		name = "BirchForestM",
		node_top = "mcl_core:dirt_with_grass",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		humidity_point = 77,
		heat_point = 27,
	})
	minetest.register_biome({
		name = "BirchForestM_ocean",
		node_top = "mcl_core:dirt",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = 0,
		humidity_point = 77,
		heat_point = 27,
	})

	-- Desert
	minetest.register_biome({
		name = "Desert",
		node_top = "mcl_core:sand",
		depth_top = 1,
		node_filler = "mcl_core:sand",
		depth_filler = 2,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		node_stone = "mcl_core:sandstone",
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		humidity_point = 26,
		heat_point = 94,
	})
	minetest.register_biome({
		name = "Desert_ocean",
		node_top = "mcl_core:sand",
		depth_top = 1,
		node_filler = "mcl_core:sand",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = 0,
		humidity_point = 26,
		heat_point = 94,
	})

	-- Roofed Forest
	minetest.register_biome({
		name = "RoofedForest",
		node_top = "mcl_core:dirt_with_grass",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 2,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		humidity_point = 94,
		heat_point = 27,
	})
	minetest.register_biome({
		name = "RoofedForest_ocean",
		node_top = "mcl_core:dirt",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 2,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = 0,
		humidity_point = 94,
		heat_point = 27,
	})

	-- Mesa
	minetest.register_biome({
		name = "Mesa",
		node_top = "mcl_colorblocks:hardened_clay",
		depth_top = 1,
		node_filler = "mcl_colorblocks:hardened_clay",
		node_riverbed = "mcl_core:redsand",
		depth_riverbed = 1,
		node_stone = "mcl_colorblocks:hardened_clay",
		y_min = 11,
		y_max = mcl_vars.mg_overworld_max,
		humidity_point = 0,
		heat_point = 100,
	})
	-- Helper biome for the red sand at the bottom of Mesas.
	minetest.register_biome({
		name = "Mesa_sandlevel",
		node_top = "mcl_core:redsand",
		depth_top = 1,
		node_filler = "mcl_colorblocks:hardened_clay_orange",
		depth_filler = 3,
		node_riverbed = "mcl_core:redsand",
		depth_riverbed = 1,
		node_stone = "mcl_colorblocks:hardened_clay_orange",
		y_min = -3,
		y_max = 10,
		humidity_point = 0,
		heat_point = 100,
	})
	minetest.register_biome({
		name = "Mesa_ocean",
		node_top = "mcl_core:sand",
		depth_top = 3,
		node_filler = "mcl_core:sand",
		depth_filler = 2,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = -4,
		humidity_point = 0,
		heat_point = 100,
	})

	-- Mesa Plateau F
	-- Identical to Mesa below Y=30. At Y=30 and above there is an oak forest
	minetest.register_biome({
		name = "MesaPlateauF",
		node_top = "mcl_colorblocks:hardened_clay",
		depth_top = 1,
		node_filler = "mcl_colorblocks:hardened_clay",
		node_riverbed = "mcl_core:redsand",
		depth_riverbed = 1,
		node_stone = "mcl_colorblocks:hardened_clay",
		y_min = 11,
		y_max = 29,
		humidity_point = 0,
		heat_point = 60,
	})

	-- The actual plateau of this biome
	-- This is a plateau for grass blocks, tall grass, coarse dirt and oaks.
	minetest.register_biome({
		name = "MesaPlateauF_grasstop",
		node_top = "mcl_core:dirt_with_dry_grass",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 1,
		node_riverbed = "mcl_core:redsand",
		depth_riverbed = 1,
		node_stone = "mcl_colorblocks:hardened_clay",
		y_min = 30,
		y_max = mcl_vars.mg_overworld_max,
		humidity_point = 0,
		heat_point = 60,
	})

	-- Helper biome for the red sand at the bottom.
	minetest.register_biome({
		name = "MesaPlateauF_sandlevel",
		node_top = "mcl_core:redsand",
		depth_top = 1,
		node_filler = "mcl_colorblocks:hardened_clay_orange",
		depth_filler = 3,
		node_riverbed = "mcl_core:redsand",
		depth_riverbed = 1,
		node_stone = "mcl_colorblocks:hardened_clay_orange",
		y_min = -3,
		y_max = 10,
		humidity_point = 0,
		heat_point = 60,
	})
	minetest.register_biome({
		name = "MesaPlateauF_ocean",
		node_top = "mcl_core:sand",
		depth_top = 3,
		node_filler = "mcl_colorblocks:sand",
		depth_filler = 2,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = -4,
		humidity_point = 0,
		heat_point = 60,
	})

	-- Savanna
	minetest.register_biome({
		name = "Savanna",
		node_top = "mcl_core:dirt_with_dry_grass",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 2,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		humidity_point = 36,
		heat_point = 79,
	})
	minetest.register_biome({
		name = "Savanna_beach",
		node_top = "mcl_core:sand",
		depth_top = 3,
		node_filler = "mcl_core:sandstone",
		depth_filler = 2,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = -1,
		y_max = 0,
		humidity_point = 36,
		heat_point = 79,
	})
	minetest.register_biome({
		name = "Savanna_ocean",
		node_top = "mcl_core:dirt",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = -2,
		humidity_point = 36,
		heat_point = 79,
	})

	-- Savanna M
	-- Changes to Savanna: Coarse Dirt. No sand beach. No oaks.
	-- Otherwise identical to Savanna
	minetest.register_biome({
		name = "SavannaM",
		node_top = "mcl_core:dirt_with_dry_grass",
		depth_top = 1,
		node_filler = "mcl_core:coarse_dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		humidity_point = 48,
		heat_point = 100,
	})
	minetest.register_biome({
		name = "SavannaM_ocean",
		node_top = "mcl_core:dirt",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = 0,
		humidity_point = 48,
		heat_point = 100,
	})

	-- Jungle
	minetest.register_biome({
		name = "Jungle",
		node_top = "mcl_core:dirt_with_grass",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		humidity_point = 88,
		heat_point = 81,
	})
	minetest.register_biome({
		name = "Jungle_shore",
		node_top = "mcl_core:dirt",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = -1,
		y_max = 0,
		humidity_point = 88,
		heat_point = 81,
	})
	minetest.register_biome({
		name = "Jungle_ocean",
		node_top = "mcl_core:dirt",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = -2,
		humidity_point = 88,
		heat_point = 81,
	})

	-- Jungle M
	-- Like Jungle but with even more dense vegetation
	minetest.register_biome({
		name = "JungleM",
		node_top = "mcl_core:dirt_with_grass",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		humidity_point = 92,
		heat_point = 81,
	})
	minetest.register_biome({
		name = "JungleM_shore",
		node_top = "mcl_core:dirt",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = -1,
		y_max = 0,
		humidity_point = 92,
		heat_point = 81,
	})
	minetest.register_biome({
		name = "JungleM_ocean",
		node_top = "mcl_core:dirt",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = -2,
		humidity_point = 92,
		heat_point = 81,
	})

	-- Jungle Edge
	minetest.register_biome({
		name = "JungleEdge",
		node_top = "mcl_core:dirt_with_grass",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 2,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		humidity_point = 88,
		heat_point = 76,
	})
	minetest.register_biome({
		name = "JungleEdge_ocean",
		node_top = "mcl_core:dirt",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 2,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = 0,
		humidity_point = 88,
		heat_point = 76,
	})

	-- Jungle Edge M (very rare).
	-- Almost identical to Jungle Edge. Has deeper dirt. Melons spawn here a lot.
	-- This biome occours directly between Jungle M and Jungle Edge but also has a small border to Jungle.
	-- This biome is very small in general.
	minetest.register_biome({
		name = "JungleEdgeM",
		node_top = "mcl_core:dirt_with_grass",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 4,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		humidity_point = 90,
		heat_point = 79,
	})
	minetest.register_biome({
		name = "JungleEdgeM_ocean",
		node_top = "mcl_core:dirt",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 4,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = 0,
		humidity_point = 90,
		heat_point = 79,
	})

	-- Swampland
	minetest.register_biome({
		name = "Swampland",
		node_top = "mcl_core:dirt_with_grass",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = 1,
		-- Note: Limited in height!
		y_max = 23,
		humidity_point = 90,
		heat_point = 50,
	})
	minetest.register_biome({
		name = "Swampland_shore",
		node_top = "mcl_core:dirt",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = -4,
		y_max = 0,
		humidity_point = 90,
		heat_point = 50,
	})
	minetest.register_biome({
		name = "Swampland_ocean",
		node_top = "mcl_core:sand",
		depth_top = 1,
		node_filler = "mcl_core:sand",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = -5,
		humidity_point = 90,
		heat_point = 50,
	})

	-- Mushroom Island / Mushroom Island Shore (rare)
	-- TODO: Make sure these biomes only spawn in islands
	minetest.register_biome({
		name = "MushroomIsland",
		node_top = "mcl_core:mycelium",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = 4,
		-- Note: Limited in height!
		y_max = 20,
		humidity_point = 106,
		heat_point = 50,
	})

	minetest.register_biome({
		name = "MushroomIslandShore",
		node_top = "mcl_core:mycelium",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = 1,
		y_max = 3,
		humidity_point = 106,
		heat_point = 50,
	})
	minetest.register_biome({
		name = "MushroomIsland_ocean",
		node_top = "mcl_core:dirt",
		depth_top = 1,
		node_filler = "mcl_core:dirt",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = 0,
		humidity_point = 106,
		heat_point = 50,
	})

	-- Add deep ocean and underground biomes automatically.
	for i=1, #overworld_biomes do
		local biome = overworld_biomes[i]

		-- Deep Ocean: Has gravel floor
		minetest.register_biome({
			name = biome .. "_deep_ocean",
			heat_point = minetest.registered_biomes[biome].heat_point,
			humidity_point = minetest.registered_biomes[biome].humidity_point,
			y_min = DEEP_OCEAN_MIN,
			y_max = DEEP_OCEAN_MAX,
			node_top = "mcl_core:gravel",
			depth_top = 1,
			node_filler = "mcl_core:gravel",
			depth_filler = 2,
			node_riverbed = "mcl_core:gravel",
			depth_riverbed = 2,
		})

		-- Underground biomes are used to identify the underground and to prevent nodes from the surface
		-- (sand, dirt) from leaking into the underground.
		minetest.register_biome({
			name = biome .. "_underground",
			heat_point = minetest.registered_biomes[biome].heat_point,
			humidity_point = minetest.registered_biomes[biome].humidity_point,
			y_min = mcl_vars.mg_overworld_min,
			y_max = DEEP_OCEAN_MIN - 1,
		})

	end
end

-- Register biomes of non-Overworld biomes
local function register_dimension_biomes()
	--[[ REALMS ]]

	--[[ THE NETHER ]]
	minetest.register_biome({
		name = "Nether",
		node_filler = "mcl_nether:netherrack",
		node_stone = "mcl_nether:netherrack",
		node_water = "air",
		node_river_water = "air",
		y_min = mcl_vars.mg_nether_min,
		-- FIXME: For some reason the Nether stops generating early if this constant is not added.
		-- Figure out why.
		y_max = mcl_vars.mg_nether_max + 80,
		heat_point = 100,
		humidity_point = 0,
	})

	--[[ THE END ]]
	minetest.register_biome({
		name = "End",
		node_stone = "air",
		node_filler = "air",
		node_water = "air",
		node_river_water = "air",
		-- FIXME: For some reason the End stops generating early if this constant is not added.
		-- Figure out why.
		y_min = mcl_vars.mg_end_min,
		y_max = mcl_vars.mg_end_max + 80,
		heat_point = 50,
		humidity_point = 50,
	})

end

-- Register ores which are limited by biomes. For all mapgens except flat and singlenode.
local function register_biome_ores()
	local stonelike = {"mcl_core:stone", "mcl_core:diorite", "mcl_core:andesite", "mcl_core:granite"}

	-- Emeralds
	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_worlds.layer_to_y(4),
		y_max          = mcl_worlds.layer_to_y(32),
		biomes         = { "ExtremeHills", "ExtremeHills_beach", "ExtremeHills_ocean" },
	})

	-- Rarely replace stone with stone monster eggs.
	-- In v6 this can happen anywhere, in other mapgens only in Extreme Hills.
	local monster_egg_scarcity
	if mg_name == "v6" then
		monster_egg_scarcity = 28 * 28 * 28
	else
		monster_egg_scarcity = 26 * 26 * 26
	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,
		y_min          = mcl_vars.mg_overworld_min,
		y_max          = mcl_worlds.layer_to_y(61),
		biomes         = { "ExtremeHills", "ExtremeHills_beach", "ExtremeHills_ocean" },
	})

	-- Bonus gold spawn in Mesa
	if mg_name ~= "v6" then
		minetest.register_ore({
			ore_type       = "scatter",
			ore            = "mcl_core:stone_with_gold",
			wherein        = stonelike,
			clust_scarcity = 3333,
			clust_num_ores = 5,
			clust_size     = 3,
			y_min          = mcl_worlds.layer_to_y(32),
			y_max          = mcl_worlds.layer_to_y(79),
			biomes         = { "Mesa", "Mesa_sandlevel", "Mesa_ocean" },
		})
	end
end

-- Register “fake” ores directly related to the biomes. These are mostly low-level landscape alternations
local function register_biomelike_ores()

	-- Random coarse dirt floor in Mega Taiga and Mesa Plateau F
	minetest.register_ore({
		ore_type	= "sheet",
		ore		= "mcl_core:coarse_dirt",
		wherein		= {"mcl_core:podzol", "mcl_core:dirt"},
		clust_scarcity	= 1,
		clust_num_ores	= 12,
		clust_size	= 10,
		y_min		= mcl_vars.mg_overworld_min,
		y_max		= mcl_vars.mg_overworld_max,
		noise_threshold = 0.2,
		noise_params = {offset=0, scale=15, spread={x=130, y=130, z=130}, seed=24, octaves=3, persist=0.70},
		biomes = { "MegaTaiga" },
	})

	minetest.register_ore({
		ore_type	= "sheet",
		ore		= "mcl_core:coarse_dirt",
		wherein		= {"mcl_core:dirt_with_dry_grass", "mcl_core:dirt"},
		column_height_max = 1,
		column_midpoint_factor = 0.0,
		y_min		= mcl_vars.mg_overworld_min,
		y_max		= mcl_vars.mg_overworld_max,
		noise_threshold = 0.0,
		noise_params = {offset=0, scale=15, spread={x=250, y=250, z=250}, seed=24, octaves=3, persist=0.70},
		biomes = { "MesaPlateauF_grasstop" },
	})
	minetest.register_ore({
		ore_type	= "blob",
		ore		= "mcl_core:coarse_dirt",
		wherein		= {"mcl_core:dirt_with_dry_grass", "mcl_core:dirt"},
		clust_scarcity	= 1500,
		clust_num_ores	= 25,
		clust_size	= 7,
		y_min		= mcl_vars.mg_overworld_min,
		y_max		= mcl_vars.mg_overworld_max,
		biomes = { "MesaPlateauF_grasstop" },
	})

	-- Small dirt patches in Extreme Hills M
	minetest.register_ore({
		ore_type	= "blob",
		-- TODO: Should be grass block. But generating this as ore means gras blocks will spawn undeground. :-(
		ore		= "mcl_core:dirt",
		wherein		= {"mcl_core:gravel"},
		clust_scarcity	= 5000,
		clust_num_ores	= 12,
		clust_size	= 4,
		y_min		= mcl_vars.mg_overworld_min,
		y_max		= mcl_vars.mg_overworld_max,
		noise_threshold = 0.2,
		noise_params = {offset=0, scale=5, spread={x=250, y=250, z=250}, seed=64, octaves=3, persist=0.60},
		biomes = { "ExtremeHillsM" },
	})


	-- Small hack to make sure stone appears at ca. sea level in Mesa biomes
	minetest.register_ore({
		ore_type = "sheet",
		ore = "mcl_core:stone",
		noise_threshold = -100,
		noise_params = {offset=0, scale=1, spread={x=3100, y=3100, z=3100}, octaves=1, persist=1.00},
		biomes = {
			"Mesa", "Mesa_sandlevel", "Mesa_ocean", "Mesa_deep_ocean", "Mesa_underground",
			"MesaPlateauF", "MesaPlateauF_sandlevel", "MesaPlateauF_ocean", "MesaPlateauF_deep_ocean", "MesaPlateauF_underground",
		},
		wherein = {"mcl_colorblocks:hardened_clay"},
		column_height_min = 32,
		column_height_max = 32,
		y_min = -32,
		y_max = 0,
	})



	-- Mesa strata (registered as sheet ores)

	-- Helper function to create strata.
	local stratum = function(y_min, height, color, seed)
		if not height then
			height = 1
		end
		if not seed then
			seed = 39
		end
		local y_max = y_min + height-1
		minetest.register_ore({
			ore_type = "sheet",
			ore = "mcl_colorblocks:hardened_clay_"..color,
			wherein = {"mcl_colorblocks:hardened_clay"},
			column_height_min = height,
			column_height_max = height,
			y_min = y_min,
			y_max = y_max,
			noise_threshold = -1.0,
			noise_params = {offset=0, scale=1, spread={x=3100, y=3100, z=3100}, seed=seed, octaves=3, persist=0.70},
			biomes = { "Mesa", "MesaPlateauF", },
		})
	end

	-- First stratum near the sand level. Always orange.
	stratum(11, 3, "orange")

	-- Create random strata for up to Y = 256.
	-- These strata are calculated based on the world seed and are global.
	-- They are thus unique per-world.
	local mesapr = PcgRandom(minetest.get_mapgen_setting("seed"))

	--[[

	------ DANGER ZONE! ------

	The following code is sensitive to changes; changing any number may break
	mapgen consistency when the mapgen generates new mapchunks in existing
	worlds because the random generator will yield different results and the strata
	suddenly don't match up anymore. ]]

	-- Available Mesa colors:
	local mesa_stratum_colors = { "silver", "brown", "orange", "red", "yellow", "white" }

	-- Start level
	local y = 17

	-- Generate stratas
	repeat
		-- Each stratum has a color (duh!)
		local colorid = mesapr:next(1, #mesa_stratum_colors)

		-- … and a random thickness
		local heightrandom = mesapr:next(1, 12)
		local h
		if heightrandom == 12 then
			h = 4
		elseif heightrandom >= 10 then
			h = 3
		elseif heightrandom >= 8 then
			h = 2
		else
			h = 1
		end
		-- Small built-in bias: Only thin strata up to this Y level
		if y < 45 then
			h = math.min(h, 2)
		end

		-- Register stratum
		stratum(y, h, mesa_stratum_colors[colorid])

		-- Skip a random amount of layers (which won't get painted)
		local skiprandom = mesapr:next(1, 12)
		local skip
		if skiprandom == 12 then
			skip = 4
		elseif skiprandom >= 10 then
			skip = 3
		elseif skiprandom >= 5 then
			skip = 2
		elseif skiprandom >= 2 then
			skip = 1
		else
			-- If this happens, the next stratum will touch the previous one without gap
			skip = 0
		end

		-- Get height of next stratum or finish
		y = y + h + skip
	until y > 256

	--[[ END OF DANGER ZONE ]]
end

-- Non-Overworld ores
local function register_dimension_ores()

	--[[ NETHER GENERATION ]]

	-- Soul sand
	minetest.register_ore({
		ore_type        = "sheet",
		ore             = "mcl_nether:soul_sand",
		-- Note: Stone is included only for v6 mapgen support. Netherrack is not generated naturally
		-- in v6, but instead set with the on_generated function in mcl_mapgen_core.
		wherein         = {"mcl_nether:netherrack", "mcl_core:stone"},
		clust_scarcity  = 13 * 13 * 13,
		clust_size      = 5,
		y_min           = mcl_vars.mg_nether_min,
		y_max           = mcl_worlds.layer_to_y(64, "nether"),
		noise_threshold = 0.0,
		noise_params    = {
			offset = 0.5,
			scale = 0.1,
			spread = {x = 5, y = 5, z = 5},
			seed = 2316,
			octaves = 1,
			persist = 0.0
		},
	})

	-- Magma blocks
	minetest.register_ore({
		ore_type       = "blob",
		ore            = "mcl_nether:magma",
		wherein         = {"mcl_nether:netherrack", "mcl_core:stone"},
		clust_scarcity = 8*8*8,
		clust_num_ores = 45,
		clust_size     = 6,
		y_min          = mcl_worlds.layer_to_y(23, "nether"),
		y_max          = mcl_worlds.layer_to_y(37, "nether"),
	})
	minetest.register_ore({
		ore_type       = "blob",
		ore            = "mcl_nether:magma",
		wherein        = {"mcl_nether:netherrack"},
		clust_scarcity = 10*10*10,
		clust_num_ores = 65,
		clust_size     = 8,
		y_min          = mcl_worlds.layer_to_y(23, "nether"),
		y_max          = mcl_worlds.layer_to_y(37, "nether"),
	})

	-- Glowstone
	minetest.register_ore({
		ore_type        = "blob",
		ore             = "mcl_nether:glowstone",
		wherein         = {"mcl_nether:netherrack", "mcl_core:stone"},
		clust_scarcity  = 26 * 26 * 26,
		clust_size      = 5,
		y_min           = mcl_vars.mg_lava_nether_max + 10,
		y_max           = mcl_vars.mg_nether_max,
		noise_threshold = 0.0,
		noise_params    = {
			offset = 0.5,
			scale = 0.1,
			spread = {x = 5, y = 5, z = 5},
			seed = 17676,
			octaves = 1,
			persist = 0.0
		},
	})

	-- Gravel (Nether)
	minetest.register_ore({
		ore_type        = "sheet",
		ore             = "mcl_core:gravel",
		wherein         = {"mcl_nether:netherrack", "mcl_core:stone"},
		column_height_min = 1,
		column_height_max = 1,
		column_midpoint_factor = 0,
		y_min           = mcl_worlds.layer_to_y(63, "nether"),
		-- This should be 65, but for some reason with this setting, the sheet ore really stops at 65. o_O
		y_max           = mcl_worlds.layer_to_y(65+2, "nether"),
		noise_threshold = 0.2,
		noise_params    = {
			offset = 0.0,
			scale = 0.5,
			spread = {x = 20, y = 20, z = 20},
			seed = 766,
			octaves = 3,
			persist = 0.6,
		},
	})

	-- Nether quartz
	minetest.register_ore({
		ore_type       = "scatter",
		ore            = "mcl_nether:quartz_ore",
		wherein         = {"mcl_nether:netherrack", "mcl_core:stone"},
		clust_scarcity = 850,
		clust_num_ores = 4, -- MC cluster amount: 4-10
		clust_size     = 3,
		y_min = mcl_vars.mg_nether_min,
		y_max = mcl_vars.mg_nether_max,
	})
	minetest.register_ore({
		ore_type       = "scatter",
		ore            = "mcl_nether:quartz_ore",
		wherein         = {"mcl_nether:netherrack", "mcl_core:stone"},
		clust_scarcity = 1650,
		clust_num_ores = 8, -- MC cluster amount: 4-10
		clust_size     = 4,
		y_min = mcl_vars.mg_nether_min,
		y_max = mcl_vars.mg_nether_max,
	})

	-- Lava springs in the Nether
	minetest.register_ore({
		ore_type       = "scatter",
		ore            = "mcl_nether:nether_lava_source",
		wherein         = {"mcl_nether:netherrack", "mcl_core:stone"},
		clust_scarcity = 500,
		clust_num_ores = 1,
		clust_size     = 1,
		y_min           = mcl_vars.mg_nether_min,
		y_max           = mcl_vars.mg_lava_nether_max + 1,
	})

	minetest.register_ore({
		ore_type       = "scatter",
		ore            = "mcl_nether:nether_lava_source",
		wherein         = {"mcl_nether:netherrack", "mcl_core:stone"},
		clust_scarcity = 1000,
		clust_num_ores = 1,
		clust_size     = 1,
		y_min           = mcl_vars.mg_lava_nether_max + 2,
		y_max           = mcl_vars.mg_lava_nether_max + 12,
	})

	minetest.register_ore({
		ore_type       = "scatter",
		ore            = "mcl_nether:nether_lava_source",
		wherein         = {"mcl_nether:netherrack", "mcl_core:stone"},
		clust_scarcity = 2000,
		clust_num_ores = 1,
		clust_size     = 1,
		y_min           = mcl_vars.mg_lava_nether_max + 13,
		y_max           = mcl_vars.mg_lava_nether_max + 48,
	})
	minetest.register_ore({
		ore_type       = "scatter",
		ore            = "mcl_nether:nether_lava_source",
		wherein         = {"mcl_nether:netherrack", "mcl_core:stone"},
		clust_scarcity = 3500,
		clust_num_ores = 1,
		clust_size     = 1,
		y_min           = mcl_vars.mg_lava_nether_max + 49,
		y_max           = mcl_vars.mg_nether_max,
	})

	--[[ THE END ]]

	-- Generate fake End
	-- TODO: Remove both "ores" when there's a better End generator

	minetest.register_ore({
		ore_type        = "sheet",
		ore             = "mcl_end:end_stone",
		wherein         = {"air"},
		y_min           = mcl_vars.mg_end_min+64,
		y_max           = mcl_vars.mg_end_min+80,
		column_height_min = 6,
		column_height_max = 7,
		column_midpoint_factor = 0.0,
		noise_params = {
			offset  = -2,
			scale   = 8,
			spread  = {x=100, y=100, z=100},
			seed    = 2999,
			octaves = 5,
			persist = 0.55,
		},
		noise_threshold = 0,
	})

	minetest.register_ore({
		ore_type        = "sheet",
		ore             = "mcl_end:end_stone",
		wherein         = {"air"},
		y_min           = mcl_vars.mg_end_min+64,
		y_max           = mcl_vars.mg_end_min+80,
		column_height_min = 4,
		column_height_max = 4,
		column_midpoint_factor = 0.0,
		noise_params = {
			offset  = -4,
			scale   = 3,
			spread  = {x=200, y=200, z=200},
			seed    = 5390,
			octaves = 5,
			persist = 0.6,
		},
		noise_threshold = 0,
	})

end


-- All mapgens except mgv6

-- Template to register a grass or fern decoration
local function register_grass_decoration(grasstype, offset, scale, biomes, param2)
	local place_on, seed, node
	if grasstype == "fern" then
		node = "mcl_flowers:fern"
		place_on = {"group:grass_block_no_snow", "mcl_core:podzol"}
		seed = 333
	elseif grasstype == "tallgrass" then
		node = "mcl_flowers:tallgrass"
		place_on = {"group:grass_block_no_snow"}
		seed = 420
	end
	local noise = {
		offset = offset,
		scale = scale,
		spread = {x = 200, y = 200, z = 200},
		seed = seed,
		octaves = 3,
		persist = 0.6
	}
	minetest.register_decoration({
		deco_type = "simple",
		place_on = place_on,
		sidelen = 16,
		noise_params = noise,
		biomes = biomes,
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		decoration = node,
		param2 = param2,
	})
end

local function register_decorations()
	-- Large ice spike
	minetest.register_decoration({
		deco_type = "schematic",
		place_on = {"mcl_core:snowblock", "mcl_core:snow", "group:grass_block_snow"},
		sidelen = 80,
		noise_params = {
			offset = 0.00040,
			scale = 0.001,
			spread = {x = 250, y = 250, z = 250},
			seed = 1133,
			octaves = 4,
			persist = 0.67,
		},
		biomes = {"IcePlainsSpikes"},
		y_min = 4,
		y_max = mcl_vars.mg_overworld_max,
		schematic = minetest.get_modpath("mcl_structures").."/schematics/mcl_structures_ice_spike_large.mts",
		rotation = "random",
		flags = "place_center_x, place_center_z",
	})

	-- Small ice spike
	minetest.register_decoration({
		deco_type = "schematic",
		place_on = {"mcl_core:snowblock", "mcl_core:snow", "group:grass_block_snow"},
		sidelen = 80,
		noise_params = {
			offset = 0.005,
			scale = 0.001,
			spread = {x = 250, y = 250, z = 250},
			seed = 1133,
			octaves = 4,
			persist = 0.67,
		},
		biomes = {"IcePlainsSpikes"},
		y_min = 4,
		y_max = mcl_vars.mg_overworld_max,
		schematic = minetest.get_modpath("mcl_structures").."/schematics/mcl_structures_ice_spike_small.mts",
		rotation = "random",
		flags = "place_center_x, place_center_z",
	})

	-- Oak
	-- Large oaks
	for i=1, 2 do
		minetest.register_decoration({
			deco_type = "schematic",
			place_on = {"group:grass_block_no_snow", "mcl_core:dirt"},
			sidelen = 80,
			noise_params = {
				offset = 0.00075,
				scale = 0.0011,
				spread = {x = 250, y = 250, z = 250},
				seed = 3,
				octaves = 3,
				persist = 0.66
			},
			biomes = {"Forest"},
			y_min = 1,
			y_max = mcl_vars.mg_overworld_max,
			schematic = minetest.get_modpath("mcl_core").."/schematics/mcl_core_oak_large_"..i..".mts",
			flags = "place_center_x, place_center_z",
			rotation = "random",
		})

		minetest.register_decoration({
			deco_type = "schematic",
			place_on = {"group:grass_block", "mcl_core:dirt", },
			sidelen = 80,
			noise_params = {
				offset = -0.0004,
				scale = 0.001,
				spread = {x = 250, y = 250, z = 250},
				seed = 3,
				octaves = 3,
				persist = 0.6
			},
			biomes = {"ExtremeHills", "ExtremeHillsM", "ExtremeHills+", "ExtremeHills+_snowtop"},
			y_min = 1,
			y_max = mcl_vars.mg_overworld_max,
			schematic = minetest.get_modpath("mcl_core").."/schematics/mcl_core_oak_large_"..i..".mts",
			flags = "place_center_x, place_center_z",
			rotation = "random",
		})
	end
	-- Small “classic” oak (many biomes)
	minetest.register_decoration({
		deco_type = "schematic",
		place_on = {"group:grass_block_no_snow", "mcl_core:dirt"},
		sidelen = 16,
		noise_params = {
			offset = 0.025,
			scale = 0.0022,
			spread = {x = 250, y = 250, z = 250},
			seed = 2,
			octaves = 3,
			persist = 0.66
		},
		biomes = {"Forest"},
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		schematic = minetest.get_modpath("mcl_core").."/schematics/mcl_core_oak_classic.mts",
		flags = "place_center_x, place_center_z",
		rotation = "random",
	})
	minetest.register_decoration({
		deco_type = "schematic",
		place_on = {"group:grass_block_no_snow", "mcl_core:dirt"},
		sidelen = 16,
		noise_params = {
			offset = 0.01,
			scale = 0.0022,
			spread = {x = 250, y = 250, z = 250},
			seed = 2,
			octaves = 3,
			persist = 0.66
		},
		biomes = {"FlowerForest"},
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		schematic = minetest.get_modpath("mcl_core").."/schematics/mcl_core_oak_classic.mts",
		flags = "place_center_x, place_center_z",
		rotation = "random",
	})
	minetest.register_decoration({
		deco_type = "schematic",
		place_on = {"group:grass_block", "mcl_core:dirt", },
		sidelen = 16,
		noise_params = {
			offset = 0.0,
			scale = 0.002,
			spread = {x = 250, y = 250, z = 250},
			seed = 2,
			octaves = 3,
			persist = 0.7
		},
		biomes = {"ExtremeHills", "ExtremeHillsM", "ExtremeHills+", "ExtremeHills+_snowtop"},
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		schematic = minetest.get_modpath("mcl_core").."/schematics/mcl_core_oak_classic.mts",
		flags = "place_center_x, place_center_z",
		rotation = "random",
	})

	minetest.register_decoration({
		deco_type = "schematic",
		place_on = {"group:grass_block", "mcl_core:dirt"},
		sidelen = 16,
		noise_params = {
			offset = 0.006,
			scale = 0.002,
			spread = {x = 250, y = 250, z = 250},
			seed = 2,
			octaves = 3,
			persist = 0.7
		},
		biomes = {"ExtremeHills+", "ExtremeHills+_snowtop"},
		y_min = 50,
		y_max = mcl_vars.mg_overworld_max,
		schematic = minetest.get_modpath("mcl_core").."/schematics/mcl_core_oak_classic.mts",
		flags = "place_center_x, place_center_z",
		rotation = "random",
	})
	minetest.register_decoration({
		deco_type = "schematic",
		place_on = {"mcl_core:dirt_with_dry_grass", "mcl_core:dirt"},
		sidelen = 16,
		noise_params = {
			offset = 0.015,
			scale = 0.002,
			spread = {x = 250, y = 250, z = 250},
			seed = 2,
			octaves = 3,
			persist = 0.7
		},
		biomes = {"MesaPlateauF_grasstop"},
		y_min = 30,
		y_max = mcl_vars.mg_overworld_max,
		schematic = minetest.get_modpath("mcl_core").."/schematics/mcl_core_oak_classic.mts",
		flags = "place_center_x, place_center_z",
		rotation = "random",
	})

	minetest.register_decoration({
		deco_type = "schematic",
		place_on = {"group:grass_block", "mcl_core:dirt", },
		sidelen = 16,
		noise_params = {
			offset = 0.0,
			scale = 0.0002,
			spread = {x = 250, y = 250, z = 250},
			seed = 2,
			octaves = 3,
			persist = 0.7
		},
		biomes = {"IcePlains"},
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		schematic = minetest.get_modpath("mcl_core").."/schematics/mcl_core_oak_classic.mts",
		flags = "place_center_x, place_center_z",
		rotation = "random",
	})
	minetest.register_decoration({
		deco_type = "schematic",
		place_on = {"group:grass_block_no_snow", "mcl_core:dirt"},
		sidelen = 80,
		fill_ratio = 0.004,
		biomes = {"Jungle", "JungleM"},
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		schematic = minetest.get_modpath("mcl_core").."/schematics/mcl_core_oak_classic.mts",
		flags = "place_center_x, place_center_z",
		rotation = "random",
	})
	minetest.register_decoration({
		deco_type = "schematic",
		place_on = {"group:grass_block_no_snow", "mcl_core:dirt"},
		sidelen = 80,
		fill_ratio = 0.0004,
		biomes = {"JungleEdge", "JungleEdgeM", "Savanna"},
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		schematic = minetest.get_modpath("mcl_core").."/schematics/mcl_core_oak_classic.mts",
		flags = "place_center_x, place_center_z",
		rotation = "random",
	})


	-- Rare balloon oak
	minetest.register_decoration({
		deco_type = "schematic",
		place_on = {"group:grass_block_no_snow", "mcl_core:dirt"},
		sidelen = 16,
		noise_params = {
			offset = 0.002083,
			scale = 0.0022,
			spread = {x = 250, y = 250, z = 250},
			seed = 3,
			octaves = 3,
			persist = 0.6,
		},
		biomes = {"Forest"},
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		schematic = minetest.get_modpath("mcl_core").."/schematics/mcl_core_oak_balloon.mts",
		flags = "place_center_x, place_center_z",
		rotation = "random",
	})
	-- Swamp oak
	minetest.register_decoration({
		deco_type = "schematic",
		place_on = {"group:grass_block_no_snow", "mcl_core:dirt"},
		sidelen = 80,
		noise_params = {
			offset = 0.0055,
			scale = 0.0011,
			spread = {x = 250, y = 250, z = 250},
			seed = 5005,
			octaves = 5,
			persist = 0.6,
		},
		biomes = {"Swampland", "Swampland_shore"},
		y_min = 0,
		y_max = mcl_vars.mg_overworld_max,
		schematic = minetest.get_modpath("mcl_core").."/schematics/mcl_core_oak_swamp.mts",
		flags = "place_center_x, place_center_z",
		rotation = "random",
	})

	-- Jungle tree

	-- Huge jungle tree (2 variants)
	for i=1, 2 do
		minetest.register_decoration({
			deco_type = "schematic",
			place_on = {"group:grass_block_no_snow", "mcl_core:dirt"},
			sidelen = 80,
			fill_ratio = 0.00125,
			biomes = {"Jungle"},
			y_min = 4,
			y_max = mcl_vars.mg_overworld_max,
			schematic = minetest.get_modpath("mcl_core").."/schematics/mcl_core_jungle_tree_huge_"..i..".mts",
			flags = "place_center_x, place_center_z",
			rotation = "random",
		})
		minetest.register_decoration({
			deco_type = "schematic",
			place_on = {"group:grass_block_no_snow", "mcl_core:dirt"},
			sidelen = 80,
			fill_ratio = 0.004,
			biomes = {"JungleM"},
			y_min = 4,
			y_max = mcl_vars.mg_overworld_max,
			schematic = minetest.get_modpath("mcl_core").."/schematics/mcl_core_jungle_tree_huge_"..i..".mts",
			flags = "place_center_x, place_center_z",
			rotation = "random",
		})
	end

	-- Common jungle tree
	minetest.register_decoration({
		deco_type = "schematic",
		place_on = {"group:grass_block_no_snow", "mcl_core:dirt"},
		sidelen = 80,
		fill_ratio = 0.045,
		biomes = {"Jungle"},
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		schematic = minetest.get_modpath("mcl_core").."/schematics/mcl_core_jungle_tree.mts",
		flags = "place_center_x, place_center_z",
		rotation = "random",
	})
	minetest.register_decoration({
		deco_type = "schematic",
		place_on = {"group:grass_block_no_snow", "mcl_core:dirt"},
		sidelen = 80,
		fill_ratio = 0.0045,
		biomes = {"JungleEdge", "JungleEdgeM"},
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		schematic = minetest.get_modpath("mcl_core").."/schematics/mcl_core_jungle_tree.mts",
		flags = "place_center_x, place_center_z",
		rotation = "random",
	})

	minetest.register_decoration({
		deco_type = "schematic",
		place_on = {"group:grass_block_no_snow", "mcl_core:dirt"},
		sidelen = 80,
		fill_ratio = 0.09,
		biomes = {"JungleM"},
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		schematic = minetest.get_modpath("mcl_core").."/schematics/mcl_core_jungle_tree.mts",
		flags = "place_center_x, place_center_z",
		rotation = "random",
	})

	-- Spruce
	local function quick_spruce(seed, offset, sprucename, biomes, y)
		if not y then
			y = 1
		end
		minetest.register_decoration({
			deco_type = "schematic",
			place_on = {"group:grass_block", "mcl_core:dirt", "mcl_core:podzol"},
			sidelen = 16,
			noise_params = {
				offset = offset,
				scale = 0.0006,
				spread = {x = 250, y = 250, z = 250},
				seed = seed,
				octaves = 3,
				persist = 0.66
			},
			biomes = biomes,
			y_min = y,
			y_max = mcl_vars.mg_overworld_max,
			schematic = minetest.get_modpath("mcl_core").."/schematics/"..sprucename,
			flags = "place_center_x, place_center_z",
		})
	end

	-- Huge spruce
	quick_spruce(3000, 0.005, "mcl_core_spruce_huge_1.mts", {"MegaSpruceTaiga"})
	quick_spruce(4000, 0.005, "mcl_core_spruce_huge_2.mts", {"MegaSpruceTaiga"})
	quick_spruce(6000, 0.005, "mcl_core_spruce_huge_3.mts", {"MegaSpruceTaiga"})

	quick_spruce(3000, 0.0008, "mcl_core_spruce_huge_up_1.mts", {"MegaTaiga"})
	quick_spruce(4000, 0.0008, "mcl_core_spruce_huge_up_2.mts", {"MegaTaiga"})
	quick_spruce(6000, 0.0008, "mcl_core_spruce_huge_up_3.mts", {"MegaTaiga"})


	-- Common spruce
	quick_spruce(11000, 0.00150, "mcl_core_spruce_5.mts", {"Taiga", "ColdTaiga"})

	quick_spruce(2500, 0.00325, "mcl_core_spruce_1.mts", {"MegaSpruceTaiga", "MegaTaiga", "Taiga", "ColdTaiga"})
	quick_spruce(7000, 0.00425, "mcl_core_spruce_3.mts", {"MegaSpruceTaiga", "MegaTaiga", "Taiga", "ColdTaiga"})
	quick_spruce(9000, 0.00325, "mcl_core_spruce_4.mts", {"MegaTaiga", "Taiga", "ColdTaiga"})

	quick_spruce(9500, 0.00500, "mcl_core_spruce_tall.mts", {"MegaTaiga"})

	quick_spruce(5000, 0.00250, "mcl_core_spruce_2.mts", {"MegaSpruceTaiga", "MegaTaiga"})

	quick_spruce(11000, 0.000025, "mcl_core_spruce_5.mts", {"ExtremeHills", "ExtremeHillsM"})
	quick_spruce(2500, 0.00005, "mcl_core_spruce_1.mts", {"ExtremeHills", "ExtremeHillsM"})
	quick_spruce(7000, 0.00005, "mcl_core_spruce_3.mts", {"ExtremeHills", "ExtremeHillsM"})
	quick_spruce(9000, 0.00005, "mcl_core_spruce_4.mts", {"ExtremeHills", "ExtremeHillsM"})

	quick_spruce(11000, 0.001, "mcl_core_spruce_5.mts", {"ExtremeHills+", "ExtremeHills+_snowtop"}, 50)
	quick_spruce(2500, 0.002, "mcl_core_spruce_1.mts", {"ExtremeHills+", "ExtremeHills+_snowtop"}, 50)
	quick_spruce(7000, 0.003, "mcl_core_spruce_3.mts", {"ExtremeHills+", "ExtremeHills+_snowtop"}, 50)
	quick_spruce(9000, 0.002, "mcl_core_spruce_4.mts", {"ExtremeHills+", "ExtremeHills+_snowtop"}, 50)


	-- Small lollipop spruce
	minetest.register_decoration({
		deco_type = "schematic",
		place_on = {"group:grass_block", "mcl_core:podzol"},
		sidelen = 16,
		noise_params = {
			offset = 0.004,
			scale = 0.0022,
			spread = {x = 250, y = 250, z = 250},
			seed = 2500,
			octaves = 3,
			persist = 0.66
		},
		biomes = {"Taiga", "ColdTaiga"},
		y_min = 2,
		y_max = mcl_vars.mg_overworld_max,
		schematic = minetest.get_modpath("mcl_core").."/schematics/mcl_core_spruce_lollipop.mts",
		flags = "place_center_x, place_center_z",
	})

	-- Matchstick spruce: Very few leaves, tall trunk
	minetest.register_decoration({
		deco_type = "schematic",
		place_on = {"group:grass_block", "mcl_core:podzol"},
		sidelen = 80,
		noise_params = {
			offset = -0.025,
			scale = 0.025,
			spread = {x = 250, y = 250, z = 250},
			seed = 2566,
			octaves = 5,
			persist = 0.60,
		},
		biomes = {"Taiga", "ColdTaiga"},
		y_min = 3,
		y_max = mcl_vars.mg_overworld_max,
		schematic = minetest.get_modpath("mcl_core").."/schematics/mcl_core_spruce_matchstick.mts",
		flags = "place_center_x, place_center_z",
	})

	-- Rare spruce in Ice Plains
	minetest.register_decoration({
		deco_type = "schematic",
		place_on = {"group:grass_block"},
		sidelen = 16,
		noise_params = {
			offset = -0.00075,
			scale = -0.0015,
			spread = {x = 250, y = 250, z = 250},
			seed = 11,
			octaves = 3,
			persist = 0.7
		},
		biomes = {"IcePlains"},
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		schematic = minetest.get_modpath("mcl_core").."/schematics/mcl_core_spruce_5.mts",
		flags = "place_center_x, place_center_z",
	})

	-- Acacia (many variants)
	for a=1, 7 do
		minetest.register_decoration({
			deco_type = "schematic",
			place_on = {"mcl_core:dirt_with_dry_grass", "mcl_core:dirt", "mcl_core:coarse_dirt"},
			sidelen = 16,
			fill_ratio = 0.0002,
			biomes = {"Savanna", "SavannaM"},
			y_min = 1,
			y_max = mcl_vars.mg_overworld_max,
			schematic = minetest.get_modpath("mcl_core").."/schematics/mcl_core_acacia_"..a..".mts",
			flags = "place_center_x, place_center_z",
			rotation = "random",
		})
	end

	-- Birch
	minetest.register_decoration({
		deco_type = "schematic",
		place_on = {"group:grass_block_no_snow"},
		sidelen = 16,
		noise_params = {
			offset = 0.03,
			scale = 0.0025,
			spread = {x = 250, y = 250, z = 250},
			seed = 11,
			octaves = 3,
			persist = 0.66
		},
		biomes = {"BirchForest"},
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		schematic = minetest.get_modpath("mcl_core").."/schematics/mcl_core_birch.mts",
		flags = "place_center_x, place_center_z",
	})
	minetest.register_decoration({
		deco_type = "schematic",
		place_on = {"group:grass_block_no_snow"},
		sidelen = 16,
		noise_params = {
			offset = 0.03,
			scale = 0.0025,
			spread = {x = 250, y = 250, z = 250},
			seed = 11,
			octaves = 3,
			persist = 0.66
		},
		biomes = {"BirchForestM"},
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		schematic = minetest.get_modpath("mcl_core").."/schematics/mcl_core_birch_tall.mts",
		flags = "place_center_x, place_center_z",
	})

	minetest.register_decoration({
		deco_type = "schematic",
		place_on = {"group:grass_block_no_snow", "mcl_core:dirt"},
		sidelen = 16,
		noise_params = {
			offset = 0.000333,
			scale = -0.0015,
			spread = {x = 250, y = 250, z = 250},
			seed = 11,
			octaves = 3,
			persist = 0.66
		},
		biomes = {"Forest", "FlowerForest"},
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		schematic = minetest.get_modpath("mcl_core").."/schematics/mcl_core_birch.mts",
		flags = "place_center_x, place_center_z",
	})

	-- Dark Oak
	minetest.register_decoration({
		deco_type = "schematic",
		place_on = {"group:grass_block_no_snow"},
		sidelen = 16,
		noise_params = {
			offset = 0.05,
			scale = 0.0015,
			spread = {x = 125, y = 125, z = 125},
			seed = 223,
			octaves = 3,
			persist = 0.66
		},
		biomes = {"RoofedForest"},
		y_min = 4,
		y_max = mcl_vars.mg_overworld_max,
		schematic = minetest.get_modpath("mcl_core").."/schematics/mcl_core_dark_oak.mts",
		flags = "place_center_x, place_center_z",
		rotation = "random",
	})


	local ratio_mushroom = 0.0001
	local ratio_mushroom_huge = ratio_mushroom * (11/12)
	local ratio_mushroom_giant = ratio_mushroom * (1/12)
	local ratio_mushroom_mycelium = 0.002
	local ratio_mushroom_mycelium_huge = ratio_mushroom_mycelium * (11/12)
	local ratio_mushroom_mycelium_giant = ratio_mushroom_mycelium * (1/12)

	-- Huge Brown Mushroom
	minetest.register_decoration({
		deco_type = "schematic",
		place_on = { "group:grass_block_no_snow", "mcl_core:dirt" },
		sidelen = 80,
		fill_ratio = ratio_mushroom_huge,
		biomes = { "RoofedForest" },
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		schematic = minetest.get_modpath("mcl_mushrooms").."/schematics/mcl_mushrooms_huge_brown.mts",
		flags = "place_center_x, place_center_z",
		rotation = "0",
	})
	minetest.register_decoration({
		deco_type = "schematic",
		place_on = { "group:grass_block_no_snow", "mcl_core:dirt" },
		sidelen = 80,
		fill_ratio = ratio_mushroom_giant,
		biomes = { "RoofedForest" },
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		schematic = minetest.get_modpath("mcl_mushrooms").."/schematics/mcl_mushrooms_giant_brown.mts",
		flags = "place_center_x, place_center_z",
		rotation = "0",
	})

	minetest.register_decoration({
		deco_type = "schematic",
		place_on = { "mcl_core:mycelium" },
		sidelen = 80,
		fill_ratio = ratio_mushroom_mycelium_huge,
		biomes = { "MushroomIsland", "MushroomIslandShore" },
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		schematic = minetest.get_modpath("mcl_mushrooms").."/schematics/mcl_mushrooms_huge_brown.mts",
		flags = "place_center_x, place_center_z",
		rotation = "0",
	})
	minetest.register_decoration({
		deco_type = "schematic",
		place_on = { "mcl_core:mycelium" },
		sidelen = 80,
		fill_ratio = ratio_mushroom_mycelium_giant,
		biomes = { "MushroomIsland", "MushroomIslandShore" },
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		schematic = minetest.get_modpath("mcl_mushrooms").."/schematics/mcl_mushrooms_giant_brown.mts",
		flags = "place_center_x, place_center_z",
		rotation = "0",
	})

	-- Huge Red Mushroom
	minetest.register_decoration({
		deco_type = "schematic",
		place_on = { "group:grass_block_no_snow", "mcl_core:dirt" },
		sidelen = 80,
		fill_ratio = ratio_mushroom_huge,
		biomes = { "RoofedForest" },
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		schematic = minetest.get_modpath("mcl_mushrooms").."/schematics/mcl_mushrooms_huge_red.mts",
		flags = "place_center_x, place_center_z",
		rotation = "0",
	})
	minetest.register_decoration({
		deco_type = "schematic",
		place_on = { "group:grass_block_no_snow", "mcl_core:dirt" },
		sidelen = 80,
		fill_ratio = ratio_mushroom_giant,
		biomes = { "RoofedForest" },
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		schematic = minetest.get_modpath("mcl_mushrooms").."/schematics/mcl_mushrooms_giant_red.mts",
		flags = "place_center_x, place_center_z",
		rotation = "0",
	})

	minetest.register_decoration({
		deco_type = "schematic",
		place_on = { "mcl_core:mycelium" },
		sidelen = 80,
		fill_ratio = ratio_mushroom_mycelium_huge,
		biomes = { "MushroomIsland", "MushroomIslandShore" },
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		schematic = minetest.get_modpath("mcl_mushrooms").."/schematics/mcl_mushrooms_huge_red.mts",
		flags = "place_center_x, place_center_z",
		rotation = "0",
	})
	minetest.register_decoration({
		deco_type = "schematic",
		place_on = { "mcl_core:mycelium" },
		sidelen = 80,
		fill_ratio = ratio_mushroom_mycelium_giant,
		biomes = { "MushroomIsland", "MushroomIslandShore" },
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		schematic = minetest.get_modpath("mcl_mushrooms").."/schematics/mcl_mushrooms_giant_red.mts",
		flags = "place_center_x, place_center_z",
		rotation = "0",
	})

	-- Moss stone boulder (3×3)
	minetest.register_decoration({
		deco_type = "schematic",
		place_on = {"mcl_core:podzol", "mcl_core:dirt", "mcl_core:coarse_dirt"},
		sidelen = 80,
		noise_params = {
			offset = 0.00015,
			scale = 0.001,
			spread = {x = 300, y = 300, z = 300},
			seed = 775703,
			octaves = 4,
			persist = 0.63,
		},
		biomes = {"MegaTaiga", "MegaSpruceTaiga"},
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		schematic = minetest.get_modpath("mcl_structures").."/schematics/mcl_structures_boulder.mts",
		flags = "place_center_x, place_center_z",
	})

	-- Small moss stone boulder (2×2)
	minetest.register_decoration({
		deco_type = "schematic",
		place_on = {"mcl_core:podzol", "mcl_core:dirt", "mcl_core:coarse_dirt"},
		sidelen = 80,
		noise_params = {
			offset = 0.001,
			scale = 0.001,
			spread = {x = 300, y = 300, z = 300},
			seed = 775703,
			octaves = 4,
			persist = 0.63,
		},
		biomes = {"MegaTaiga", "MegaSpruceTaiga"},
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		schematic = minetest.get_modpath("mcl_structures").."/schematics/mcl_structures_boulder_small.mts",
		flags = "place_center_x, place_center_z",
	})

	-- 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",
		biomes = {"Desert","Mesa","Mesa_sandlevel","MesaPlateauF","MesaPlateauF_sandlevel"},
		height = 1,
		height_max = 3,
	})

	-- Sugar canes
	minetest.register_decoration({
		deco_type = "simple",
		place_on = {"mcl_core:dirt", "mcl_core:coarse_dirt", "group:grass_block_no_snow", "group:sand", "mcl_core:podzol", "mcl_core:reeds"},
		sidelen = 16,
		noise_params = {
			offset = -0.3,
			scale = 0.7,
			spread = {x = 200, y = 200, z = 200},
			seed = 2,
			octaves = 3,
			persist = 0.7
		},
		y_min = 1,
		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,
	})
	minetest.register_decoration({
		deco_type = "simple",
		place_on = {"mcl_core:dirt", "mcl_core:coarse_dirt", "group:grass_block_no_snow", "group:sand", "mcl_core:podzol", "mcl_core:reeds"},
		sidelen = 16,
		noise_params = {
			offset = 0.0,
			scale = 0.5,
			spread = {x = 200, y = 200, z = 200},
			seed = 2,
			octaves = 3,
			persist = 0.7,
		},
		biomes = {"Swampland", "Swampland_shore"},
		y_min = 1,
		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,
	})

	local dry_index = minetest.registered_nodes["mcl_core:dirt_with_dry_grass"]._mcl_grass_palette_index

	-- Doubletall grass
	local register_doubletall_grass = function(offset, scale, biomes, param2)

		minetest.register_decoration({
			deco_type = "schematic",
			schematic = {
				size = { x=1, y=3, z=1 },
				data = {
					{ name = "air", prob = 0 },
					{ name = "mcl_flowers:double_grass", param1=255, param2=param2 },
					{ name = "mcl_flowers:double_grass_top", param1=255, param2=param2 },
				},
			},
			replacements = {
				["mcl_flowers:tallgrass"] = "mcl_flowers:double_grass",
			},
			place_on = {"group:grass_block_no_snow"},
			sidelen = 16,
			noise_params = {
				offset = offset,
				scale = scale,
				spread = {x = 200, y = 200, z = 200},
				seed = 420,
				octaves = 3,
				persist = 0.6,
			},
			y_min = 1,
			y_max = mcl_vars.mg_overworld_max,
			biomes = biomes,
		})
	end

	register_doubletall_grass(-0.01, 0.03, {"Taiga", "Forest", "FlowerForest", "BirchForest", "BirchForestM", "RoofedForest"})
	register_doubletall_grass(-0.002, 0.03, {"Plains", "SunflowerPlains"})
	register_doubletall_grass(-0.0005, -0.03, {"Savanna", "SavannaM"}, dry_index)

	-- Large ferns
	local register_double_fern = function(offset, scale, biomes)
		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"
			},
			place_on = {"group:grass_block_no_snow", "mcl_core:podzol"},
			sidelen = 16,
			noise_params = {
				offset = offset,
				scale = scale,
				spread = {x = 250, y = 250, z = 250},
				seed = 333,
				octaves = 2,
				persist = 0.66,
			},
			biomes = biomes,
			y_min = 1,
			y_max = mcl_vars.mg_overworld_max,
		})
	end

	register_double_fern(0.01, 0.03, { "Jungle", "JungleM", "JungleEdge", "JungleEdgeM", "Taiga", "ColdTaiga", "MegaTaiga", "MegaSpruceTaiga" })
	register_double_fern(0.15, 0.1, { "JungleM" })

	-- Large flowers
	local register_large_flower = function(name, biomes, seed, offset, flower_forest_offset)
		local maxi
		if flower_forest_offset then
			maxi = 2
		else
			maxi = 1
		end
		for i=1, maxi do
			local o, b -- offset, biomes
			if i == 1 then
				o = offset
				b = biomes
			else
				o = flower_forest_offset
				b = { "FlowerForest" }
			end

			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 = {"group:grass_block_no_snow", "mcl_core:dirt"},

				sidelen = 16,
				noise_params = {
					offset = o,
					scale = 0.01,
					spread = {x = 300, y = 300, z = 300},
					seed = seed,
					octaves = 5,
					persist = 0.62,
				},
				y_min = 1,
				y_max = mcl_vars.mg_overworld_max,
				flags = "",
				biomes = b,
			})
		end
	end

	register_large_flower("rose_bush", {"Forest"}, 9350, -0.008, 0.003)
	register_large_flower("peony", {"Forest"}, 10450, -0.008, 0.003)
	register_large_flower("lilac", {"Forest"}, 10600, -0.007, 0.003)
	register_large_flower("sunflower", {"SunflowerPlains"}, 2940, 0.01)

	-- Jungle bush

	minetest.register_decoration({
		deco_type = "schematic",
		place_on = {"group:grass_block_no_snow", "mcl_core:dirt"},
		sidelen = 80,
		noise_params = {
			offset = 0.0196,
			scale = 0.025,
			spread = {x = 250, y = 250, z = 250},
			seed = 2930,
			octaves = 4,
			persist = 0.6,
		},
		biomes = {"Jungle"},
		y_min = 3,
		y_max = mcl_vars.mg_overworld_max,
		schematic = jungle_bush_schematic,
		flags = "place_center_x, place_center_z",
	})
	minetest.register_decoration({
		deco_type = "schematic",
		place_on = {"group:grass_block_no_snow", "mcl_core:dirt"},
		sidelen = 80,
		noise_params = {
			offset = 0.05,
			scale = 0.025,
			spread = {x = 250, y = 250, z = 250},
			seed = 2930,
			octaves = 4,
			persist = 0.6,
		},
		biomes = {"JungleM"},
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		schematic = jungle_bush_schematic,
		flags = "place_center_x, place_center_z",
	})
	minetest.register_decoration({
		deco_type = "schematic",
		place_on = {"group:grass_block_no_snow", "mcl_core:dirt"},
		sidelen = 80,
		noise_params = {
			offset = 0.0085,
			scale = 0.025,
			spread = {x = 250, y = 250, z = 250},
			seed = 2930,
			octaves = 4,
			persist = 0.6,
		},
		biomes = {"JungleEdge", "JungleEdgeM"},
		y_min = 3,
		y_max = mcl_vars.mg_overworld_max,
		schematic = jungle_bush_schematic,
		flags = "place_center_x, place_center_z",
	})

	-- Fallen logs
	-- These fallen logs are not really good yet. They must be longer and also have one upright block.
	-- Note the decortion API does not like wide schematics, they are likely to overhang.
	if generate_fallen_logs then
		minetest.register_decoration({
			deco_type = "schematic",
			place_on = {"group:grass_block_no_snow", "mcl_core:podzol", "mcl_core:coarse_dirt"},
			sidelen = 80,
			noise_params = {
				offset = 0.00018,
				scale = 0.00011,
				spread = {x = 250, y = 250, z = 250},
				seed = 2,
				octaves = 3,
				persist = 0.66
			},
			biomes = {"MegaTaiga", "MegaSpruceTaiga", "Taiga"},
			y_min = 1,
			y_max = mcl_vars.mg_overworld_max,
			schematic = {
				size = {x = 3, y = 3, z = 1},
				data = {
					{name = "air", prob = 0},
					{name = "air", prob = 0},
					{name = "air", prob = 0},
					{name = "mcl_core:sprucetree", param2 = 12, prob = 127},
					{name = "mcl_core:sprucetree", param2 = 12},
					{name = "mcl_core:sprucetree", param2 = 12},
					{name = "air", prob = 0},
					{name = "mcl_mushrooms:mushroom_brown", prob = 160},
					{name = "mcl_mushrooms:mushroom_red", prob = 160},
				},
			},
			flags = "place_center_x",
			rotation = "random",
		})

		minetest.register_decoration({
			deco_type = "schematic",
			place_on = {"group:grass_block", "mcl_core:podzol", "mcl_core:podzol_snow", "mcl_core:coarse_dirt"},
			sidelen = 80,
			noise_params = {
				offset = 0.00018,
				scale = 0.00011,
				spread = {x = 250, y = 250, z = 250},
				seed = 2,
				octaves = 3,
				persist = 0.66
			},
			biomes = {"ColdTaiga"},
			y_min = 1,
			y_max = mcl_vars.mg_overworld_max,
			schematic = {
				size = {x = 3, y = 3, z = 1},
				data = {
					{name = "air", prob = 0},
					{name = "air", prob = 0},
					{name = "air", prob = 0},
					{name = "mcl_core:sprucetree", param2 = 12, prob = 127},
					{name = "mcl_core:sprucetree", param2 = 12},
					{name = "mcl_core:sprucetree", param2 = 12},
					{name = "air", prob = 0},
					{name = "air", prob = 0},
					{name = "air", prob = 0},
				},
			},
			flags = "place_center_x",
			rotation = "random",
		})

		minetest.register_decoration({
			deco_type = "schematic",
			place_on = {"group:grass_block_no_snow"},
			sidelen = 16,
			noise_params = {
				offset = 0.0,
				scale = -0.00008,
				spread = {x = 250, y = 250, z = 250},
				seed = 2,
				octaves = 3,
				persist = 0.66
			},
			biomes = {"BirchForest", "BirchForestM",},
			y_min = 1,
			y_max = mcl_vars.mg_overworld_max,
			schematic = {
				size = {x = 3, y = 3, z = 1},
				data = {
					{name = "air", prob = 0},
					{name = "air", prob = 0},
					{name = "air", prob = 0},
					{name = "mcl_core:birchtree", param2 = 12},
					{name = "mcl_core:birchtree", param2 = 12},
					{name = "mcl_core:birchtree", param2 = 12, prob = 127},
					{name = "mcl_mushrooms:mushroom_red", prob = 100},
					{name = "mcl_mushrooms:mushroom_brown", prob = 10},
					{name = "air", prob = 0},
				},
			},
			flags = "place_center_x",
			rotation = "random",
		})

		minetest.register_decoration({
			deco_type = "schematic",
			place_on = {"group:grass_block_no_snow", "mcl_core:dirt"},
			sidelen = 80,
			fill_ratio = 0.005,
			biomes = {"Jungle", "JungleM"},
			y_min = 1,
			y_max = mcl_vars.mg_overworld_max,
			schematic = {
				size = {x = 3, y = 3, z = 1},
				data = {
					{name = "air", prob = 0},
					{name = "air", prob = 0},
					{name = "air", prob = 0},
					{name = "mcl_core:jungletree", param2 = 12},
					{name = "mcl_core:jungletree", param2 = 12},
					{name = "mcl_core:jungletree", param2 = 12, prob = 127},
					{name = "air", prob = 0},
					{name = "mcl_mushrooms:mushroom_brown", prob = 50},
					{name = "air", prob = 0},
				},
			},
			flags = "place_center_x",
			rotation = "random",
		})

		minetest.register_decoration({
			deco_type = "schematic",
			place_on = {"group:grass_block_no_snow"},
			sidelen = 16,
			noise_params = {
				offset = 0.00018,
				scale = 0.00011,
				spread = {x = 250, y = 250, z = 250},
				seed = 2,
				octaves = 3,
				persist = 0.66
			},
			biomes = {"Forest"},
			y_min = 1,
			y_max = mcl_vars.mg_overworld_max,
			schematic = {
				size = {x = 3, y = 3, z = 1},
				data = {
					{name = "air", prob = 0},
					{name = "air", prob = 0},
					{name = "air", prob = 0},
					{name = "mcl_core:tree", param2 = 12, prob = 127},
					{name = "mcl_core:tree", param2 = 12},
					{name = "mcl_core:tree", param2 = 12},
					{name = "air", prob = 0},
					{name = "mcl_mushrooms:mushroom_brown", prob = 96},
					{name = "mcl_mushrooms:mushroom_red", prob = 96},
				},
			},
			flags = "place_center_x",
			rotation = "random",
		})
	end

	-- Lily pad

	local lily_schem = {
		{ name = "mcl_core:water_source" },
		{ name = "mcl_flowers:waterlily" },
	}

	-- Spawn them in shallow water at ocean level in Swampland.
	-- Tweak lilydepth to change the maximum water depth
	local lilydepth = 2

	for d=1, lilydepth do
		local height = d + 2
		local y = 1 - d
		table.insert(lily_schem, 1, { name = "air", prob = 0 })

		minetest.register_decoration({
			deco_type = "schematic",
			schematic = {
				size = { x=1, y=height, z=1 },
				data = lily_schem,
			},
			place_on = "mcl_core:dirt",
			sidelen = 16,
			noise_params = {
				offset = 0,
				scale = 0.3,
				spread = {x = 100, y = 100, z = 100},
				seed = 503,
				octaves = 6,
				persist = 0.7,
			},
			y_min = y,
			y_max = y,
			biomes = { "Swampland_shore" },
			rotation = "random",
		})
	end

	-- Melon
	minetest.register_decoration({
		deco_type = "simple",
		place_on = {"group:grass_block_no_snow"},
		sidelen = 16,
		noise_params = {
			offset = -0.01,
			scale = 0.006,
			spread = {x = 250, y = 250, z = 250},
			seed = 333,
			octaves = 3,
			persist = 0.6
		},
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		decoration = "mcl_farming:melon",
		biomes = { "Jungle" },
	})
	minetest.register_decoration({
		deco_type = "simple",
		place_on = {"group:grass_block_no_snow"},
		sidelen = 16,
		noise_params = {
			offset = 0.0,
			scale = 0.006,
			spread = {x = 250, y = 250, z = 250},
			seed = 333,
			octaves = 3,
			persist = 0.6
		},
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		decoration = "mcl_farming:melon",
		biomes = { "JungleM" },
	})
	minetest.register_decoration({
		deco_type = "simple",
		place_on = {"group:grass_block_no_snow"},
		sidelen = 16,
		noise_params = {
			offset = -0.005,
			scale = 0.006,
			spread = {x = 250, y = 250, z = 250},
			seed = 333,
			octaves = 3,
			persist = 0.6
		},
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		decoration = "mcl_farming:melon",
		biomes = { "JungleEdge", "JungleEdgeM" },
	})

	-- Lots of melons in Jungle Edge M
	minetest.register_decoration({
		deco_type = "simple",
		place_on = {"group:grass_block_no_snow"},
		sidelen = 80,
		noise_params = {
			offset = 0.013,
			scale = 0.006,
			spread = {x = 125, y = 125, z = 125},
			seed = 333,
			octaves = 3,
			persist = 0.6
		},
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		decoration = "mcl_farming:melon",
		biomes = { "JungleEdgeM" },
	})

	-- Pumpkin
	minetest.register_decoration({
		deco_type = "schematic",
		schematic = {
			size = { x=1, y=2, z=1 },
			data = {
				{ name = "air", prob = 0 },
				{ name = "mcl_farming:pumpkin_face", param1=255, },
			},
		},
		place_on = {"group:grass_block_no_snow"},
		sidelen = 16,
		noise_params = {
			offset = -0.016,
			scale = 0.01332,
			spread = {x = 125, y = 125, z = 125},
			seed = 666,
			octaves = 6,
			persist = 0.666
		},
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		rotation = "random",
	})

	-- Grasses and ferns
	local grass_forest = {"Plains", "Taiga", "Forest", "FlowerForest", "BirchForest", "BirchForestM", "RoofedForest", "Swampland", }
	local grass_mpf = {"MesaPlateauF_grasstop"}
	local grass_plains = {"Plains", "SunflowerPlains", "JungleEdge", "JungleEdgeM" }
	local grass_savanna = {"Savanna", "SavannaM"}
	local grass_sparse = {"ExtremeHills", "ExtremeHills+", "ExtremeHills+_snowtop", "ExtremeHillsM", "Jungle", }

	register_grass_decoration("tallgrass", -0.03,  0.09, grass_forest)
	register_grass_decoration("tallgrass", -0.015, 0.075, grass_forest)
	register_grass_decoration("tallgrass", 0,      0.06, grass_forest)
	register_grass_decoration("tallgrass", 0.015,  0.045, grass_forest)
	register_grass_decoration("tallgrass", 0.03,   0.03, grass_forest)
	register_grass_decoration("tallgrass", -0.03, 0.09, grass_mpf, dry_index)
	register_grass_decoration("tallgrass", -0.015, 0.075, grass_mpf, dry_index)
	register_grass_decoration("tallgrass", 0, 0.06, grass_mpf, dry_index)
	register_grass_decoration("tallgrass", 0.01, 0.045, grass_mpf, dry_index)
	register_grass_decoration("tallgrass", 0.01, 0.05, grass_forest)
	register_grass_decoration("tallgrass", 0.03, 0.03, grass_plains)
	register_grass_decoration("tallgrass", 0.05, 0.01, grass_plains)
	register_grass_decoration("tallgrass", 0.07, -0.01, grass_plains)
	register_grass_decoration("tallgrass", 0.09, -0.03, grass_plains)
	register_grass_decoration("tallgrass", 0.18, -0.03, grass_savanna, dry_index)
	register_grass_decoration("tallgrass", 0.05, -0.03, grass_sparse)

	local fern_minimal = { "Jungle", "JungleM", "JungleEdge", "JungleEdgeM", "Taiga", "MegaTaiga", "MegaSpruceTaiga", "ColdTaiga" }
	local fern_low = { "Jungle", "JungleM", "JungleEdge", "JungleEdgeM", "Taiga", "MegaTaiga", "MegaSpruceTaiga" }
	local fern_Jungle = { "Jungle", "JungleM", "JungleEdge", "JungleEdgeM" }
	local fern_JungleM = { "JungleM" },
	register_grass_decoration("fern", -0.03,  0.09, fern_minimal)
	register_grass_decoration("fern", -0.015, 0.075, fern_minimal)
	register_grass_decoration("fern", 0,      0.06, fern_minimal)
	register_grass_decoration("fern", 0.015,  0.045, fern_low)
	register_grass_decoration("fern", 0.03,   0.03, fern_low)
	register_grass_decoration("fern", 0.01, 0.05, fern_Jungle)
	register_grass_decoration("fern", 0.03, 0.03, fern_Jungle)
	register_grass_decoration("fern", 0.05, 0.01, fern_Jungle)
	register_grass_decoration("fern", 0.07, -0.01, fern_Jungle)
	register_grass_decoration("fern", 0.09, -0.03, fern_Jungle)
	register_grass_decoration("fern", 0.12, -0.03, fern_JungleM)

	-- Place tall grass on snow in Ice Plains and Extreme Hills+
	minetest.register_decoration({
		deco_type = "schematic",
		place_on = {"group:grass_block"},
		sidelen = 16,
		noise_params = {
			offset = -0.08,
			scale = 0.09,
			spread = {x = 15, y = 15, z = 15},
			seed = 420,
			octaves = 3,
			persist = 0.6,
		},
		biomes = {"IcePlains"},
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		schematic = {
			size = { x=1, y=2, z=1 },
			data = {
				{ name = "mcl_core:dirt_with_grass", force_place=true, },
				{ name = "mcl_flowers:tallgrass", },
			},
		},
	})
	minetest.register_decoration({
		deco_type = "schematic",
		place_on = {"group:grass_block"},
		sidelen = 16,
		noise_params = {
			offset = 0.0,
			scale = 0.09,
			spread = {x = 15, y = 15, z = 15},
			seed = 420,
			octaves = 3,
			persist = 0.6,
		},
		biomes = {"ExtremeHills+_snowtop"},
		y_min = 1,
		y_max = mcl_vars.mg_overworld_max,
		schematic = {
			size = { x=1, y=2, z=1 },
			data = {
				{ name = "mcl_core:dirt_with_grass", force_place=true, },
				{ name = "mcl_flowers:tallgrass", },
			},
		},
	})


	-- Dead bushes
	minetest.register_decoration({
		deco_type = "simple",
		place_on = {"group:sand", "mcl_core:podzol", "mcl_core:dirt", "mcl_core:dirt_with_dry_grass", "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,
		biomes = {"Desert", "Mesa", "Mesa_sandlevel", "MesaPlateauF", "MesaPlateauF_sandlevel", "MesaPlateauF_grasstop", "Taiga", "MegaTaiga"},
		decoration = "mcl_core:deadbush",
		height = 1,
	})

	-- Mushrooms in mushroom biome
	minetest.register_decoration({
		deco_type = "simple",
		place_on = {"mcl_core:mycelium"},
		sidelen = 80,
		fill_ratio = 0.009,
		biomes = {"MushroomIsland", "MushroomIslandShore"},
		noise_threshold = 2.0,
		y_min = mcl_vars.mg_overworld_min,
		y_max = mcl_vars.mg_overworld_max,
		decoration = "mcl_mushrooms:mushroom_red",
	})
	minetest.register_decoration({
		deco_type = "simple",
		place_on = {"mcl_core:mycelium"},
		sidelen = 80,
		fill_ratio = 0.009,
		biomes = {"MushroomIsland", "MushroomIslandShore"},
		y_min = mcl_vars.mg_overworld_min,
		y_max = mcl_vars.mg_overworld_max,
		decoration = "mcl_mushrooms:mushroom_brown",
	})

	-- Mushrooms in Taiga
	minetest.register_decoration({
		deco_type = "simple",
		place_on = {"mcl_core:podzol"},
		sidelen = 80,
		fill_ratio = 0.003,
		biomes = {"Taiga", "MegaTaiga", "MegaSpruceTaiga"},
		y_min = mcl_vars.mg_overworld_min,
		y_max = mcl_vars.mg_overworld_max,
		decoration = "mcl_mushrooms:mushroom_red",
	})
	minetest.register_decoration({
		deco_type = "simple",
		place_on = {"mcl_core:podzol"},
		sidelen = 80,
		fill_ratio = 0.003,
		biomes = {"Taiga", "MegaTaiga", "MegaSpruceTaiga"},
		y_min = mcl_vars.mg_overworld_min,
		y_max = mcl_vars.mg_overworld_max,
		decoration = "mcl_mushrooms:mushroom_brown",
	})


	-- Mushrooms next to trees
	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 = {"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"},
			sidelen = 16,
			noise_params = {
				offset = 0,
				scale = 0.003,
				spread = {x = 250, y = 250, z = 250},
				seed = mseeds[m],
				octaves = 3,
				persist = 0.66,
			},
			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,
		})

		-- More mushrooms in Swampland
		minetest.register_decoration({
			deco_type = "simple",
			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"},
			sidelen = 16,
			noise_params = {
				offset = 0.05,
				scale = 0.003,
				spread = {x = 250, y = 250, z = 250},
				seed = mseeds[m],
				octaves = 3,
				persist = 0.6,
			},
			y_min = 1,
			y_max = mcl_vars.mg_overworld_max,
			decoration = mushrooms[m],
			biomes = { "Swampland"},
			spawn_by = { "mcl_core:tree", "mcl_core:sprucetree", "mcl_core:darktree", "mcl_core:birchtree" },
			num_spawn_by = 1,
		})
	end
	local function register_flower(name, biomes, seed, is_in_flower_forest)
		if is_in_flower_forest == nil then
			is_in_flower_forest = true
		end
		if biomes then
			minetest.register_decoration({
				deco_type = "simple",
				place_on = {"group:grass_block_no_snow", "mcl_core:dirt"},
				sidelen = 16,
				noise_params = {
					offset = 0.0008,
					scale = 0.006,
					spread = {x = 100, y = 100, z = 100},
					seed = seed,
					octaves = 3,
					persist = 0.6
				},
				y_min = 1,
				y_max = mcl_vars.mg_overworld_max,
				biomes = biomes,
				decoration = "mcl_flowers:"..name,
			})
		end
		if is_in_flower_forest then
			minetest.register_decoration({
				deco_type = "simple",
				place_on = {"group:grass_block_no_snow", "mcl_core:dirt"},
				sidelen = 80,
				noise_params= {
					offset = 0.0008*40,
					scale = 0.003,
					spread = {x = 100, y = 100, z = 100},
					seed = seed,
					octaves = 3,
					persist = 0.6,
				},
				y_min = 1,
				y_max = mcl_vars.mg_overworld_max,
				biomes = {"FlowerForest"},
				decoration = "mcl_flowers:"..name,
			})
		end
	end

	local flower_biomes1 = {"Plains", "SunflowerPlains", "RoofedForest", "Forest", "BirchForest", "BirchForestM", "Taiga", "ColdTaiga", "Jungle", "JungleM", "JungleEdge", "JungleEdgeM", "Savanna", "SavannaM", "ExtremeHills", "ExtremeHillsM", "ExtremeHills+", "ExtremeHills+_snowtop" }

	register_flower("dandelion", flower_biomes1, 8)
	register_flower("poppy", flower_biomes1, 9439)

	local flower_biomes2 = {"Plains", "SunflowerPlains"}
	register_flower("tulip_red", flower_biomes2, 436)
	register_flower("tulip_orange", flower_biomes2, 536)
	register_flower("tulip_pink", flower_biomes2, 636)
	register_flower("tulip_white", flower_biomes2, 736)
	register_flower("azure_bluet", flower_biomes2, 800)
	register_flower("oxeye_daisy", flower_biomes2, 3490)

	register_flower("allium", nil, 0) -- flower Forest only
	register_flower("blue_orchid", {"Swampland"}, 64500, false)

end

-- Decorations in non-Overworld dimensions
local function register_dimension_decorations()
	-- TODO
end


--
-- Detect mapgen to select functions
--
if mg_name ~= "singlenode" then
	if mg_name ~= "flat" then
		if mg_name ~= "v6" then
			register_biomes()
			register_biomelike_ores()
		end
		register_biome_ores()
		if mg_name ~= "v6" then
			register_decorations()
		end
	else
		-- Implementation of Minecraft's Superflat mapgen, classic style
		minetest.clear_registered_biomes()
		minetest.clear_registered_decorations()
		minetest.clear_registered_schematics()
		register_classic_superflat_biome()
	end

	-- Non-overworld stuff is registered independently
	register_dimension_biomes()
	register_dimension_ores()
	register_dimension_decorations()

	-- Overworld decorations for v6 are handled in mcl_mapgen_core
end