Re-implement minetest.get_spawn_level

This commit is contained in:
Gaël C 2024-02-11 08:40:48 +01:00
parent 70418f9526
commit 6017510df0
2 changed files with 78 additions and 0 deletions

View File

@ -11,5 +11,6 @@ dofile(modpath .. 'gridmanager.lua')
dofile(modpath .. 'polygons.lua')
dofile(modpath .. 'heightmap.lua')
dofile(modpath .. 'mapgen.lua')
dofile(modpath .. 'spawn.lua')
minetest.register_on_mods_loaded(mapgen_rivers.load_or_generate_grid)

77
spawn.lua Normal file
View File

@ -0,0 +1,77 @@
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