mirror of
				https://gitlab.com/gaelysam/mapgen_rivers.git
				synced 2025-10-31 00:05:35 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			78 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			78 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
| local np_distort_x = mapgen_rivers.noise_params.distort_x
 | |
| local np_distort_z = mapgen_rivers.noise_params.distort_z
 | |
| local np_distort_amplitude = mapgen_rivers.noise_params.distort_amplitude
 | |
| 
 | |
| local nobj_distort_x, nobj_distort_z, nobj_distort_amplitude
 | |
| 
 | |
| local sea_level = mapgen_rivers.settings.sea_level
 | |
| local distort = mapgen_rivers.settings.distort
 | |
| 
 | |
| -- Linear interpolation
 | |
| local function interp(v00, v01, v11, v10, xf, zf)
 | |
| 	local v0 = v01*xf + v00*(1-xf)
 | |
| 	local v1 = v11*xf + v10*(1-xf)
 | |
| 	return v1*zf + v0*(1-zf)
 | |
| end
 | |
| 
 | |
| local function estimate_spawn_level(pos, use_distort)
 | |
| 	local x, z = pos.x, pos.z
 | |
| 	if distort and use_distort then
 | |
| 		nobj_distort_x = nobj_distort_x or minetest.get_perlin(np_distort_x)
 | |
| 		nobj_distort_z = nobj_distort_z or minetest.get_perlin(np_distort_z)
 | |
| 		nobj_distort_amplitude = nobj_distort_amplitude or minetest.get_perlin(np_distort_amplitude)
 | |
| 
 | |
| 		local amplitude = nobj_distort_amplitude:get_2d({x=pos.x, y=pos.z})
 | |
| 		x = x + nobj_distort_x:get_3d(pos)*amplitude
 | |
| 		z = z + nobj_distort_z:get_3d(pos)*amplitude
 | |
| 	end
 | |
| 
 | |
| 	local terrain, lakes = mapgen_rivers.make_heightmaps(
 | |
| 		{x=math.floor(x),   z=math.floor(z)  },
 | |
| 		{x=math.floor(x)+1, z=math.floor(z)+1}
 | |
| 	)
 | |
| 
 | |
| 	local ex, ez = x % 1, z % 1
 | |
| 	--local h = terrain[1]*(1-ex)*(1-ez) + terrain[2]*ex*(1-ez) + terrain[3]*(1-ex)*ez + terrain[4]*ex*ez
 | |
| 	local h = interp(terrain[1], terrain[2], terrain[4], terrain[3], ex, ez)
 | |
| 	local lake = math.min(lakes[1], lakes[2], lakes[3], lakes[4])
 | |
| 
 | |
| 	if h < lake or h <= sea_level then
 | |
| 		return false, h
 | |
| 	end
 | |
| 
 | |
| 	return true, h
 | |
| end
 | |
| 
 | |
| function minetest.get_spawn_level(x, z)
 | |
| 	local pos = {x=x, z=z}
 | |
| 	local suitable, y = estimate_spawn_level(pos, false)
 | |
| 	if not suitable then
 | |
| 		return
 | |
| 	end
 | |
| 
 | |
| 	if not distort then
 | |
| 		return math.floor(y) + 1
 | |
| 	end
 | |
| 
 | |
| 	local low_bound = -math.huge
 | |
| 	local high_bound = math.huge
 | |
| 	local suitable_high = false
 | |
| 
 | |
| 	repeat
 | |
| 		pos.y = math.max(math.min(math.floor(y+0.5), high_bound-1), low_bound+1)
 | |
| 		suitable, y = estimate_spawn_level(pos, true)
 | |
| 		if y > pos.y then
 | |
| 			low_bound = pos.y
 | |
| 		else
 | |
| 			high_bound = pos.y
 | |
| 			suitable_high = suitable
 | |
| 		end
 | |
| 	until high_bound - low_bound <= 1
 | |
| 
 | |
| 	if not suitable_high then
 | |
| 		return
 | |
| 	end
 | |
| 
 | |
| 	return high_bound
 | |
| end
 |