Allow reignition of portals in player-built areas

e.g. allow remote ignition to a portal in a "portal room"
This commit is contained in:
Treer 2019-06-30 13:55:38 +10:00 committed by SmallJoker
parent 7a4d9ebf01
commit edf961907e

View File

@ -25,7 +25,7 @@
local NETHER_DEPTH = -5000
local TCAVE = 0.6
local BLEND = 128
local DEBUG = true
local DEBUG = false
-- 3D noise
@ -77,14 +77,15 @@ netherportal = {} -- portal API
A better location for AnchorPos would be directly under WormholePos, as it's more centered
and you don't need to know the portal's orientation to find AnchorPos from the WormholePos
or vice-versa, however AnchorPos is in the bottom/south/west-corner to keep compatibility
with earlier versions of this mod (which only records portal corners p1 & p2 in the node metadata).
with earlier versions of nether mod (which only records portal corners p1 & p2 in the node
metadata).
Orientation is 0 or 90, 0 meaning a portal that faces north/south - i.e. obsidian running
east/west.
]]
-- This object defines a portal's shape, segregating the shape logic code from portal physics.
-- This object defines a portal's shape, segregating the shape logic code from portal behaviour code.
-- You can create a new "PortalShape" definition object which implements the same
-- functions if you wish to register a custom shaped portal in register_portal().
-- Since it's symmetric, this PortalShape definition has only implemented orientations of 0 and 90
@ -294,8 +295,9 @@ local function set_portal_metadata(portal_definition, anchorPos, orientation, de
meta:set_string("target", minetest.pos_to_string(destination_wormholePos))
-- including "frame_node_name" in the metadata lets us know which kind of portal this is.
-- It's not strictly necessary for TraditionalPortalShape as we know that p1 is part of
-- the frame, and legacy portals don't have this extra metadata, but p1 isn't always loaded
-- and reading this from the metadata saves an extra call to minetest.getnode().
-- the frame, and legacy portals don't have this extra metadata - indicating obsidian,
-- but p1 isn't always loaded so reading this from the metadata saves an extra call to
-- minetest.getnode().
meta:set_string("frame_node_name", portal_definition.frame_node_name)
end
@ -515,13 +517,20 @@ Also, the search for non-natural nodes doesn't actually guarantee avoiding playe
Each placement position search has to search a volume of nodes for non-natural nodes, this is not lightweight, and many searches may happen if there a lot of underground player builds present. So the code has been written to avoid intensive procedures.
https://github.com/minetest-mods/nether/issues/5#issuecomment-506983676
]]
local function find_surface_target_y(target_x, target_z, start_y)
local function find_surface_target_y(portal_definition, target_x, target_z, start_y)
for y = start_y, start_y - 256, -16 do
-- Check volume for non-natural nodes
local minp = {x = target_x - 1, y = y - 1, z = target_z - 2}
local maxp = {x = target_x + 2, y = y + 3, z = target_z + 2}
if volume_is_natural(minp, maxp) then
return y
else
-- players have built here - don't grief.
-- but reigniting existing portals in portal rooms is fine - desirable even.
local anchorPos, orientation, is_ignited = is_portal_frame(portal_definition, {x = target_x, y = y, z = target_z})
if anchorPos ~= nil then
return y
end
end
end
@ -557,7 +566,7 @@ local function ignite_portal(ignition_pos)
-- pick a destination
local destination_wormholePos = portal_definition.shape.get_wormholePos_from_anchorPos(anchorPos, orientation)
if anchorPos.y < NETHER_DEPTH then
destination_wormholePos.y = find_surface_target_y(destination_wormholePos.x, destination_wormholePos.z, -16)
destination_wormholePos.y = find_surface_target_y(portal_definition, destination_wormholePos.x, destination_wormholePos.z, -16)
else
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)
@ -776,7 +785,7 @@ minetest.register_lbm({
nodenames = {"nether:portal"},
run_at_every_load = false,
action = function(pos, node)
local p1
local p1, p2
local meta = minetest.get_meta(pos)
if meta ~= nil then
p1 = minetest.string_to_pos(meta:get_string("p1"))