-- The mapgen thread.
-- This makes custom LVM-based adjustments to the mapgen that
-- cannot be done with ores, decorations and biomes alone.
-- This script must be loaded in the mapgen environment,
-- therefore it has only limited access to the Luanti API.

local c_water = minetest.get_content_id("hades_core:water_source")
local c_lava = minetest.get_content_id("hades_core:lava_source")
local c_clay = minetest.get_content_id("hades_core:clay")
local c_gravel_volcanic = minetest.get_content_id("hades_core:gravel_volcanic")

-- Localise VoxelManip data buffer tables outside the loop,
-- to be re-used for all mapchunks, therefore minimising memory use.
local vm_data = {}
local vm_light_data = {}

-- Fetch the node content IDs of all falling nodes beforehand
-- so we can just do a fast lookup at mapgen runtime
local falling_nodes = {}
minetest.register_on_mods_loaded(function()
	for k,v in pairs(minetest.registered_nodes) do
		if minetest.get_item_group(k, "falling_node") ~= 0 then
			local cid = minetest.get_content_id(k)
			falling_nodes[cid] = true
		end
	end
end)

minetest.register_on_generated(function(vmanip, minp, maxp)
	minetest.log("info", "[hades_mapgen] Generating area at " .. minetest.pos_to_string(minp).." in the mapgen environment ...")

	local sidelen_x = maxp.x - minp.x + 1
	local sidelen_z = maxp.z - minp.z + 1

	local emin, emax = vmanip:get_emerged_area()

	local area = VoxelArea:new{MinEdge = emin, MaxEdge = emax}
	vmanip:get_data(vm_data)

	-- Replace falling node above water source with clay,
	-- and falling node above lava source with volcanic gravel.
	for z = minp.z, maxp.z do
		for y = minp.y, maxp.y do
			for x = minp.x, maxp.x do
				local vi = area:index(x, y, z)
				local vi_plus = vi + area.ystride
				if area:containsi(vi_plus) then
					local cid_plus = vm_data[vi_plus]
					if falling_nodes[cid_plus] then
						if vm_data[vi] == c_water then
							vm_data[vi_plus] = c_clay
						elseif vm_data[vi] == c_lava then
							vm_data[vi_plus] = c_gravel_volcanic
						end
					end
				end
			end
		end
	end

	vmanip:set_data(vm_data)
	vmanip:calc_lighting(minp, maxp)
end)

minetest.log("action", "[hades_mapgen] mapgen script successfully run in mapgen environment")
