From 77b8f6514a8d7d07598a422d3083ce2f66456345 Mon Sep 17 00:00:00 2001 From: Zefram Date: Sat, 3 May 2014 19:53:23 +0100 Subject: [PATCH] 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. --- mesecons_compatibility/init.lua | 167 ------------------ .../depends.txt | 2 +- mesecons_doors/init.lua | 130 ++++++++++++++ 3 files changed, 131 insertions(+), 168 deletions(-) delete mode 100644 mesecons_compatibility/init.lua rename {mesecons_compatibility => mesecons_doors}/depends.txt (100%) create mode 100644 mesecons_doors/init.lua diff --git a/mesecons_compatibility/init.lua b/mesecons_compatibility/init.lua deleted file mode 100644 index 5bdce27..0000000 --- a/mesecons_compatibility/init.lua +++ /dev/null @@ -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(), -}) diff --git a/mesecons_compatibility/depends.txt b/mesecons_doors/depends.txt similarity index 100% rename from mesecons_compatibility/depends.txt rename to mesecons_doors/depends.txt index ed2fcd8..308c4c1 100644 --- a/mesecons_compatibility/depends.txt +++ b/mesecons_doors/depends.txt @@ -1,2 +1,2 @@ -mesecons doors +mesecons diff --git a/mesecons_doors/init.lua b/mesecons_doors/init.lua new file mode 100644 index 0000000..0938889 --- /dev/null +++ b/mesecons_doors/init.lua @@ -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