From 6017510df08438e1456d6a4a551c85f31289f318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20C?= Date: Sun, 11 Feb 2024 08:40:48 +0100 Subject: [PATCH] Re-implement minetest.get_spawn_level --- init.lua | 1 + spawn.lua | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 spawn.lua diff --git a/init.lua b/init.lua index c8c2886..df67d75 100644 --- a/init.lua +++ b/init.lua @@ -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) diff --git a/spawn.lua b/spawn.lua new file mode 100644 index 0000000..d9704ba --- /dev/null +++ b/spawn.lua @@ -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