forked from mtcontrib/homedecor_modpack
Detecting whether existing doors are closed
Got calculate closed working Fixed isSolid, figured out when closed has not been set, added a way to reset closed by punching for debugging
This commit is contained in:
parent
47d98410b5
commit
51e88d5d2d
@ -11,19 +11,145 @@ end
|
|||||||
|
|
||||||
-- doors
|
-- doors
|
||||||
|
|
||||||
|
function isSolid(pos,adj)
|
||||||
|
adj = vector.new(adj[1],adj[2],adj[3])
|
||||||
|
local node = minetest.get_node(vector.add(pos,adj))
|
||||||
|
if node then
|
||||||
|
local idef = minetest.registered_nodes[minetest.get_node(vector.add(pos,adj)).name]
|
||||||
|
print('doop')
|
||||||
|
if idef then
|
||||||
|
return idef.walkable
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function countSolids(pos,node,level)
|
||||||
|
local solids = 0
|
||||||
|
for x = -1, 1 do
|
||||||
|
for z = -1, 1 do
|
||||||
|
local y = 0
|
||||||
|
if node.param2 == 5 then
|
||||||
|
y = -level
|
||||||
|
else
|
||||||
|
y = level
|
||||||
|
end
|
||||||
|
-- special cases when x == z == 0
|
||||||
|
if x == 0 and z == 0 then
|
||||||
|
if level == 1 then
|
||||||
|
-- when looking past the trap door, cannot be solid in center
|
||||||
|
if isSolid(pos,{x,y,z}) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
-- no else. it doesn't matter if x == y == z is solid, that's us.
|
||||||
|
end
|
||||||
|
elseif isSolid(pos,{x,y,z}) then
|
||||||
|
solids = solids + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return solids
|
||||||
|
end
|
||||||
|
|
||||||
|
function calculateClosed(pos)
|
||||||
|
local node = minetest.get_node(pos)
|
||||||
|
-- the door is considered closed if it is closing off something.
|
||||||
|
|
||||||
|
local solids = 0
|
||||||
|
local direction = node.param2 % 6
|
||||||
|
local isTrap = direction == 0 or direction == 5
|
||||||
|
if isTrap then
|
||||||
|
-- the trap door is considered closed when all nodes on its sides are solid
|
||||||
|
-- or all nodes in the 3x3 above/below it are solid except the center
|
||||||
|
for levels = 0, 1 do
|
||||||
|
local fail = false
|
||||||
|
local solids = countSolids(pos,node,level)
|
||||||
|
if solids == 8 then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
else
|
||||||
|
-- the door is considered closed when the nodes on its sides are solid
|
||||||
|
-- or the 3 nodes in its facing direction are solid nonsolid solid
|
||||||
|
-- if the door has two levels (i.e. not a gate) then this must
|
||||||
|
-- be true for the top node as well.
|
||||||
|
|
||||||
|
-- sorry I dunno the math to figure whether to x or z
|
||||||
|
if direction == 1 or direction == 2 then
|
||||||
|
if isSolid(pos,{0,0,-1}) and isSolid(pos,{0,0,1}) then
|
||||||
|
if string.find(node.name,'_bottom_') then
|
||||||
|
return calculateClosed({x=pos.x,y=pos.y+1,z=pos.z})
|
||||||
|
else
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local x
|
||||||
|
if direction == 1 then
|
||||||
|
x = 1
|
||||||
|
else
|
||||||
|
x = -1
|
||||||
|
end
|
||||||
|
if isSolid(pos,{x,0,-1}) and not isSolid(pos,{x,0,0}) and isSolid(pos,{x,0,1}) then
|
||||||
|
if string.find(node.name,'_bottom_') then
|
||||||
|
return calculateClosed({x=pos.x,y=pos.y+1,z=pos.z})
|
||||||
|
else
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
else
|
||||||
|
-- direction == 3 or 4
|
||||||
|
if isSolid(pos,{-1,0,0}) and isSolid(pos,{1,0,0}) then
|
||||||
|
if string.find(node.name,'_bottom_') then
|
||||||
|
return calculateClosed({x=pos.x,y=pos.y+1,z=pos.z})
|
||||||
|
else
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local z
|
||||||
|
if direction == 3 then
|
||||||
|
z = 1
|
||||||
|
else
|
||||||
|
z = -1
|
||||||
|
end
|
||||||
|
if isSolid(pos,{-1,0,z}) and not isSolid(pos,{0,0,z}) and isSolid(pos,{1,0,z}) then
|
||||||
|
if string.find(node.name,'_bottom_') then
|
||||||
|
return calculateClosed({x=pos.x,y=pos.y+1,z=pos.z})
|
||||||
|
else
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
error("What direction is this???",direction)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- isClosed flag, is 0 or 1 0 = open, 1 = closed
|
-- isClosed flag, is 0 or 1 0 = open, 1 = closed
|
||||||
function getClosed(pos)
|
function getClosed(pos)
|
||||||
local isClosed = minetest.get_meta(pos):get_int('closed')
|
local isClosed = minetest.get_meta(pos):get_string('closed')
|
||||||
if isClosed == nil then
|
print('closed!'..isClosed)
|
||||||
-- doors when unknown, are closed.
|
assert(pos)
|
||||||
return 1
|
if isClosed=='' then
|
||||||
|
if calculateClosed(pos) then
|
||||||
|
return true
|
||||||
else
|
else
|
||||||
-- may be closed or open (0 or 1)
|
return false
|
||||||
return isClosed
|
end
|
||||||
|
else
|
||||||
|
isClosed = tonumber(isClosed)
|
||||||
|
-- may be closed or open (1 or 0)
|
||||||
|
return isClosed == 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function addDoorNode(pos,def,isClosed)
|
function addDoorNode(pos,def,isClosed)
|
||||||
|
if isClosed then
|
||||||
|
isClosed = 1
|
||||||
|
else
|
||||||
|
isClosed = 0
|
||||||
|
end
|
||||||
minetest.add_node(pos, def)
|
minetest.add_node(pos, def)
|
||||||
minetest.get_meta(pos):set_int('closed',isClosed)
|
minetest.get_meta(pos):set_int('closed',isClosed)
|
||||||
end
|
end
|
||||||
@ -112,28 +238,8 @@ for i in ipairs(sides) do
|
|||||||
end,
|
end,
|
||||||
on_rightclick = function(pos, node, clicker)
|
on_rightclick = function(pos, node, clicker)
|
||||||
homedecor_flip_door({x=pos.x, y=pos.y-1, z=pos.z}, node, clicker, doorname, side)
|
homedecor_flip_door({x=pos.x, y=pos.y-1, z=pos.z}, node, clicker, doorname, side)
|
||||||
end,
|
end
|
||||||
|
|
||||||
-- both left and right doors may be used for open or closed doors
|
|
||||||
-- so they have to have both action_on and action_off and just
|
|
||||||
-- check when that action is invoked if to continue
|
|
||||||
|
|
||||||
mesecons = {
|
|
||||||
effector = {
|
|
||||||
action_on = function(pos,node)
|
|
||||||
local isClosed = getClosed(pos)
|
|
||||||
if isClosed==1 then
|
|
||||||
homedecor_flip_door(pos,node,nil,doorname,side,isClosed)
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
action_off = function(pos,node)
|
|
||||||
local isClosed = getClosed(pos)
|
|
||||||
if isClosed==0 then
|
|
||||||
homedecor_flip_door(pos,node,nil,doorname,side,isClosed)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_node("homedecor:door_"..doorname.."_bottom_"..side, {
|
minetest.register_node("homedecor:door_"..doorname.."_bottom_"..side, {
|
||||||
@ -163,7 +269,32 @@ for i in ipairs(sides) do
|
|||||||
end,
|
end,
|
||||||
on_rightclick = function(pos, node, clicker)
|
on_rightclick = function(pos, node, clicker)
|
||||||
homedecor_flip_door(pos, node, clicker, doorname, side)
|
homedecor_flip_door(pos, node, clicker, doorname, side)
|
||||||
|
end,
|
||||||
|
-- both left and right doors may be used for open or closed doors
|
||||||
|
-- so they have to have both action_on and action_off and just
|
||||||
|
-- check when that action is invoked if to continue
|
||||||
|
|
||||||
|
on_punch = function(pos, node, puncher)
|
||||||
|
print('erasing closed status')
|
||||||
|
minetest.get_meta(pos):set_string('closed',nil)
|
||||||
|
end,
|
||||||
|
mesecons = {
|
||||||
|
effector = {
|
||||||
|
action_on = function(pos,node)
|
||||||
|
local isClosed = getClosed(pos)
|
||||||
|
if isClosed then
|
||||||
|
print('closing')
|
||||||
|
homedecor_flip_door(pos,node,nil,doorname,side,isClosed)
|
||||||
end
|
end
|
||||||
|
end,
|
||||||
|
action_off = function(pos,node)
|
||||||
|
local isClosed = getClosed(pos)
|
||||||
|
if not isClosed then
|
||||||
|
homedecor_flip_door(pos,node,nil,doorname,side,isClosed)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -319,7 +450,7 @@ function homedecor_place_door(itemstack, placer, pointed_thing, name, side)
|
|||||||
else
|
else
|
||||||
local fdir = minetest.dir_to_facedir(placer:get_look_dir())
|
local fdir = minetest.dir_to_facedir(placer:get_look_dir())
|
||||||
local def = { name = "homedecor:door_"..name.."_bottom_"..side, param2=fdir}
|
local def = { name = "homedecor:door_"..name.."_bottom_"..side, param2=fdir}
|
||||||
addDoorNode(pos1, def, 1)
|
addDoorNode(pos1, def, true)
|
||||||
minetest.add_node(pos2, { name = "homedecor:door_"..name.."_top_"..side, param2=fdir})
|
minetest.add_node(pos2, { name = "homedecor:door_"..name.."_top_"..side, param2=fdir})
|
||||||
if not homedecor_expect_infinite_stacks then
|
if not homedecor_expect_infinite_stacks then
|
||||||
itemstack:take_item()
|
itemstack:take_item()
|
||||||
@ -337,6 +468,14 @@ end
|
|||||||
-- also adjusting param2 so the node is at 90 degrees.
|
-- also adjusting param2 so the node is at 90 degrees.
|
||||||
|
|
||||||
function homedecor_flip_door(pos, node, player, name, side, isClosed)
|
function homedecor_flip_door(pos, node, player, name, side, isClosed)
|
||||||
|
if isClosed == nil then
|
||||||
|
isClosed = getClosed(pos)
|
||||||
|
end
|
||||||
|
-- this is where we swap the isClosed status!
|
||||||
|
-- i.e. if isClosed, we're adding an open door
|
||||||
|
-- and if not isClosed, a closed door
|
||||||
|
isClosed = not isClosed
|
||||||
|
|
||||||
local rside = nil
|
local rside = nil
|
||||||
local nfdir = nil
|
local nfdir = nil
|
||||||
if side == "left" then
|
if side == "left" then
|
||||||
@ -354,7 +493,7 @@ function homedecor_flip_door(pos, node, player, name, side, isClosed)
|
|||||||
else
|
else
|
||||||
sound = 'open'
|
sound = 'open'
|
||||||
end
|
end
|
||||||
minetest.sound_play("homedecor_door_"+sound, {
|
minetest.sound_play("homedecor_door_"..sound, {
|
||||||
pos=pos,
|
pos=pos,
|
||||||
max_hear_distance = 5,
|
max_hear_distance = 5,
|
||||||
gain = 2,
|
gain = 2,
|
||||||
|
Loading…
Reference in New Issue
Block a user