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
|
||||||
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)
|
local function destroy_nether_portal(pos, node)
|
||||||
if not node then return end
|
if destroying_portal then
|
||||||
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})
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if orientation == 0 then
|
destroying_portal = true
|
||||||
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)
|
local orientation = node.param2
|
||||||
else
|
local checked_tab = { [minetest.hash_node_position(pos)] = true }
|
||||||
check_remove({x = pos.x, y = pos.y, z = pos.z - 1}, 1)
|
local nodes = { pos }
|
||||||
check_remove({x = pos.x, y = pos.y, z = pos.z + 1}, 1)
|
|
||||||
|
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
|
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})
|
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})
|
||||||
|
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})
|
||||||
|
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
|
end
|
||||||
|
|
||||||
local on_rotate
|
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, {
|
minetest.override_item(OBSIDIAN, {
|
||||||
_doc_items_longdesc = longdesc,
|
_doc_items_longdesc = longdesc,
|
||||||
_doc_items_usagehelp = usagehelp,
|
_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)
|
_on_ignite = function(user, pointed_thing)
|
||||||
local x, y, z = pointed_thing.under.x, pointed_thing.under.y, pointed_thing.under.z
|
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:
|
-- Check empty spaces around obsidian and light all frames found:
|
||||||
|
|
Loading…
Reference in New Issue