Doors: Allow falling nodes to fall onto doors.
authorAuke Kok <sofar@foo-projects.org>
Tue, 15 Mar 2016 04:27:32 +0000 (21:27 -0700)
committerparamat <mat.gregory@virginmedia.com>
Mon, 21 Mar 2016 06:17:27 +0000 (06:17 +0000)
We were cleverly attempting to use an airlike node as the
top half of the doors, but as airlike nodes are not walkable,
falling nodes would not stop falling and thus remain an entity
stuck on top of a door.

After inspecting the builtin/game/falling.lua code, I considered
the remaining options: (a) revert doors such that the top part is
actually the door, (b) play with nodedef fields and see if other
flags may work, or (c) modify the hidden door part to another
drawtype that properly prevents this issue.

(a) seemed way over the top for now, although it would solve the
issue, it would cause a rewrite of most of the code including the
old-door-conversion.

(b) turned up nothing.

(c) turned out to be relatively simple.

So, here's the implementation where I turn the hidden door top
into a tiny, non-targetable but walkable nodebox that is entirely
inside the door hinge. It's entirely transparent, so you still
can't see it, can't hit it, nor can you place anything in it or
make liquids flow through it. The top part is placed in the right
position on placement and not touched further.

Falling nodes will properly stop on top of these doors. I've
adjusted the door conversion code to properly account for the
issue as well, so the only thing remaining is people who have
been running a git branch - those can upgrade by re-placing the
door.

mods/doors/init.lua
mods/doors/textures/doors_blank.png [new file with mode: 0644]

index 6e624e9ed6923f0e34afd55138b82b6b4c502a1c..bd3e69985f7f4bf5e14755fddeac8b7c62df5ac8 100644 (file)
@@ -74,17 +74,32 @@ end
 -- nodes from being placed in the top half of the door.
 minetest.register_node("doors:hidden", {
        description = "Hidden Door Segment",
-       drawtype = "airlike",
+       -- can't use airlike otherwise falling nodes will turn to entities
+       -- and will be forever stuck until door is removed.
+       drawtype = "nodebox",
        paramtype = "light",
+       paramtype2 = "facedir",
        sunlight_propagates = true,
-       walkable = false,
+       -- has to be walkable for falling nodes to stop falling.
+       walkable = true,
        pointable = false,
        diggable = false,
        buildable_to = false,
        floodable = false,
        drop = "",
-       groups = { not_in_creative_inventory = 1 },
-       on_blast = function() end
+       groups = {not_in_creative_inventory = 1},
+       on_blast = function() end,
+       tiles = {"doors_blank.png"},
+       -- 1px transparent block inside door hinge near node top.
+       nodebox = {
+               type = "fixed",
+               fixed = {-15/32, 13/32, -15/32, -13/32, 1/2, -13/32},
+       },
+       -- collision_box needed otherise selection box would be full node size
+       collision_box = {
+               type = "fixed",
+               fixed = {-15/32, 13/32, -15/32, -13/32, 1/2, -13/32},
+       },
 })
 
 -- table used to aid door opening/closing
@@ -196,8 +211,21 @@ function doors.register(name, def)
                        -- retain infotext and doors_owner fields
                        minetest.swap_node(pos, {name = name .. "_" .. new.type, param2 = p2})
                        meta:set_int("state", new.state)
+                       -- properly place doors:hidden at the right spot
+                       local p3 = p2
+                       if new.state >= 2 then
+                               p3 = (p3 + 3) % 4
+                       end
+                       if new.state % 2 == 1 then
+                               if new.state >= 2 then
+                                       p3 = (p3 + 1) % 4
+                               else
+                                       p3 = (p3 + 3) % 4
+                               end
+                       end
                        -- wipe meta on top node as it's unused
-                       minetest.set_node({x = pos.x, y = pos.y + 1, z = pos.z}, { name = "doors:hidden" })
+                       minetest.set_node({x = pos.x, y = pos.y + 1, z = pos.z},
+                               {name = "doors:hidden", param2 = p3})
                end
        })
 
@@ -259,10 +287,11 @@ function doors.register(name, def)
                        if minetest.get_item_group(minetest.get_node(aside).name, "door") == 1 then
                                state = state + 2
                                minetest.set_node(pos, {name = name .. "_b", param2 = dir})
+                               minetest.set_node(above, {name = "doors:hidden", param2 = (dir + 3) % 4})
                        else
                                minetest.set_node(pos, {name = name .. "_a", param2 = dir})
+                               minetest.set_node(above, {name = "doors:hidden", param2 = dir})
                        end
-                       minetest.set_node(above, { name = "doors:hidden" })
 
                        local meta = minetest.get_meta(pos)
                        meta:set_int("state", state)
@@ -322,7 +351,8 @@ function doors.register(name, def)
                _doors.door_toggle(pos, clicker)
        end
        def.after_dig_node = function(pos, node, meta, digger)
-               minetest.remove_node({ x = pos.x, y = pos.y + 1, z = pos.z})
+               minetest.remove_node({x = pos.x, y = pos.y + 1, z = pos.z})
+               nodeupdate({x = pos.x, y = pos.y + 1, z = pos.z})
        end
        def.can_dig = function(pos, player)
                return can_dig(pos, player)
diff --git a/mods/doors/textures/doors_blank.png b/mods/doors/textures/doors_blank.png
new file mode 100644 (file)
index 0000000..1914264
Binary files /dev/null and b/mods/doors/textures/doors_blank.png differ