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 NETHER_DEPTH = -5000
local TCAVE = 0.6 local TCAVE = 0.6
local BLEND = 128 local BLEND = 128
local DEBUG = true local DEBUG = false
-- 3D noise -- 3D noise
@ -77,14 +77,15 @@ netherportal = {} -- portal API
A better location for AnchorPos would be directly under WormholePos, as it's more centered 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 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 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 Orientation is 0 or 90, 0 meaning a portal that faces north/south - i.e. obsidian running
east/west. 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 -- 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(). -- 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 -- 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)) 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. -- 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 -- 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 -- the frame, and legacy portals don't have this extra metadata - indicating obsidian,
-- and reading this from the metadata saves an extra call to minetest.getnode(). -- 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) meta:set_string("frame_node_name", portal_definition.frame_node_name)
end 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. 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 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 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}
local maxp = {x = target_x + 2, y = y + 3, z = target_z + 2} local maxp = {x = target_x + 2, y = y + 3, z = target_z + 2}
if volume_is_natural(minp, maxp) then if volume_is_natural(minp, maxp) then
return y 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
end end
@ -557,7 +566,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(destination_wormholePos.x, destination_wormholePos.z, -16) destination_wormholePos.y = find_surface_target_y(portal_definition, destination_wormholePos.x, destination_wormholePos.z, -16)
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)
@ -776,7 +785,7 @@ minetest.register_lbm({
nodenames = {"nether:portal"}, nodenames = {"nether:portal"},
run_at_every_load = false, run_at_every_load = false,
action = function(pos, node) action = function(pos, node)
local p1 local p1, p2
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
if meta ~= nil then if meta ~= nil then
p1 = minetest.string_to_pos(meta:get_string("p1")) p1 = minetest.string_to_pos(meta:get_string("p1"))