Nether portals now work without corners, too

This commit is contained in:
Wuzzy 2017-08-17 15:08:07 +02:00
parent f2bee2286f
commit 130f05b9cd

View File

@ -23,17 +23,17 @@ local destroy_portal = function(pos)
return return
end end
local first = true local counter = 1
-- p1 metadata of first node
local mp1 local mp1
for x = p1.x, p2.x do for x = p1.x, p2.x do
for y = p1.y, p2.y do for y = p1.y, p2.y do
for z = p1.z, p2.z do for z = p1.z, p2.z do
local p = vector.new(x, y, z) local p = vector.new(x, y, z)
local m = minetest.get_meta(p) local m = minetest.get_meta(p)
if first then if counter == 2 then
--[[ Only proceed if the first node still has metadata. --[[ Only proceed if the second node still has metadata.
(first node is a corner and not needed for the portal)
If it doesn't have metadata, another node propably triggred the delection If it doesn't have metadata, another node propably triggred the delection
routine earlier, so we bail out earlier to avoid an infinite cascade routine earlier, so we bail out earlier to avoid an infinite cascade
of on_destroy events. ]] of on_destroy events. ]]
@ -53,7 +53,7 @@ local destroy_portal = function(pos)
m:set_string("portal_frame2", "") m:set_string("portal_frame2", "")
m:set_string("portal_target", "") m:set_string("portal_target", "")
end end
first = false counter = counter + 1
end end
end end
end end
@ -139,13 +139,15 @@ local function build_portal(pos, target)
for x = p1.x, p2.x do for x = p1.x, p2.x do
for y = p1.y, p2.y do for y = p1.y, p2.y do
p = {x = x, y = y, z = p1.z} p = {x = x, y = y, z = p1.z}
if not (x == p1.x or x == p2.x or y == p1.y or y == p2.y) then if not ((x == p1.x or x == p2.x) and (y == p1.y or y == p2.y)) then
minetest.set_node(p, {name = "mcl_portals:portal", param2 = 0}) if not (x == p1.x or x == p2.x or y == p1.y or y == p2.y) then
minetest.set_node(p, {name = "mcl_portals:portal", param2 = 0})
end
local meta = minetest.get_meta(p)
meta:set_string("portal_frame1", minetest.pos_to_string(p1))
meta:set_string("portal_frame2", minetest.pos_to_string(p2))
meta:set_string("portal_target", minetest.pos_to_string(target))
end end
local meta = minetest.get_meta(p)
meta:set_string("portal_frame1", minetest.pos_to_string(p1))
meta:set_string("portal_frame2", minetest.pos_to_string(p2))
meta:set_string("portal_target", minetest.pos_to_string(target))
if y ~= p1.y then if y ~= p1.y then
for z = -2, 2 do for z = -2, 2 do
@ -189,20 +191,25 @@ end
local function move_check(p1, max, dir) local function move_check(p1, max, dir)
local p = {x = p1.x, y = p1.y, z = p1.z} local p = {x = p1.x, y = p1.y, z = p1.z}
local d = math.abs(max - p1[dir]) / (max - p1[dir]) local d = math.sign(max - p1[dir])
local min = p[dir]
while p[dir] ~= max do for k = min, max, d do
p[dir] = p[dir] + d p[dir] = k
if minetest.get_node(p).name ~= "mcl_core:obsidian" then local node = minetest.get_node(p)
-- Check for obsidian (except at corners)
if k ~= min and k ~= max and node.name ~= "mcl_core:obsidian" then
return false return false
end end
-- Abort if any of the portal frame blocks already has metadata. -- Abort if any of the portal frame blocks already has metadata.
-- This mod does not yet portals which neighbor each other directly. -- This mod does not yet portals which neighbor each other directly.
-- TODO: Reorganize the way how portal frame coordinates are stored. -- TODO: Reorganize the way how portal frame coordinates are stored.
local meta = minetest.get_meta(p) if node.name == "mcl_core:obsidian" then
local p1 = meta:get_string("portal_frame1") local meta = minetest.get_meta(p)
if minetest.string_to_pos(p1) ~= nil then local pframe1 = meta:get_string("portal_frame1")
return false if minetest.string_to_pos(pframe1) ~= nil then
return false
end
end end
end end
@ -289,16 +296,17 @@ local function make_portal(pos)
target.y = find_nether_target_y(target.x, target.z) target.y = find_nether_target_y(target.x, target.z)
end end
for d = 0, 3 do local dmin, dmax, ymin, ymax = 0, 3, p1.y, p2.y
for y = p1.y, p2.y do for d = dmin, dmax do
local p = {} for y = ymin, ymax do
if not ((d == dmin or d == dmax) and (y == ymin or y == ymax)) then
local p
if param2 == 0 then if param2 == 0 then
p = {x = p1.x + d, y = y, z = p1.z} p = {x = p1.x + d, y = y, z = p1.z}
else else
p = {x = p1.x, y = y, z = p1.z + d} p = {x = p1.x, y = y, z = p1.z + d}
end end
if minetest.get_node(p).name == "air" if minetest.get_node(p).name == "air" then
then
minetest.set_node(p, {name = "mcl_portals:portal", param2 = param2}) minetest.set_node(p, {name = "mcl_portals:portal", param2 = param2})
end end
local meta = minetest.get_meta(p) local meta = minetest.get_meta(p)
@ -311,6 +319,7 @@ local function make_portal(pos)
meta:set_string("portal_target", minetest.pos_to_string(target)) meta:set_string("portal_target", minetest.pos_to_string(target))
end end
end end
end
return true return true
end end