forked from VoxeLibre/VoxeLibre
Merge pull request 'Alternative solution to fix crash on nether portal destruction' (#2029) from ryvnf-portal-removal into master
Reviewed-on: MineClone2/MineClone2#2029
This commit is contained in:
commit
e8ff33a741
|
@ -204,37 +204,52 @@ local function get_target(p)
|
|||
end
|
||||
end
|
||||
|
||||
-- Destroy portal if pos (portal frame or portal node) got destroyed
|
||||
-- Destroy a nether portal. Connected portal nodes are searched and removed
|
||||
-- using 'bulk_set_node'. This function is called from 'after_destruct' of
|
||||
-- nether portal nodes. The flag 'destroying_portal' is used to avoid this
|
||||
-- function being called recursively through callbacks in 'bulk_set_node'.
|
||||
local destroying_portal = false
|
||||
local function destroy_nether_portal(pos, node)
|
||||
if not node then return end
|
||||
local nn, orientation = node.name, node.param2
|
||||
local obsidian = nn == OBSIDIAN
|
||||
|
||||
local function check_remove(pos, orientation)
|
||||
local node = get_node(pos)
|
||||
if node and (node.name == PORTAL and (orientation == nil or (node.param2 == orientation))) then
|
||||
minetest.remove_node(pos)
|
||||
remove_exit(pos)
|
||||
end
|
||||
end
|
||||
if obsidian then -- check each of 6 sides of it and destroy every portal:
|
||||
check_remove({x = pos.x - 1, y = pos.y, z = pos.z}, 0)
|
||||
check_remove({x = pos.x + 1, y = pos.y, z = pos.z}, 0)
|
||||
check_remove({x = pos.x, y = pos.y, z = pos.z - 1}, 1)
|
||||
check_remove({x = pos.x, y = pos.y, z = pos.z + 1}, 1)
|
||||
check_remove({x = pos.x, y = pos.y - 1, z = pos.z})
|
||||
check_remove({x = pos.x, y = pos.y + 1, z = pos.z})
|
||||
if destroying_portal then
|
||||
return
|
||||
end
|
||||
destroying_portal = true
|
||||
|
||||
local orientation = node.param2
|
||||
local checked_tab = { [minetest.hash_node_position(pos)] = true }
|
||||
local nodes = { pos }
|
||||
|
||||
local function check_remove(pos)
|
||||
local h = minetest.hash_node_position(pos)
|
||||
if checked_tab[h] then
|
||||
return
|
||||
end
|
||||
|
||||
local node = minetest.get_node(pos)
|
||||
if node and node.name == PORTAL and (orientation == nil or node.param2 == orientation) then
|
||||
table.insert(nodes, pos)
|
||||
checked_tab[h] = true
|
||||
end
|
||||
end
|
||||
|
||||
local i = 1
|
||||
while i <= #nodes do
|
||||
pos = nodes[i]
|
||||
if orientation == 0 then
|
||||
check_remove({x = pos.x - 1, y = pos.y, z = pos.z}, 0)
|
||||
check_remove({x = pos.x + 1, y = pos.y, z = pos.z}, 0)
|
||||
check_remove({x = pos.x - 1, y = pos.y, z = pos.z})
|
||||
check_remove({x = pos.x + 1, y = pos.y, z = pos.z})
|
||||
else
|
||||
check_remove({x = pos.x, y = pos.y, z = pos.z - 1}, 1)
|
||||
check_remove({x = pos.x, y = pos.y, z = pos.z + 1}, 1)
|
||||
check_remove({x = pos.x, y = pos.y, z = pos.z - 1})
|
||||
check_remove({x = pos.x, y = pos.y, z = pos.z + 1})
|
||||
end
|
||||
check_remove({x = pos.x, y = pos.y - 1, z = pos.z})
|
||||
check_remove({x = pos.x, y = pos.y + 1, z = pos.z})
|
||||
remove_exit(pos)
|
||||
i = i + 1
|
||||
end
|
||||
|
||||
minetest.bulk_set_node(nodes, { name = "air" })
|
||||
destroying_portal = false
|
||||
end
|
||||
|
||||
local on_rotate
|
||||
|
@ -817,7 +832,23 @@ local usagehelp = S("To open a Nether portal, place an upright frame of obsidian
|
|||
minetest.override_item(OBSIDIAN, {
|
||||
_doc_items_longdesc = longdesc,
|
||||
_doc_items_usagehelp = usagehelp,
|
||||
after_destruct = destroy_nether_portal,
|
||||
after_destruct = function(pos, node)
|
||||
local function check_remove(pos, orientation)
|
||||
local node = get_node(pos)
|
||||
if node and node.name == PORTAL then
|
||||
minetest.remove_node(pos)
|
||||
end
|
||||
end
|
||||
|
||||
-- check each of 6 sides of it and destroy every portal
|
||||
check_remove({x = pos.x - 1, y = pos.y, z = pos.z})
|
||||
check_remove({x = pos.x + 1, y = pos.y, z = pos.z})
|
||||
check_remove({x = pos.x, y = pos.y, z = pos.z - 1})
|
||||
check_remove({x = pos.x, y = pos.y, z = pos.z + 1})
|
||||
check_remove({x = pos.x, y = pos.y - 1, z = pos.z})
|
||||
check_remove({x = pos.x, y = pos.y + 1, z = pos.z})
|
||||
end,
|
||||
|
||||
_on_ignite = function(user, pointed_thing)
|
||||
local x, y, z = pointed_thing.under.x, pointed_thing.under.y, pointed_thing.under.z
|
||||
-- Check empty spaces around obsidian and light all frames found:
|
||||
|
|
Loading…
Reference in New Issue