mirror of
https://github.com/minetest-mods/mesecons.git
synced 2024-11-19 22:03:52 +01:00
Better mesecon-enabled doors
The mesecons_compatibility doors erred in making steel doors, which are meant to be locked, openable by anyone using a mesecon signal. They also didn't handle mirror-paired doors, and nastily duplicated lots of the standard door code rather than using it and adding to it. Replace mesecons_compatibility with a new system, in which standard doors are left alone and new types of door are added that have mesecon behaviour. The new door types are each available in both wood and steel, using the standard door textures. The mesecon-operated doors open and close according to the mesecon signal they receive: open when the signal is on and closed when off. Unlike the old mesecons_compatibility doors, which only accepted the signal to the bottom half, these accept the signal to either half of the door. A convenient kind of control therefore is a wall-mounted button just above the doorway: the signal flows diagonally down to the top half of the door. The door cannot be operated manually. The mesecon-signalling doors are opened and closed manually, and generate a mesecon signal indicating whether they're open, on when open and off when closed. Thus opening the door can trigger automatic activity. Pairing a mesecon-signalling door with a mesecon-operated door results in a door pair where right-clicking on one door operates both. By making use of the pairing behaviour built into the standard doors mod, which is inherited by the mesecon doors, and placing doors from sideways angles, it is possible to effectively get mesecon doors with the opposite signal sense. For example, a mesecon-signalling door that sends an on signal when closed, turning the signal off when opened.
This commit is contained in:
parent
b64fea4f70
commit
77b8f6514a
@ -1,167 +0,0 @@
|
||||
doors = {}
|
||||
|
||||
-- Registers a door - REDEFINITION ONLY | DOORS MOD MUST HAVE BEEN LOADED BEFORE
|
||||
-- name: The name of the door
|
||||
-- def: a table with the folowing fields:
|
||||
-- description
|
||||
-- inventory_image
|
||||
-- groups
|
||||
-- tiles_bottom: the tiles of the bottom part of the door {front, side}
|
||||
-- tiles_top: the tiles of the bottom part of the door {front, side}
|
||||
-- If the following fields are not defined the default values are used
|
||||
-- node_box_bottom
|
||||
-- node_box_top
|
||||
-- selection_box_bottom
|
||||
-- selection_box_top
|
||||
-- only_placer_can_open: if true only the player who placed the door can
|
||||
-- open it
|
||||
|
||||
function doors:register_door(name, def)
|
||||
def.groups.not_in_creative_inventory = 1
|
||||
|
||||
local box = {{-0.5, -0.5, -0.5, 0.5, 0.5, -0.5+1.5/16}}
|
||||
|
||||
if not def.node_box_bottom then
|
||||
def.node_box_bottom = box
|
||||
end
|
||||
if not def.node_box_top then
|
||||
def.node_box_top = box
|
||||
end
|
||||
if not def.selection_box_bottom then
|
||||
def.selection_box_bottom= box
|
||||
end
|
||||
if not def.selection_box_top then
|
||||
def.selection_box_top = box
|
||||
end
|
||||
|
||||
local tt = def.tiles_top
|
||||
local tb = def.tiles_bottom
|
||||
|
||||
local function after_dig_node(pos, name)
|
||||
if minetest.get_node(pos).name == name then
|
||||
minetest.remove_node(pos)
|
||||
end
|
||||
end
|
||||
|
||||
local function on_rightclick(pos, dir, check_name, replace, replace_dir, params)
|
||||
pos.y = pos.y+dir
|
||||
if not minetest.get_node(pos).name == check_name then
|
||||
return
|
||||
end
|
||||
local p2 = minetest.get_node(pos).param2
|
||||
p2 = params[p2+1]
|
||||
|
||||
local meta = minetest.get_meta(pos):to_table()
|
||||
minetest.set_node(pos, {name=replace_dir, param2=p2})
|
||||
minetest.get_meta(pos):from_table(meta)
|
||||
|
||||
pos.y = pos.y-dir
|
||||
meta = minetest.get_meta(pos):to_table()
|
||||
minetest.set_node(pos, {name=replace, param2=p2})
|
||||
minetest.get_meta(pos):from_table(meta)
|
||||
end
|
||||
|
||||
local function on_mesecons_signal_open (pos, node)
|
||||
on_rightclick(pos, 1, name.."_t_1", name.."_b_2", name.."_t_2", {1,2,3,0})
|
||||
end
|
||||
|
||||
local function on_mesecons_signal_close (pos, node)
|
||||
on_rightclick(pos, 1, name.."_t_2", name.."_b_1", name.."_t_1", {3,0,1,2})
|
||||
end
|
||||
|
||||
local function check_player_priv(pos, player)
|
||||
if not def.only_placer_can_open then
|
||||
return true
|
||||
end
|
||||
local meta = minetest.get_meta(pos)
|
||||
local pn = player:get_player_name()
|
||||
return meta:get_string("doors_owner") == pn
|
||||
end
|
||||
|
||||
minetest.register_node(":"..name.."_b_1", {
|
||||
tiles = {tb[2], tb[2], tb[2], tb[2], tb[1], tb[1].."^[transformfx"},
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
drop = name,
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = def.node_box_bottom
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = def.selection_box_bottom
|
||||
},
|
||||
groups = def.groups,
|
||||
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
pos.y = pos.y+1
|
||||
after_dig_node(pos, name.."_t_1")
|
||||
end,
|
||||
|
||||
on_rightclick = function(pos, node, puncher)
|
||||
if check_player_priv(pos, puncher) then
|
||||
on_rightclick(pos, 1, name.."_t_1", name.."_b_2", name.."_t_2", {1,2,3,0})
|
||||
end
|
||||
end,
|
||||
|
||||
mesecons = {effector = {
|
||||
action_on = on_mesecons_signal_open
|
||||
}},
|
||||
|
||||
can_dig = check_player_priv,
|
||||
})
|
||||
|
||||
minetest.register_node(":"..name.."_b_2", {
|
||||
tiles = {tb[2], tb[2], tb[2], tb[2], tb[1].."^[transformfx", tb[1]},
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
drop = name,
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = def.node_box_bottom
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = def.selection_box_bottom
|
||||
},
|
||||
groups = def.groups,
|
||||
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
pos.y = pos.y+1
|
||||
after_dig_node(pos, name.."_t_2")
|
||||
end,
|
||||
|
||||
on_rightclick = function(pos, node, puncher)
|
||||
if check_player_priv(pos, puncher) then
|
||||
on_rightclick(pos, 1, name.."_t_2", name.."_b_1", name.."_t_1", {3,0,1,2})
|
||||
end
|
||||
end,
|
||||
|
||||
mesecons = {effector = {
|
||||
action_off = on_mesecons_signal_close
|
||||
}},
|
||||
|
||||
can_dig = check_player_priv,
|
||||
})
|
||||
end
|
||||
|
||||
doors:register_door("doors:door_wood", {
|
||||
description = "Wooden Door",
|
||||
inventory_image = "door_wood.png",
|
||||
groups = {snappy=1,choppy=2,oddly_breakable_by_hand=2,flammable=2,door=1},
|
||||
tiles_bottom = {"door_wood_b.png", "door_brown.png"},
|
||||
tiles_top = {"door_wood_a.png", "door_brown.png"},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
doors:register_door("doors:door_steel", {
|
||||
description = "Steel Door",
|
||||
inventory_image = "door_steel.png",
|
||||
groups = {snappy=1,bendy=2,cracky=1,melty=2,level=2,door=1},
|
||||
tiles_bottom = {"door_steel_b.png", "door_grey.png"},
|
||||
tiles_top = {"door_steel_a.png", "door_grey.png"},
|
||||
only_placer_can_open = true,
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
})
|
@ -1,2 +1,2 @@
|
||||
mesecons
|
||||
doors
|
||||
mesecons
|
130
mesecons_doors/init.lua
Normal file
130
mesecons_doors/init.lua
Normal file
@ -0,0 +1,130 @@
|
||||
local other_state_node = {}
|
||||
for _, material in ipairs({
|
||||
{ id = "wood", desc = "Wooden", color = "brown" },
|
||||
{ id = "steel", desc = "Steel", color = "grey" },
|
||||
}) do
|
||||
doors:register_door("mesecons_doors:op_door_"..material.id, {
|
||||
description = "Mesecon-operated "..material.desc.." Door",
|
||||
inventory_image = minetest.registered_items["doors:door_"..material.id].inventory_image,
|
||||
groups = minetest.registered_nodes["doors:door_"..material.id.."_b_1"].groups,
|
||||
tiles_bottom = {"door_"..material.id.."_b.png", "door_"..material.color..".png"},
|
||||
tiles_top = {"door_"..material.id.."_a.png", "door_"..material.color..".png"},
|
||||
})
|
||||
local groups_plus_mesecon = { mesecon = 2 }
|
||||
for k, v in pairs(minetest.registered_nodes["doors:door_"..material.id.."_b_1"].groups) do
|
||||
groups_plus_mesecon[k] = v
|
||||
end
|
||||
doors:register_door("mesecons_doors:sig_door_"..material.id, {
|
||||
description = "Mesecon-signalling "..material.desc.." Door",
|
||||
inventory_image = minetest.registered_items["doors:door_"..material.id].inventory_image,
|
||||
groups = groups_plus_mesecon,
|
||||
tiles_bottom = {"door_"..material.id.."_b.png", "door_"..material.color..".png"},
|
||||
tiles_top = {"door_"..material.id.."_a.png", "door_"..material.color..".png"},
|
||||
})
|
||||
for _, thishalf in ipairs({ "t", "b" }) do
|
||||
local otherhalf = thishalf == "t" and "b" or "t"
|
||||
local otherdir = thishalf == "t" and -1 or 1
|
||||
for orientation = 1, 2 do
|
||||
local thissuffix = material.id.."_"..thishalf.."_"..orientation
|
||||
local othersuffix = material.id.."_"..otherhalf.."_"..orientation
|
||||
local thisopname = "mesecons_doors:op_door_"..thissuffix
|
||||
local otheropname = "mesecons_doors:op_door_"..othersuffix
|
||||
local oponr = minetest.registered_nodes[thisopname].on_rightclick
|
||||
local function handle_mesecon_signal (thispos, thisnode, signal)
|
||||
local thismeta = minetest.get_meta(thispos)
|
||||
if signal == thismeta:get_int("sigstate") then return end
|
||||
thismeta:set_int("sigstate", signal)
|
||||
local otherpos = { x = thispos.x, y = thispos.y + otherdir, z = thispos.z }
|
||||
if minetest.get_node(otherpos).name ~= otheropname then return end
|
||||
local othermeta = minetest.get_meta(otherpos)
|
||||
local newdoorstate = math.max(thismeta:get_int("sigstate"), othermeta:get_int("sigstate"))
|
||||
if newdoorstate == thismeta:get_int("doorstate") then return end
|
||||
oponr(thispos, thisnode, nil)
|
||||
thismeta:set_int("doorstate", newdoorstate)
|
||||
othermeta:set_int("doorstate", newdoorstate)
|
||||
end
|
||||
minetest.override_item(thisopname, {
|
||||
on_construct = function (pos)
|
||||
if mesecon:is_powered(pos) then
|
||||
local node = minetest.get_node(pos)
|
||||
mesecon:changesignal(pos, node, mesecon:effector_get_rules(node), "on", 1)
|
||||
mesecon:activate(pos, node, nil, 1)
|
||||
end
|
||||
end,
|
||||
on_rightclick = function (pos, node, clicker) end,
|
||||
mesecons = {
|
||||
effector = {
|
||||
action_on = function (pos, node)
|
||||
handle_mesecon_signal(pos, node, 1)
|
||||
end,
|
||||
action_off = function (pos, node)
|
||||
handle_mesecon_signal(pos, node, 0)
|
||||
end,
|
||||
},
|
||||
},
|
||||
})
|
||||
local thissigname = "mesecons_doors:sig_door_"..thissuffix
|
||||
local othersigname = "mesecons_doors:sig_door_"..othersuffix
|
||||
local sigonr = minetest.registered_nodes[thissigname].on_rightclick
|
||||
minetest.override_item(thissigname, {
|
||||
on_rightclick = function (thispos, thisnode, clicker)
|
||||
local otherpos = { x = thispos.x, y = thispos.y + otherdir, z = thispos.z }
|
||||
print("open: otherpos.name="..minetest.get_node(otherpos).name..", othersigname="..othersigname)
|
||||
if minetest.get_node(otherpos).name ~= othersigname then return end
|
||||
sigonr(thispos, thisnode, clicker)
|
||||
for _, pos in ipairs({ thispos, otherpos }) do
|
||||
local node = minetest.get_node(pos)
|
||||
node.name = other_state_node[node.name]
|
||||
minetest.swap_node(pos, node)
|
||||
mesecon:receptor_on(pos)
|
||||
end
|
||||
end,
|
||||
mesecons = { receptor = { state = mesecon.state.off } },
|
||||
})
|
||||
other_state_node[thissigname] = thissigname.."_on"
|
||||
local ondef = {}
|
||||
for k, v in pairs(minetest.registered_nodes[thissigname]) do
|
||||
ondef[k] = v
|
||||
end
|
||||
ondef.on_rightclick = function (thispos, thisnode, clicker)
|
||||
local otherpos = { x = thispos.x, y = thispos.y + otherdir, z = thispos.z }
|
||||
print("close: otherpos.name="..minetest.get_node(otherpos).name..", othersigname="..othersigname)
|
||||
if minetest.get_node(otherpos).name ~= othersigname.."_on" then return end
|
||||
for _, pos in ipairs({ thispos, otherpos }) do
|
||||
local node = minetest.get_node(pos)
|
||||
node.name = other_state_node[node.name]
|
||||
minetest.swap_node(pos, node)
|
||||
mesecon:receptor_off(pos)
|
||||
end
|
||||
sigonr(thispos, thisnode, clicker)
|
||||
end
|
||||
ondef.mesecons = { receptor = { state = mesecon.state.on } }
|
||||
ondef.after_destruct = function (thispos, thisnode)
|
||||
local otherpos = { x = thispos.x, y = thispos.y + otherdir, z = thispos.z }
|
||||
if minetest.get_node(otherpos).name == othersigname.."_on" then
|
||||
minetest.remove_node(otherpos)
|
||||
mesecon:receptor_off(otherpos)
|
||||
end
|
||||
end
|
||||
other_state_node[thissigname.."_on"] = thissigname
|
||||
ondef.mesecon_other_state_node = thissigname
|
||||
minetest.register_node(thissigname.."_on", ondef)
|
||||
end
|
||||
end
|
||||
minetest.register_craft({
|
||||
output = "mesecons_doors:op_door_"..material.id,
|
||||
recipe = {
|
||||
{ "group:mesecon_conductor_craftable", "", "" },
|
||||
{ "", "doors:door_"..material.id, "group:mesecon_conductor_craftable" },
|
||||
{ "group:mesecon_conductor_craftable", "", "" },
|
||||
},
|
||||
})
|
||||
minetest.register_craft({
|
||||
output = "mesecons_doors:sig_door_"..material.id,
|
||||
recipe = {
|
||||
{ "", "", "group:mesecon_conductor_craftable" },
|
||||
{ "group:mesecon_conductor_craftable", "doors:door_"..material.id, "" },
|
||||
{ "", "", "group:mesecon_conductor_craftable" },
|
||||
},
|
||||
})
|
||||
end
|
Loading…
Reference in New Issue
Block a user