local mg_seed = mcl_mapgen.seed

-- Some mapgen settings
local superflat = mcl_mapgen.superflat

local generate_fallen_logs = minetest.settings:get_bool("mcl_generate_fallen_logs", false)

local mod_mcl_structures = minetest.get_modpath("mcl_structures")
local mod_mcl_core = minetest.get_modpath("mcl_core")
local mod_mcl_mushrooms = minetest.get_modpath("mcl_mushrooms")

-- Jungle bush schematic. In PC/Java Edition it's Jungle Wood + Oak Leaves
local jungle_bush_schematic = mod_mcl_core.."/schematics/mcl_core_jungle_bush_oak_leaves.mts"

local deco_id_chorus_plant

--
-- Register biomes
--

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

local minetest_get_perlin = minetest.get_perlin
local math_floor = math.floor
local math_abs = math.abs

--[[ Special biome field: _mcl_biome_type:
Rough categorization of biomes: One of "snowy", "cold", "medium" and "hot"
Based off <https://minecraft.gamepedia.com/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_mapgen.overworld.min - 512,
		y_max = mcl_mapgen.overworld.max,
		humidity_point = 50,
		heat_point = 50,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 0,
	})
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, as of Minecraft 1.11 (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)
	* Hills biomes (shape only)
	* Plateau (shape only)
	* Plateau M (shape only)
	* Cold Taiga M (mountain only)
	* Taiga M (mountain only)
	* Roofed Forest M (mountain only)
	* Swampland M (mountain only)
	* Extreme Hills Edge (unused in MC)

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

	]]

	-- 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",
		"MesaBryce",
		"MesaPlateauF",
		"MesaPlateauFM",
	}

	-- 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_water_top = "mcl_core:ice",
		depth_water_top = 1,
		node_river_water = "mcl_core:ice",
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = 1,
		y_max = mcl_mapgen.overworld.max,
		humidity_point = 24,
		heat_point = -5,
		_mcl_biome_type = "snowy",
		_mcl_palette_index = 2,
	})
	minetest.register_biome({
		name = "IcePlainsSpikes_ocean",
		node_top = "mcl_core:gravel",
		depth_top = 2,
		node_filler = "mcl_core:gravel",
		depth_filler = 3,
		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,
		_mcl_biome_type = "snowy",
		_mcl_palette_index = 2,
	})

	-- 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_mapgen.overworld.max,
		humidity_point = 58,
		heat_point = 8,
		_mcl_biome_type = "snowy",
		_mcl_palette_index = 3,
	})

	-- 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,
		_mcl_biome_type = "snowy",
		_mcl_palette_index = 3,
	})
	-- 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 = -4,
		y_max = 0,
		humidity_point = 58,
		heat_point = 8,
		_mcl_biome_type = "snowy",
		_mcl_palette_index = 3,
	})
	minetest.register_biome({
		name = "ColdTaiga_ocean",
		node_top = "mcl_core:gravel",
		depth_top = 1,
		node_filler = "mcl_core:gravel",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = -5,
		humidity_point = 58,
		heat_point = 8,
		vertical_blend = 1,
		_mcl_biome_type = "snowy",
		_mcl_palette_index = 3,
	})

	-- 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_mapgen.overworld.max,
		humidity_point = 76,
		heat_point = 10,
		_mcl_biome_type = "cold",
		_mcl_palette_index = 4,
	})
	minetest.register_biome({
		name = "MegaTaiga_ocean",
		node_top = "mcl_core:gravel",
		depth_top = 1,
		node_filler = "mcl_core:gravel",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = 0,
		humidity_point = 76,
		heat_point = 10,
		_mcl_biome_type = "cold",
		_mcl_palette_index = 4,
	})

	-- 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_mapgen.overworld.max,
		humidity_point = 100,
		heat_point = 8,
		_mcl_biome_type = "cold",
		_mcl_palette_index = 5,
	})
	minetest.register_biome({
		name = "MegaSpruceTaiga_ocean",
		node_top = "mcl_core:gravel",
		depth_top = 1,
		node_filler = "mcl_core:gravel",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = 0,
		humidity_point = 100,
		heat_point = 8,
		_mcl_biome_type = "cold",
		_mcl_palette_index = 5,
	})

	-- Extreme Hills
	-- Sparsely populated grasslands with little tallgras and trees.
	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_mapgen.overworld.max,
		humidity_point = 10,
		heat_point = 45,
		_mcl_biome_type = "cold",
		_mcl_palette_index = 6,
	})
	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 = -4,
		y_max = 3,
		humidity_point = 10,
		heat_point = 45,
		_mcl_biome_type = "cold",
		_mcl_palette_index = 6,
	})
	minetest.register_biome({
		name = "ExtremeHills_ocean",
		node_top = "mcl_core:gravel",
		depth_top = 1,
		node_filler = "mcl_core:gravel",
		depth_filler = 4,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 4,
		y_min = OCEAN_MIN,
		y_max = -5,
		vertical_blend = 1,
		humidity_point = 10,
		heat_point = 45,
		_mcl_biome_type = "cold",
		_mcl_palette_index = 6,
	})

	-- Extreme Hills M
	-- Just gravel.
	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_mapgen.overworld.max,
		humidity_point = 0,
		heat_point = 25,
		_mcl_biome_type = "cold",
		_mcl_palette_index = 7,
	})
	minetest.register_biome({
		name = "ExtremeHillsM_ocean",
		node_top = "mcl_core:gravel",
		depth_top = 1,
		node_filler = "mcl_core:gravel",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 3,
		y_min = OCEAN_MIN,
		y_max = 0,
		humidity_point = 0,
		heat_point = 25,
		_mcl_biome_type = "cold",
		_mcl_palette_index = 7,
	})

	-- Extreme Hills+
	-- This biome is near-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 = 41,
		humidity_point = 24,
		heat_point = 25,
		vertical_blend = 6,
		_mcl_biome_type = "cold",
		_mcl_palette_index = 8,
	})
	---- 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 = 42,
		y_max = mcl_mapgen.overworld.max,
		humidity_point = 24,
		heat_point = 25,
		_mcl_biome_type = "cold",
		_mcl_palette_index = 8,
	})
	minetest.register_biome({
		name = "ExtremeHills+_ocean",
		node_top = "mcl_core:gravel",
		depth_top = 1,
		node_filler = "mcl_core:gravel",
		depth_filler = 4,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 4,
		y_min = OCEAN_MIN,
		y_max = 0,
		humidity_point = 24,
		heat_point = 25,
		_mcl_biome_type = "cold",
		_mcl_palette_index = 8,
	})

	-- Stone beach
	-- Just stone.
	-- Not neccessarily a beach at all, only named so according to MC
	minetest.register_biome({
		name = "StoneBeach",
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 1,
		y_min = -7,
		y_max = mcl_mapgen.overworld.max,
		humidity_point = 0,
		heat_point = 8,
		_mcl_biome_type = "cold",
		_mcl_palette_index = 9,
	})

	minetest.register_biome({
		name = "StoneBeach_ocean",
		node_top = "mcl_core:gravel",
		depth_top = 1,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 1,
		y_min = OCEAN_MIN,
		y_max = -8,
		vertical_blend = 2,
		humidity_point = 0,
		heat_point = 8,
		_mcl_biome_type = "cold",
		_mcl_palette_index = 9,
	})

	-- 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_mapgen.overworld.max,
		humidity_point = 24,
		heat_point = 8,
		_mcl_biome_type = "snowy",
		_mcl_palette_index = 10,
	})
	minetest.register_biome({
		name = "IcePlains_ocean",
		node_top = "mcl_core:gravel",
		depth_top = 1,
		node_filler = "mcl_core:gravel",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = 0,
		humidity_point = 24,
		heat_point = 8,
		_mcl_biome_type = "snowy",
		_mcl_palette_index = 10,
	})

	-- 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_mapgen.overworld.max,
		humidity_point = 39,
		heat_point = 58,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 0,
	})
	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,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 0,
	})
	minetest.register_biome({
		name = "Plains_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 = -1,
		humidity_point = 39,
		heat_point = 58,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 0,
	})

	-- 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_mapgen.overworld.max,
		humidity_point = 28,
		heat_point = 45,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 11,
	})
	minetest.register_biome({
		name = "SunflowerPlains_ocean",
		node_top = "mcl_core:sand",
		depth_top = 1,
		node_filler = "mcl_core:sand",
		depth_filler = 3,
		node_riverbed = "mcl_core:dirt",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = 0,
		humidity_point = 28,
		heat_point = 45,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 11,
	})

	-- 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_mapgen.overworld.max,
		humidity_point = 58,
		heat_point = 22,
		_mcl_biome_type = "cold",
		_mcl_palette_index = 12,
	})
	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,
		_mcl_biome_type = "cold",
		_mcl_palette_index = 12,
	})
	minetest.register_biome({
		name = "Taiga_ocean",
		node_top = "mcl_core:gravel",
		depth_top = 1,
		node_filler = "mcl_core:gravel",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = 0,
		humidity_point = 58,
		heat_point = 22,
		_mcl_biome_type = "cold",
		_mcl_palette_index = 12,
	})

	-- 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_mapgen.overworld.max,
		humidity_point = 61,
		heat_point = 45,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 13,
	})
	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,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 13,
	})
	minetest.register_biome({
		name = "Forest_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 = -2,
		humidity_point = 61,
		heat_point = 45,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 13,
	})

	-- 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_mapgen.overworld.max,
		humidity_point = 44,
		heat_point = 32,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 14,
	})
	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,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 14,
	})
	minetest.register_biome({
		name = "FlowerForest_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 = -3,
		humidity_point = 44,
		heat_point = 32,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 14,
	})

	-- 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_mapgen.overworld.max,
		humidity_point = 78,
		heat_point = 31,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 15,
	})
	minetest.register_biome({
		name = "BirchForest_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 = 78,
		heat_point = 31,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 15,
	})

	-- 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_mapgen.overworld.max,
		humidity_point = 77,
		heat_point = 27,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 16,
	})
	minetest.register_biome({
		name = "BirchForestM_ocean",
		node_top = "mcl_core:sand",
		depth_top = 1,
		node_filler = "mcl_core:gravel",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = 0,
		humidity_point = 77,
		heat_point = 27,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 16,
	})

	-- 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_mapgen.overworld.max,
		humidity_point = 26,
		heat_point = 94,
		_mcl_biome_type = "hot",
		_mcl_palette_index = 17,
	})
	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,
		_mcl_biome_type = "hot",
		_mcl_palette_index = 17,
	})

	-- 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_mapgen.overworld.max,
		humidity_point = 94,
		heat_point = 27,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 18,
	})
	minetest.register_biome({
		name = "RoofedForest_ocean",
		node_top = "mcl_core:gravel",
		depth_top = 1,
		node_filler = "mcl_core:gravel",
		depth_filler = 2,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = 0,
		humidity_point = 94,
		heat_point = 27,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 18,
	})

	-- Mesa: Starts with a couple of sand-covered layers (the "sandlevel"),
	-- followed by terracotta with colorful (but imperfect) strata
	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_mapgen.overworld.max,
		humidity_point = 0,
		heat_point = 100,
		_mcl_biome_type = "hot",
		_mcl_palette_index = 19,
	})
	-- 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 = -4,
		y_max = 10,
		humidity_point = 0,
		heat_point = 100,
		_mcl_biome_type = "hot",
		_mcl_palette_index = 19,
	})
	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 = -5,
		vertical_blend = 1,
		humidity_point = 0,
		heat_point = 100,
		_mcl_biome_type = "hot",
		_mcl_palette_index = 19,
	})

	-- Mesa Bryce: Variant of Mesa, but with perfect strata and a much smaller red sand desert
	minetest.register_biome({
		name = "MesaBryce",
		node_top = "mcl_colorblocks:hardened_clay",
		depth_top = 1,
		node_filler = "mcl_colorblocks:hardened_clay",
		node_riverbed = "mcl_colorblocks:hardened_clay",
		depth_riverbed = 1,
		node_stone = "mcl_colorblocks:hardened_clay",
		y_min = 4,
		y_max = mcl_mapgen.overworld.max,
		humidity_point = -5,
		heat_point = 100,
		_mcl_biome_type = "hot",
		_mcl_palette_index = 20,
	})
	minetest.register_biome({
		name = "MesaBryce_sandlevel",
		node_top = "mcl_core:redsand",
		depth_top = 1,
		node_filler = "mcl_colorblocks:hardened_clay_orange",
		depth_filler = 3,
		node_riverbed = "mcl_colorblocks:hardened_clay",
		depth_riverbed = 1,
		node_stone = "mcl_colorblocks:hardened_clay_orange",
		y_min = -4,
		y_max = 3,
		humidity_point = -5,
		heat_point = 100,
		_mcl_biome_type = "hot",
		_mcl_palette_index = 20,
	})
	minetest.register_biome({
		name = "MesaBryce_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 = -5,
		vertical_blend = 1,
		humidity_point = -5,
		heat_point = 100,
		_mcl_biome_type = "hot",
		_mcl_palette_index = 20,
	})



	-- Mesa Plateau F
	-- Identical to Mesa below Y=30. At Y=30 and above there is a "dry" 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,
		vertical_blend = 0, -- we want a sharp transition
		_mcl_biome_type = "hot",
		_mcl_palette_index = 21,
	})
	-- The oak forest plateau of this biome.
	-- This is a plateau for grass blocks, dry shrubs, tall grass, coarse dirt and oaks.
	-- Strata don't generate here.
	minetest.register_biome({
		name = "MesaPlateauF_grasstop",
		node_top = "mcl_core:dirt_with_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_mapgen.overworld.max,
		humidity_point = 0,
		heat_point = 60,
		_mcl_biome_type = "hot",
		_mcl_palette_index = 21,
	})
	minetest.register_biome({
		name = "MesaPlateauF_sandlevel",
		node_top = "mcl_core:redsand",
		depth_top = 2,
		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 = -5,
		y_max = 10,
		humidity_point = 0,
		heat_point = 60,
		_mcl_biome_type = "hot",
		_mcl_palette_index = 21,
	})
	minetest.register_biome({
		name = "MesaPlateauF_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 = -6,
		vertical_blend = 1,
		humidity_point = 0,
		heat_point = 60,
		_mcl_biome_type = "hot",
		_mcl_palette_index = 21,
	})

	-- Mesa Plateau FM
	-- Dryer and more "chaotic"/"weathered down" variant of MesaPlateauF:
	-- oak forest is less dense, more coarse dirt, more erratic terrain, vertical blend, more red sand layers,
	-- red sand as ores, red sandstone at sandlevel
	minetest.register_biome({
		name = "MesaPlateauFM",
		node_top = "mcl_colorblocks:hardened_clay",
		depth_top = 1,
		node_filler = "mcl_colorblocks:hardened_clay",
		node_riverbed = "mcl_core:redsand",
		depth_riverbed = 2,
		node_stone = "mcl_colorblocks:hardened_clay",
		y_min = 12,
		y_max = 29,
		humidity_point = -5,
		heat_point = 60,
		vertical_blend = 5,
		_mcl_biome_type = "hot",
		_mcl_palette_index = 22,
	})
	-- Grass plateau
	minetest.register_biome({
		name = "MesaPlateauFM_grasstop",
		node_top = "mcl_core:dirt_with_grass",
		depth_top = 1,
		node_filler = "mcl_core:coarse_dirt",
		depth_filler = 2,
		node_riverbed = "mcl_core:redsand",
		depth_riverbed = 1,
		node_stone = "mcl_colorblocks:hardened_clay",
		y_min = 30,
		y_max = mcl_mapgen.overworld.max,
		humidity_point = -5,
		heat_point = 60,
		_mcl_biome_type = "hot",
		_mcl_palette_index = 22,
	})
	minetest.register_biome({
		name = "MesaPlateauFM_sandlevel",
		node_top = "mcl_core:redsand",
		depth_top = 3,
		node_filler = "mcl_colorblocks:hardened_clay_orange",
		depth_filler = 3,
		node_riverbed = "mcl_core:redsand",
		depth_riverbed = 2,
		node_stone = "mcl_colorblocks:hardened_clay",
		-- red sand has wider reach than in other mesa biomes
		y_min = -7,
		y_max = 11,
		humidity_point = -5,
		heat_point = 60,
		vertical_blend = 4,
		_mcl_biome_type = "hot",
		_mcl_palette_index = 22,
	})
	minetest.register_biome({
		name = "MesaPlateauFM_ocean",
		node_top = "mcl_core:sand",
		depth_top = 3,
		node_filler = "mcl_core:sand",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 3,
		y_min = OCEAN_MIN,
		y_max = -8,
		vertical_blend = 2,
		humidity_point = -5,
		heat_point = 60,
		_mcl_biome_type = "hot",
		_mcl_palette_index = 22,
	})


	-- Savanna
	minetest.register_biome({
		name = "Savanna",
		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_mapgen.overworld.max,
		humidity_point = 36,
		heat_point = 79,
		_mcl_biome_type = "hot",
		_mcl_palette_index = 1,
	})
	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,
		_mcl_biome_type = "hot",
		_mcl_palette_index = 1,
	})
	minetest.register_biome({
		name = "Savanna_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 = -2,
		humidity_point = 36,
		heat_point = 79,
		_mcl_biome_type = "hot",
		_mcl_palette_index = 1,
	})

	-- 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_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_mapgen.overworld.max,
		humidity_point = 48,
		heat_point = 100,
		_mcl_biome_type = "hot",
		_mcl_palette_index = 23,
	})
	minetest.register_biome({
		name = "SavannaM_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 = 48,
		heat_point = 100,
		_mcl_biome_type = "hot",
		_mcl_palette_index = 23,
	})

	-- 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_mapgen.overworld.max,
		humidity_point = 88,
		heat_point = 81,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 24,
	})
	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 = -2,
		y_max = 0,
		humidity_point = 88,
		heat_point = 81,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 24,
	})
	minetest.register_biome({
		name = "Jungle_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 = -3,
		vertical_blend = 1,
		humidity_point = 88,
		heat_point = 81,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 24,
	})

	-- 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_mapgen.overworld.max,
		humidity_point = 92,
		heat_point = 81,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 25,
	})
	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 = -2,
		y_max = 0,
		humidity_point = 92,
		heat_point = 81,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 25,
	})
	minetest.register_biome({
		name = "JungleM_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 = -3,
		vertical_blend = 1,
		humidity_point = 92,
		heat_point = 81,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 25,
	})

	-- 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_mapgen.overworld.max,
		humidity_point = 88,
		heat_point = 76,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 26,
	})
	minetest.register_biome({
		name = "JungleEdge_ocean",
		node_top = "mcl_core:sand",
		depth_top = 1,
		node_filler = "mcl_core:sand",
		depth_filler = 2,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = 0,
		humidity_point = 88,
		heat_point = 76,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 26,
	})

	-- 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_mapgen.overworld.max,
		humidity_point = 90,
		heat_point = 79,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 27,
	})
	minetest.register_biome({
		name = "JungleEdgeM_ocean",
		node_top = "mcl_core:sand",
		depth_top = 1,
		node_filler = "mcl_core:sand",
		depth_filler = 4,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = 0,
		humidity_point = 90,
		heat_point = 79,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 27,
	})

	-- 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,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 28,
	})
	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 = -5,
		y_max = 0,
		humidity_point = 90,
		heat_point = 50,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 28,
	})
	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 = -6,
		vertical_blend = 1,
		humidity_point = 90,
		heat_point = 50,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 28,
	})

	-- Mushroom Island / Mushroom Island Shore (rare)
	-- Not neccessarily an island at all, only named after Minecraft's biome
	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,
		vertical_blend = 1,
		humidity_point = 106,
		heat_point = 50,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 29,
	})

	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,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 29,
	})
	minetest.register_biome({
		name = "MushroomIsland_ocean",
		node_top = "mcl_core:gravel",
		depth_top = 1,
		node_filler = "mcl_core:gravel",
		depth_filler = 3,
		node_riverbed = "mcl_core:sand",
		depth_riverbed = 2,
		y_min = OCEAN_MIN,
		y_max = 0,
		humidity_point = 106,
		heat_point = 50,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 29,
	})

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

		-- Deep Ocean
		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 = minetest.registered_biomes[biome.."_ocean"].node_top,
			depth_top = 2,
			node_filler = minetest.registered_biomes[biome.."_ocean"].node_filler,
			depth_filler = 3,
			node_riverbed = minetest.registered_biomes[biome.."_ocean"].node_riverbed,
			depth_riverbed = 2,
			vertical_blend = 5,
			_mcl_biome_type = minetest.registered_biomes[biome]._mcl_biome_type,
			_mcl_palette_index = minetest.registered_biomes[biome]._mcl_palette_index,
		})

		-- 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_mapgen.overworld.min,
			y_max = DEEP_OCEAN_MIN - 1,
			_mcl_biome_type = minetest.registered_biomes[biome]._mcl_biome_type,
			_mcl_palette_index = minetest.registered_biomes[biome]._mcl_palette_index,
		})

	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",
		node_cave_liquid = "air",
		y_min = mcl_mapgen.nether.min,
		-- FIXME: For some reason the Nether stops generating early if this constant is not added.
		-- Figure out why.
		y_max = mcl_mapgen.nether.max + 80,
		heat_point = 100,
		humidity_point = 0,
		_mcl_biome_type = "hot",
		_mcl_palette_index = 17,
	})

	--[[ THE END ]]
	minetest.register_biome({
		name = "End",
		node_stone = "air",
		node_filler = "air",
		node_water = "air",
		node_river_water = "air",
		node_cave_liquid = "air",
		-- FIXME: For some reason the End stops generating early if this constant is not added.
		-- Figure out why.
		y_min = mcl_mapgen.end_.min,
		y_max = mcl_mapgen.end_.max + 80,
		heat_point = 50,
		humidity_point = 50,
		_mcl_biome_type = "medium",
		_mcl_palette_index = 0,
	})

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", "ExtremeHills_deep_ocean", "ExtremeHills_underground",
			"ExtremeHills+", "ExtremeHills+_ocean", "ExtremeHills+_deep_ocean", "ExtremeHills+_underground",
			"ExtremeHillsM", "ExtremeHillsM_ocean", "ExtremeHillsM_deep_ocean", "ExtremeHillsM_underground",
		},
	})

	-- 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 mcl_mapgen.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_mapgen.overworld.min,
		y_max          = mcl_worlds.layer_to_y(61),
		biomes         = {
			"ExtremeHills", "ExtremeHills_beach", "ExtremeHills_ocean", "ExtremeHills_deep_ocean", "ExtremeHills_underground",
			"ExtremeHills+", "ExtremeHills+_ocean", "ExtremeHills+_deep_ocean", "ExtremeHills+_underground",
			"ExtremeHillsM", "ExtremeHillsM_ocean", "ExtremeHillsM_deep_ocean", "ExtremeHillsM_underground",
		},
	})

	-- Bonus gold spawn in Mesa
	if not mcl_mapgen.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",
					"MesaBryce", "MesaBryce_sandlevel", "MesaBryce_ocean",
					"MesaPlateauF", "MesaPlateauF_sandlevel", "MesaPlateauF_ocean",
					"MesaPlateauFM", "MesaPlateauFM_sandlevel", "MesaPlateauFM_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_mapgen.overworld.min,
		y_max		= mcl_mapgen.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_grass", "mcl_core:dirt"},
		column_height_max = 1,
		column_midpoint_factor = 0.0,
		y_min		= mcl_mapgen.overworld.min,
		y_max		= mcl_mapgen.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_grass", "mcl_core:dirt"},
		clust_scarcity	= 1500,
		clust_num_ores	= 25,
		clust_size	= 7,
		y_min		= mcl_mapgen.overworld.min,
		y_max		= mcl_mapgen.overworld.max,
		noise_params = {
			offset  = 0,
			scale   = 1,
			spread  = {x=250, y=250, z=250},
			seed    = 12345,
			octaves = 3,
			persist = 0.6,
			lacunarity = 2,
			flags = "defaults",
		},
		biomes = { "MesaPlateauF_grasstop" },
	})
	minetest.register_ore({
		ore_type	= "sheet",
		ore		= "mcl_core:coarse_dirt",
		wherein		= {"mcl_core:dirt_with_grass", "mcl_core:dirt"},
		column_height_max = 1,
		column_midpoint_factor = 0.0,
		y_min		= mcl_mapgen.overworld.min,
		y_max		= mcl_mapgen.overworld.max,
		noise_threshold = -2.5,
		noise_params = {offset=1, scale=15, spread={x=250, y=250, z=250}, seed=24, octaves=3, persist=0.80},
		biomes = { "MesaPlateauFM_grasstop" },
	})
	minetest.register_ore({
		ore_type	= "blob",
		ore		= "mcl_core:coarse_dirt",
		wherein		= {"mcl_core:dirt_with_grass", "mcl_core:dirt"},
		clust_scarcity	= 1800,
		clust_num_ores	= 65,
		clust_size	= 15,
		y_min		= mcl_mapgen.overworld.min,
		y_max		= mcl_mapgen.overworld.max,
		noise_params = {
			offset  = 0,
			scale   = 1,
			spread  = {x=250, y=250, z=250},
			seed    = 12345,
			octaves = 3,
			persist = 0.6,
			lacunarity = 2,
			flags = "defaults",
		},
		biomes = { "MesaPlateauFM_grasstop" },
	})
	-- Occasionally dig out portions of MesaPlateauFM
	minetest.register_ore({
		ore_type	= "blob",
		ore		= "air",
		wherein		= {"group:hardened_clay", "group:sand","mcl_core:coarse_dirt"},
		clust_scarcity	= 4000,
		clust_size	= 5,
		y_min		= mcl_mapgen.overworld.min,
		y_max		= mcl_mapgen.overworld.max,
		noise_params = {
			offset  = 0,
			scale   = 1,
			spread  = {x=250, y=250, z=250},
			seed    = 12345,
			octaves = 3,
			persist = 0.6,
			lacunarity = 2,
			flags = "defaults",
		},
		biomes = { "MesaPlateauFM", "MesaPlateauFM_grasstop" },
	})
	minetest.register_ore({
		ore_type	= "blob",
		ore		= "mcl_core:redsandstone",
		wherein		= {"mcl_colorblocks:hardened_clay_orange"},
		clust_scarcity	= 300,
		clust_size	= 8,
		y_min		= mcl_mapgen.overworld.min,
		y_max		= mcl_mapgen.overworld.max,
		noise_params = {
			offset  = 0,
			scale   = 1,
			spread  = {x=250, y=250, z=250},
			seed    = 12345,
			octaves = 3,
			persist = 0.6,
			lacunarity = 2,
			flags = "defaults",
		},
		biomes = { "MesaPlateauFM_sandlevel" },
	})
	-- More red sand in MesaPlateauFM
	minetest.register_ore({
		ore_type	= "sheet",
		ore		= "mcl_core:redsand",
		wherein		= {"group:hardened_clay"},
		clust_scarcity	= 1,
		clust_num_ores	= 12,
		clust_size	= 10,
		y_min		= mcl_mapgen.overworld.min,
		y_max		= mcl_mapgen.overworld.max,
		noise_threshold = 0.1,
		noise_params = {offset=0, scale=15, spread={x=130, y=130, z=130}, seed=95, octaves=3, persist=0.70},
		biomes = { "MesaPlateauFM" },
	})
	minetest.register_ore({
		ore_type	= "blob",
		ore		= "mcl_core:redsand",
		wherein		= {"group:hardened_clay"},
		clust_scarcity	= 1500,
		clust_size	= 4,
		y_min		= mcl_mapgen.overworld.min,
		y_max		= mcl_mapgen.overworld.max,
		noise_params = {
			offset  = 0,
			scale   = 1,
			spread  = {x=250, y=250, z=250},
			seed    = 12345,
			octaves = 3,
			persist = 0.6,
			lacunarity = 2,
			flags = "defaults",
		},
		biomes = { "MesaPlateauFM", "MesaPlateauFM_grasstop", "MesaPlateauFM_sandlevel" },
	})

	-- 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_mapgen.overworld.min,
		y_max		= mcl_mapgen.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" },
	})
	-- For a transition from stone to hardened clay in mesa biomes that is not perfectly flat
	minetest.register_ore({
		ore_type = "stratum",
		ore = "mcl_core:stone",
		wherein = {"group:hardened_clay"},
		noise_params = {offset=-6, scale=2, spread={x=25, y=25, z=25}, octaves=1, persist=0.60},
		stratum_thickness = 8,
		biomes = {
			"Mesa_sandlevel", "Mesa_ocean",
			"MesaBryce_sandlevel", "MesaBryce_ocean",
			"MesaPlateauF_sandlevel", "MesaPlateauF_ocean",
			"MesaPlateauFM_sandlevel", "MesaPlateauFM_ocean",
		},
		y_min = -4,
		y_max = 0,

	})

	-- Mesa strata (registered as sheet ores)

	-- Helper function to create strata.
	local function stratum(y_min, height, color, seed, is_perfect)
		if not height then
			height = 1
		end
		if not seed then
			seed = 39
		end
		local y_max = y_min + height-1
		local perfect_biomes
		if is_perfect then
			-- "perfect" means no erosion
			perfect_biomes = { "MesaBryce", "Mesa", "MesaPlateauF", "MesaPlateauFM" }
		else
			perfect_biomes = { "MesaBryce" }
		end
		-- Full, perfect stratum
		minetest.register_ore({
			ore_type = "stratum",
			ore = "mcl_colorblocks:hardened_clay_"..color,
			-- Only paint uncolored so the biome can choose
			-- a color in advance.
			wherein = {"mcl_colorblocks:hardened_clay"},
			y_min = y_min,
			y_max = y_max,
			biomes = perfect_biomes,
		})
		if not is_perfect then
		-- Slightly eroded stratum, only minor imperfections
		minetest.register_ore({
			ore_type = "stratum",
			ore = "mcl_colorblocks:hardened_clay_"..color,
			wherein = {"mcl_colorblocks:hardened_clay"},
			y_min = y_min,
			y_max = y_max,
			biomes = { "Mesa", "MesaPlateauF" },
			noise_params = {
				offset = y_min+(y_max-y_min)/2,
				scale = 0,
				spread = {x = 50, y = 50, z = 50},
				seed = seed+4,
				octaves = 1,
				persist = 1.0
			},
			np_stratum_thickness = {
				offset = 1.28,
				scale = 1,
				spread = {x = 18, y = 18, z = 18},
				seed = seed+4,
				octaves = 3,
				persist = 0.8,
			},
		})
		-- Very eroded stratum, most of the color is gone
		minetest.register_ore({
			ore_type = "stratum",
			ore = "mcl_colorblocks:hardened_clay_"..color,
			wherein = {"mcl_colorblocks:hardened_clay"},
			y_min = y_min,
			y_max = y_max,
			biomes = { "MesaPlateauFM" },
			noise_params = {
				offset = y_min+(y_max-y_min)/2,
				scale = 0,
				spread = {x = 50, y = 50, z = 50},
				seed = seed+4,
				octaves = 1,
				persist = 1.0
			},
			np_stratum_thickness = {
				offset = 0.1,
				scale = 1,
				spread = {x = 28, y = 28, z = 28},
				seed = seed+4,
				octaves = 2,
				persist = 0.6,
			},
		})
		end

	end

	-- Hardcoded orange strata near sea level.

	-- For MesaBryce, since it has no sand at these heights
	stratum(4, 1, "orange", nil, true)
	stratum(7, 2, "orange", nil, true)

	-- 3-level stratum above the sandlevel (all mesa biomes)
	stratum(11, 3, "orange", nil, true)

	-- Create random strata for up to Y = 256.
	-- These strata are calculated based on the world seed and are global.
	-- They are thus different per-world.
	local mesapr = PcgRandom(mg_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_mapgen.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"),
		noise_params = {
			offset  = 0,
			scale   = 1,
			spread  = {x=250, y=250, z=250},
			seed    = 12345,
			octaves = 3,
			persist = 0.6,
			lacunarity = 2,
			flags = "defaults",
		},
	})
	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"),
		noise_params = {
			offset  = 0,
			scale   = 1,
			spread  = {x=250, y=250, z=250},
			seed    = 12345,
			octaves = 3,
			persist = 0.6,
			lacunarity = 2,
			flags = "defaults",
		},
	})

	-- 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_mapgen.nether.lava_max + 10,
		y_max           = mcl_mapgen.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
	if minetest.settings:get_bool("mcl_generate_ores", true) then
		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_mapgen.nether.min,
			y_max = mcl_mapgen.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_mapgen.nether.min,
			y_max = mcl_mapgen.nether.max,
		})
	end

	-- Ancient debris
	if minetest.settings:get_bool("mcl_generate_ores", true) then
		minetest.register_ore({
			ore_type       = "scatter",
			ore	       = "mcl_nether:ancient_debris",
			wherein        = {"mcl_nether:netherrack"},
			clust_scarcity = 10000,
			clust_num_ores = 4,
			clust_size     = 1,
			y_min = mcl_worlds.layer_to_y(8, "nether"),
			y_max = mcl_worlds.layer_to_y(119, "nether"),
		})
	end

	-- 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_mapgen.nether.min,
		y_max           = mcl_mapgen.nether.lava_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_mapgen.nether.lava_max + 2,
		y_max           = mcl_mapgen.nether.lava_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_mapgen.nether.lava_max + 13,
		y_max           = mcl_mapgen.nether.lava_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_mapgen.nether.lava_max + 49,
		y_max           = mcl_mapgen.nether.max,
	})

	--[[ THE END ]]

	-- Generate fake End
	-- TODO: Remove the "ores" when there's a better End generator
	-- FIXME: Broken lighting in v6 mapgen

	local end_wherein
	if mcl_mapgen.v6 then
		end_wherein = {"air", "mcl_core:stone"}
	else
		end_wherein = {"air"}
	end

	minetest.register_ore({
		ore_type        = "stratum",
		ore             = "mcl_end:end_stone",
		wherein         = end_wherein,
		y_min           = mcl_mapgen.end_.min+64,
		y_max           = mcl_mapgen.end_.min+80,

		noise_params = {
			offset  = mcl_mapgen.end_.min+70,
			scale   = -1,
			spread  = {x=126, y=126, z=126},
			seed    = mg_seed+9999,
			octaves = 3,
			persist = 0.5,
		},

		np_stratum_thickness = {
			offset  = -2,
			scale   = 10,
			spread  = {x=126, y=126, z=126},
			seed    = mg_seed+9999,
			octaves = 3,
			persist = 0.5,
		},
		clust_scarcity = 1,
	})

	minetest.register_ore({
		ore_type        = "stratum",
		ore             = "mcl_end:end_stone",
		wherein         = end_wherein,
		y_min           = mcl_mapgen.end_.min+64,
		y_max           = mcl_mapgen.end_.min+80,

		noise_params = {
			offset  = mcl_mapgen.end_.min+72,
			scale   = -3,
			spread  = {x=84, y=84, z=84},
			seed    = mg_seed+999,
			octaves = 4,
			persist = 0.8,
		},

		np_stratum_thickness = {
			offset  = -4,
			scale   = 10,
			spread  = {x=84, y=84, z=84},
			seed    = mg_seed+999,
			octaves = 4,
			persist = 0.8,
		},
		clust_scarcity = 1,
	})
	minetest.register_ore({
		ore_type        = "stratum",
		ore             = "mcl_end:end_stone",
		wherein         = end_wherein,
		y_min           = mcl_mapgen.end_.min+64,
		y_max           = mcl_mapgen.end_.min+80,

		noise_params = {
			offset  = mcl_mapgen.end_.min+70,
			scale   = -2,
			spread  = {x=84, y=84, z=84},
			seed    = mg_seed+99,
			octaves = 4,
			persist = 0.85,
		},

		np_stratum_thickness = {
			offset  = -3,
			scale   = 5,
			spread  = {x=63, y=63, z=63},
			seed    = mg_seed+50,
			octaves = 4,
			persist = 0.85,
		},
		clust_scarcity = 1,
	})

end


-- All mapgens except mgv6

-- Template to register a grass or fern decoration
local function register_grass_decoration(grasstype, offset, scale, biomes)
	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
	}
	for b=1, #biomes do
		local param2 = minetest.registered_biomes[biomes[b]]._mcl_palette_index
		minetest.register_decoration({
			deco_type = "simple",
			place_on = place_on,
			sidelen = 16,
			noise_params = noise,
			biomes = { biomes[b] },
			y_min = 1,
			y_max = mcl_mapgen.overworld.max,
			decoration = node,
			param2 = param2,
		})
	end
end

local function register_seagrass_decoration(grasstype, offset, scale, biomes)
	local seed, nodes, surfaces, param2, param2_max, y_max
	if grasstype == "seagrass" then
		seed = 16
		surfaces = { "mcl_core:dirt", "mcl_core:sand", "mcl_core:gravel", "mcl_core:redsand" }
		nodes = { "mcl_ocean:seagrass_dirt", "mcl_ocean:seagrass_sand", "mcl_ocean:seagrass_gravel", "mcl_ocean:seagrass_redsand" }
		y_max = 0
	elseif grasstype == "kelp" then
		seed = 32
		param2 = 16
		param2_max = 96
		surfaces = { "mcl_core:dirt", "mcl_core:sand", "mcl_core:gravel" }
		nodes = { "mcl_ocean:kelp_dirt", "mcl_ocean:kelp_sand", "mcl_ocean:kelp_gravel" }
		y_max = -6
	end
	local noise = {
		offset = offset,
		scale = scale,
		spread = {x = 100, y = 100, z = 100},
		seed = seed,
		octaves = 3,
		persist = 0.6,
	}

	for s=1, #surfaces do
		minetest.register_decoration({
			deco_type = "simple",
			place_on = { surfaces[s] },
			sidelen = 16,
			noise_params = noise,
			biomes = biomes,
			y_min = DEEP_OCEAN_MIN,
			y_max = y_max,
			decoration = nodes[s],
			param2 = param2,
			param2_max = param2_max,
			place_offset_y = -1,
			flags = "force_placement",
		})
	end
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_mapgen.overworld.max,
		schematic = mod_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_mapgen.overworld.max,
		schematic = mod_mcl_structures.."/schematics/mcl_structures_ice_spike_small.mts",
		rotation = "random",
		flags = "place_center_x, place_center_z",
	})

	-- Oak
	-- Large oaks
	for i=1, 4 do
		minetest.register_decoration({
			deco_type = "schematic",
			place_on = {"group:grass_block_no_snow", "mcl_core:dirt"},
			sidelen = 80,
			noise_params = {
				offset = 0.000545,
				scale = 0.0011,
				spread = {x = 250, y = 250, z = 250},
				seed = 3 + 5 * i,
				octaves = 3,
				persist = 0.66
			},
			biomes = {"Forest"},
			y_min = 1,
			y_max = mcl_mapgen.overworld.max,
			schematic = mod_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.0007,
				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_mapgen.overworld.max,
			schematic = mod_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_mapgen.overworld.max,
		schematic = mod_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_mapgen.overworld.max,
		schematic = mod_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_mapgen.overworld.max,
		schematic = mod_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_mapgen.overworld.max,
		schematic = mod_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_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_mapgen.overworld.max,
		schematic = mod_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_grass", "mcl_core:dirt"},
		sidelen = 16,
		noise_params = {
			offset = 0.008,
			scale = 0.002,
			spread = {x = 250, y = 250, z = 250},
			seed = 2,
			octaves = 3,
			persist = 0.7
		},
		biomes = {"MesaPlateauFM_grasstop"},
		y_min = 30,
		y_max = mcl_mapgen.overworld.max,
		schematic = mod_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_mapgen.overworld.max,
		schematic = mod_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_mapgen.overworld.max,
		schematic = mod_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_mapgen.overworld.max,
		schematic = mod_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_mapgen.overworld.max,
		schematic = mod_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_mapgen.overworld.max,
		schematic = mod_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_mapgen.overworld.max,
			schematic = mod_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_mapgen.overworld.max,
			schematic = mod_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_mapgen.overworld.max,
		schematic = mod_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_mapgen.overworld.max,
		schematic = mod_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_mapgen.overworld.max,
		schematic = mod_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_mapgen.overworld.max,
			schematic = mod_mcl_core.."/schematics/"..sprucename,
			flags = "place_center_x, place_center_z",
		})
	end

	-- Huge spruce
	quick_spruce(3000, 0.0030, "mcl_core_spruce_huge_1.mts", {"MegaSpruceTaiga"})
	quick_spruce(4000, 0.0036, "mcl_core_spruce_huge_2.mts", {"MegaSpruceTaiga"})
	quick_spruce(6000, 0.0036, "mcl_core_spruce_huge_3.mts", {"MegaSpruceTaiga"})
	quick_spruce(6600, 0.0036, "mcl_core_spruce_huge_4.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_mapgen.overworld.max,
		schematic = mod_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_mapgen.overworld.max,
		schematic = mod_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_mapgen.overworld.max,
		schematic = mod_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_grass", "mcl_core:dirt", "mcl_core:coarse_dirt"},
			sidelen = 16,
			fill_ratio = 0.0002,
			biomes = {"Savanna", "SavannaM"},
			y_min = 1,
			y_max = mcl_mapgen.overworld.max,
			schematic = mod_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_mapgen.overworld.max,
		schematic = mod_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_mapgen.overworld.max,
		schematic = mod_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_mapgen.overworld.max,
		schematic = mod_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_mapgen.overworld.max,
		schematic = mod_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_mapgen.overworld.max,
		schematic = mod_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_mapgen.overworld.max,
		schematic = mod_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_mapgen.overworld.max,
		schematic = mod_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_mapgen.overworld.max,
		schematic = mod_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_mapgen.overworld.max,
		schematic = mod_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_mapgen.overworld.max,
		schematic = mod_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_mapgen.overworld.max,
		schematic = mod_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_mapgen.overworld.max,
		schematic = mod_mcl_mushrooms.."/schematics/mcl_mushrooms_giant_red.mts",
		flags = "place_center_x, place_center_z",
		rotation = "0",
	})

	-- Mossy cobblestone 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_mapgen.overworld.max,
		schematic = mod_mcl_structures.."/schematics/mcl_structures_boulder.mts",
		flags = "place_center_x, place_center_z",
	})

	-- Small mossy cobblestone 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_mapgen.overworld.max,
		schematic = mod_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
		},
		spawn_by = "air",
		num_spawn_by = 8,
		decoration = "mcl_core:cactus",
		biomes = {"Desert",
			"Mesa","Mesa_sandlevel",
			"MesaPlateauF","MesaPlateauF_sandlevel",
			"MesaPlateauFM","MesaPlateauFM_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_mapgen.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_mapgen.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
	local function register_doubletall_grass(offset, scale, biomes)

		for b=1, #biomes do
			local param2 = minetest.registered_biomes[biomes[b]]._mcl_palette_index
			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 },
					},
				},
				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_mapgen.overworld.max,
				biomes = { biomes[b] },
			})
		end
	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"})

	-- Large ferns
	local function register_double_fern(offset, scale, biomes)
		for b=1, #biomes do
			local param2 = minetest.registered_biomes[biomes[b]]._mcl_palette_index
			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, param2=param2 },
						{ name = "mcl_flowers:double_fern_top", param1=255, param2=param2 },
					},
				},
				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,
				},
				y_min = 1,
				y_max = mcl_mapgen.overworld.max,
				biomes = biomes[b],
			})
		end
	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 function register_large_flower(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_mapgen.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_mapgen.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_mapgen.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_mapgen.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_mapgen.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_mapgen.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_mapgen.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_mapgen.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_mapgen.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_mapgen.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_mapgen.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_mapgen.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_mapgen.overworld.max,
		decoration = "mcl_farming:melon",
		biomes = { "JungleEdgeM" },
	})

	-- Pumpkin
	minetest.register_decoration({
		deco_type = "simple",
		decoration = "mcl_farming:pumpkin_face",
		param2 = 0,
		param2_max = 3,
		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_mapgen.overworld.max,
	})

	-- 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" }
	local grass_mpfm = {"MesaPlateauFM_grasstop" }

	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)
	register_grass_decoration("tallgrass", -0.015, 0.075, grass_mpf)
	register_grass_decoration("tallgrass", 0, 0.06, grass_mpf)
	register_grass_decoration("tallgrass", 0.01, 0.045, grass_mpf)
	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)
	register_grass_decoration("tallgrass", 0.05, -0.03, grass_sparse)
	register_grass_decoration("tallgrass", 0.05, 0.05, grass_mpfm)

	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, {"JungleM"})

	local b_seagrass = {"ColdTaiga_ocean","ExtremeHills_ocean","ExtremeHillsM_ocean","ExtremeHills+_ocean","Taiga_ocean","MegaTaiga_ocean","MegaSpruceTaiga_ocean","StoneBeach_ocean","Plains_ocean","SunflowerPlains_ocean","Forest_ocean","FlowerForest_ocean","BirchForest_ocean","BirchForestM_ocean","RoofedForest_ocean","Swampland_ocean","Jungle_ocean","JungleM_ocean","JungleEdge_ocean","JungleEdgeM_ocean","MushroomIsland_ocean","Desert_ocean","Savanna_ocean","SavannaM_ocean","Mesa_ocean","MesaBryce_ocean","MesaPlateauF_ocean","MesaPlateauFM_ocean",
"ColdTaiga_deep_ocean","ExtremeHills_deep_ocean","ExtremeHillsM_deep_ocean","ExtremeHills+_deep_ocean","Taiga_deep_ocean","MegaTaiga_deep_ocean","MegaSpruceTaiga_deep_ocean","StoneBeach_deep_ocean","Plains_deep_ocean","SunflowerPlains_deep_ocean","Forest_deep_ocean","FlowerForest_deep_ocean","BirchForest_deep_ocean","BirchForestM_deep_ocean","RoofedForest_deep_ocean","Swampland_deep_ocean","Jungle_deep_ocean","JungleM_deep_ocean","JungleEdge_deep_ocean","JungleEdgeM_deep_ocean","MushroomIsland_deep_ocean","Desert_deep_ocean","Savanna_deep_ocean","SavannaM_deep_ocean","Mesa_deep_ocean","MesaBryce_deep_ocean","MesaPlateauF_deep_ocean","MesaPlateauFM_deep_ocean",
"Mesa_sandlevel","MesaBryce_sandlevel","MesaPlateauF_sandlevel","MesaPlateauFM_sandlevel","Swampland_shore","Jungle_shore","JungleM_shore","Savanna_beach","FlowerForest_beach","ColdTaiga_beach_water","ExtremeHills_beach"}
	local b_kelp = {"ExtremeHillsM_ocean","ExtremeHills+_ocean","MegaTaiga_ocean","MegaSpruceTaiga_ocean","Plains_ocean","SunflowerPlains_ocean","Forest_ocean","FlowerForest_ocean","BirchForest_ocean","BirchForestM_ocean","RoofedForest_ocean","Swampland_ocean","Jungle_ocean","JungleM_ocean","JungleEdge_ocean","JungleEdgeM_ocean","MushroomIsland_ocean",
"ExtremeHillsM_deep_ocean","ExtremeHills+_deep_ocean","MegaTaiga_deep_ocean","MegaSpruceTaiga_deep_ocean","Plains_deep_ocean","SunflowerPlains_deep_ocean","Forest_deep_ocean","FlowerForest_deep_ocean","BirchForest_deep_ocean","BirchForestM_deep_ocean","RoofedForest_deep_ocean","Swampland_deep_ocean","Jungle_deep_ocean","JungleM_deep_ocean","JungleEdge_deep_ocean","JungleEdgeM_deep_ocean","MushroomIsland_deep_ocean"
}

	register_seagrass_decoration("seagrass", 0, 0.5, b_seagrass)
	register_seagrass_decoration("kelp", -0.5, 1, b_kelp)

	local b_sponge = {"Plains_deep_ocean","SunflowerPlains_deep_ocean","Forest_deep_ocean","FlowerForest_deep_ocean","BirchForest_deep_ocean","BirchForestM_deep_ocean","RoofedForest_deep_ocean","Jungle_deep_ocean","JungleM_deep_ocean","JungleEdge_deep_ocean","JungleEdgeM_deep_ocean","MushroomIsland_deep_ocean","Desert_deep_ocean","Savanna_deep_ocean","SavannaM_deep_ocean","Mesa_deep_ocean","MesaBryce_deep_ocean","MesaPlateauF_deep_ocean","MesaPlateauFM_deep_ocean"}
	-- Wet Sponge
	-- TODO: Remove this when we got ocean monuments
	minetest.register_decoration({
		deco_type = "simple",
		decoration = "mcl_sponges:sponge_wet",
		biomes = b_sponge,
		spawn_by = {"group:water"},
		num_spawn_by = 1,
		place_on = {"mcl_core:dirt","mcl_core:sand","mcl_core:gravel"},
		sidelen = 16,
		noise_params = {
			offset = 0.00495,
			scale = 0.006,
			spread = {x = 250, y = 250, z = 250},
			seed = 999,
			octaves = 3,
			persist = 0.666
		},
		flags = "force_placement",
		y_min = mcl_mapgen.overworld.lava_max + 5,
		y_max = -20,
	})

	-- 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_mapgen.overworld.max,
		schematic = {
			size = { x=1, y=2, z=1 },
			data = {
				{ name = "mcl_core:dirt_with_grass", force_place=true, },
				{ name = "mcl_flowers:tallgrass", param2 = minetest.registered_biomes["IcePlains"]._mcl_palette_index },
			},
		},
	})
	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_mapgen.overworld.max,
		schematic = {
			size = { x=1, y=2, z=1 },
			data = {
				{ name = "mcl_core:dirt_with_grass", force_place=true, },
				{ name = "mcl_flowers:tallgrass", param2 = minetest.registered_biomes["ExtremeHills+_snowtop"]._mcl_palette_index },
			},
		},
	})


	-- Dead bushes
	minetest.register_decoration({
		deco_type = "simple",
		place_on = {"group:sand", "mcl_core:podzol", "mcl_core:dirt", "mcl_core:dirt_with_grass", "mcl_core:coarse_dirt", "group:hardened_clay"},
		sidelen = 16,
		noise_params = {
			offset = 0.0,
			scale = 0.035,
			spread = {x = 100, y = 100, z = 100},
			seed = 1972,
			octaves = 3,
			persist = 0.6
		},
		y_min = 4,
		y_max = mcl_mapgen.overworld.max,
		biomes = {"Desert", "Mesa", "Mesa_sandlevel", "MesaPlateauF", "MesaPlateauF_sandlevel", "MesaPlateauF_grasstop","MesaBryce","Taiga", "MegaTaiga"},
		decoration = "mcl_core:deadbush",
		height = 1,
	})
	minetest.register_decoration({
		deco_type = "simple",
		place_on = {"group:sand", "mcl_core:dirt", "mcl_core:dirt_with_grass", "mcl_core:coarse_dirt"},
		sidelen = 16,
		noise_params = {
			offset = 0.1,
			scale = 0.035,
			spread = {x = 100, y = 100, z = 100},
			seed = 1972,
			octaves = 3,
			persist = 0.6
		},
		y_min = 4,
		y_max = mcl_mapgen.overworld.max,
		biomes = {"MesaPlateauFM_grasstop"},
		decoration = "mcl_core:deadbush",
		height = 1,
	})
	minetest.register_decoration({
		deco_type = "simple",
		place_on = {"group:sand"},
		sidelen = 16,
		noise_params = {
			offset = 0.045,
			scale = 0.055,
			spread = {x = 100, y = 100, z = 100},
			seed = 1972,
			octaves = 3,
			persist = 0.6
		},
		y_min = 4,
		y_max = mcl_mapgen.overworld.max,
		biomes = {"MesaPlateauFM","MesaPlateauFM_sandlevel"},
		decoration = "mcl_core:deadbush",
		height = 1,
	})
	minetest.register_decoration({
		deco_type = "simple",
		place_on = {"group:hardened_clay"},
		sidelen = 16,
		noise_params = {
			offset = 0.010,
			scale = 0.035,
			spread = {x = 100, y = 100, z = 100},
			seed = 1972,
			octaves = 3,
			persist = 0.6
		},
		y_min = 4,
		y_max = mcl_mapgen.overworld.max,
		biomes = {"MesaPlateauFM", "MesaPlateauFM_sandlevel", "MesaPlateauFM_grasstop"},
		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_mapgen.overworld.min,
		y_max = mcl_mapgen.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_mapgen.overworld.min,
		y_max = mcl_mapgen.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_mapgen.overworld.min,
		y_max = mcl_mapgen.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_mapgen.overworld.min,
		y_max = mcl_mapgen.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_mapgen.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_mapgen.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_mapgen.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_mapgen.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 chorus_noise_params = {
	offset = -0.012,
	scale = 0.024,
	spread = {x = 100, y = 100, z = 100},
	seed = 257,
	octaves = 3,
	persistence = 0.6,
}

local function register_dimension_decorations()
	--[[ NETHER ]]
	-- TODO: Nether

	--[[ THE END ]]

	-- Chorus plant
	minetest.register_decoration({
		name = "mcl_biomes:chorus_plant",
		deco_type = "simple",
		place_on = {"mcl_end:end_stone", "air"},
		flags = "all_floors",
		sidelen = 16,
		noise_params = chorus_noise_params,
		y_min = mcl_mapgen.end_.min,
		y_max = mcl_mapgen.end_.max,
		decoration = "mcl_end:chorus_flower",
		height = 1,
		biomes = { "End" },
	})

	deco_id_chorus_plant = minetest.get_decoration_id("mcl_biomes:chorus_plant")
	minetest.set_gen_notify({decoration=true}, { deco_id_chorus_plant })

	-- TODO: End cities

end


--
-- Detect mapgen to select functions
--

local chorus_perlin_noise

if not mcl_mapgen.singlenode then
	if not superflat then
		if not mcl_mapgen.v6 then
			register_biomes()
			register_biomelike_ores()
		end
		register_biome_ores()
		if not mcl_mapgen.v6 then
			register_decorations()
		end
	else
		-- Implementation of Minecraft's Superflat mapgen, classic style:
		-- * Perfectly flat land, 1 grass biome, no decorations, no caves
		-- * 4 layers, from top to bottom: grass block, dirt, dirt, bedrock
		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

	if deco_id_chorus_plant then
		mcl_mapgen.register_mapgen_block_lvm(function(vm_context)
			vm_context.gennotify = vm_context.gennotify or minetest.get_mapgen_object("gennotify")
			local gennotify = vm_context.gennotify
			for _, pos in pairs(gennotify["decoration#"..deco_id_chorus_plant] or {}) do
				chorus_perlin_noise = chorus_perlin_noise or minetest_get_perlin(chorus_noise_params)
				local realpos = { x = pos.x, y = pos.y + 1, z = pos.z }
				local noise = chorus_perlin_noise:get_3d(realpos)
				local pr = PseudoRandom(math_floor(math_abs(noise * 32767)) % 32768)
				minetest.after(1, mcl_end.grow_chorus_plant, realpos, false, pr)
			end
			return vm_context
		end, mcl_mapgen.order.CHORUS)
	end

end
