Spawn portals on the surface, when possible

This commit is contained in:
Treer 2019-07-03 00:53:47 +10:00 committed by SmallJoker
parent 9a4c7ed875
commit 2113d332f8

View File

@ -470,10 +470,14 @@ local function volume_is_natural(minp, maxp)
local id = data[vi] -- Existing node local id = data[vi] -- Existing node
if id ~= c_air and id ~= c_ignore then -- These are natural if id ~= c_air and id ~= c_ignore then -- These are natural
local name = minetest.get_name_from_content_id(id) local name = minetest.get_name_from_content_id(id)
if not minetest.registered_nodes[name].is_ground_content then local nodedef = minetest.registered_nodes[name]
if not nodedef.is_ground_content then
-- trees are natural but not "ground content"
if nodedef.groups == nil or (nodedef.groups.tree == nil and nodedef.groups.leaves == nil) then
return false return false
end end
end end
end
vi = vi + 1 vi = vi + 1
end end
end end
@ -526,7 +530,7 @@ and are exploring the nether. The player will not be trapped.
Note that MC also often places portals embedded in stone. Note that MC also often places portals embedded in stone.
The code could be altered to first try to find a surface position, but if this surface position is The code could be [edit: has been] altered to first try to find a surface position, but if this surface position is
unsuitable due to being near player builds, the portal will still move downwards into the ground, so this is unsuitable due to being near player builds, the portal will still move downwards into the ground, so this is
unavoidable. unavoidable.
@ -548,7 +552,23 @@ searches may happen if there a lot of underground player builds present. So the
intensive procedures." intensive procedures."
-- https://github.com/minetest-mods/nether/issues/5#issuecomment-506983676 -- https://github.com/minetest-mods/nether/issues/5#issuecomment-506983676
]] ]]
local function find_surface_target_y(portal_definition, target_x, target_z, start_y) local function find_surface_target_y(portal_definition, target_x, target_z)
-- try to spawn on surface first
if minetest.get_spawn_level ~= nil then -- older versions of Minetest don't have this
local surface_level = minetest.get_spawn_level(target_x, target_z)
if surface_level ~= nil then
-- Check volume for non-natural nodes
local minp = {x = target_x - 1, y = surface_level - 1, z = target_z - 2}
local maxp = {x = target_x + 2, y = surface_level + 3, z = target_z + 2}
if volume_is_natural(minp, maxp) then
return surface_level
end
end
end
-- fallback to underground search
local start_y = -16
for y = start_y, start_y - 256, -16 do for y = start_y, start_y - 256, -16 do
-- Check volume for non-natural nodes -- Check volume for non-natural nodes
local minp = {x = target_x - 1, y = y - 1, z = target_z - 2} local minp = {x = target_x - 1, y = y - 1, z = target_z - 2}
@ -597,7 +617,7 @@ local function ignite_portal(ignition_pos)
-- pick a destination -- pick a destination
local destination_wormholePos = portal_definition.shape.get_wormholePos_from_anchorPos(anchorPos, orientation) local destination_wormholePos = portal_definition.shape.get_wormholePos_from_anchorPos(anchorPos, orientation)
if anchorPos.y < NETHER_DEPTH then if anchorPos.y < NETHER_DEPTH then
destination_wormholePos.y = find_surface_target_y(portal_definition, destination_wormholePos.x, destination_wormholePos.z, -16) destination_wormholePos.y = find_surface_target_y(portal_definition, destination_wormholePos.x, destination_wormholePos.z)
else else
local start_y = NETHER_DEPTH - math.random(500, 1500) -- Search start local start_y = NETHER_DEPTH - math.random(500, 1500) -- Search start
destination_wormholePos.y = find_nether_target_y(destination_wormholePos.x, destination_wormholePos.z, start_y) destination_wormholePos.y = find_nether_target_y(destination_wormholePos.x, destination_wormholePos.z, start_y)