Various additions

* Added intermediate connections for vertical digilines
* Added protection support to buttons and wall knobs (optional, defaults to off)
* Added the ability to manually control the button light (optional, defaults to off)
master
cheapie 2019-06-15 12:09:51 -05:00
parent 0fda965aa4
commit da9556bd3a
4 changed files with 249 additions and 39 deletions

11
README
View File

@ -16,9 +16,18 @@ Only needed for craft recipes: default, mesecons_luacontroller, basic_materials
How to use digilines buttons: How to use digilines buttons:
Connect to a digiline (or digimese), right-click, and set a channel and message. Connect to a digiline (or digimese), right-click, and set a channel and message.
When the button is pressed (right-click), it will send that message on that channel, over digilines. When the button is pressed (right-click), it will send that message on that channel, over digilines.
If the "Protected" checkbox is checked, only players allowed to interact in the area can push the button.
If the "Manual Light Control" checkbox is checked, the light will not illuminate automatically when the button is pushed - use the "light_on" and "light_off" commands to control it.
Note that the settings cannot be changed after setting - you must dig and re-place the button to do so. Note that the settings cannot be changed after setting - you must dig and re-place the button to do so.
How to use the wall knob:
Connect to a digiline, right-click, and set the channel and the minimum and maximum values.
Left-click to decrease the current setting or right-click to increase it. If the "protected" checkbox was checked, then only players allowed to interact in the area can do this.
Each time the setting is changed, the new setting is sent on the selected channel.
Note that the settings cannot be changed after setting - you must dig and re-place the knob to do so.
How to use digimese: How to use digimese:
It conducts digilines signals (like digilines) in all directions (like mese). That's about it, really. It conducts digilines signals (like digilines) in all directions (like mese). That's about it, really.
@ -26,7 +35,7 @@ It conducts digilines signals (like digilines) in all directions (like mese). Th
How to use vertical/insulated digilines: How to use vertical/insulated digilines:
These work exactly like the mesecons equivalents, that is: These work exactly like the mesecons equivalents, that is:
Vertical digilines will automatically connect to other vertical digilines directly above or below them, and form "plates" on each end of the stack. Signals can only be conducted into or out of the stack at these "plates". Vertical digilines will automatically connect to other vertical digilines directly above or below them, and form "plates" on each end of the stack. Signals can only be conducted into or out of the stack at these "plates".
Insulated digilines conduct like regular digilines, but only into/out of the ends of the "wire". Insulated digilines conduct like regular digilines, but only into/out of the ends of the "wire" or at locations where an intermediate connection has been placed.
How to use the digilines player detector: How to use the digilines player detector:

View File

@ -167,6 +167,7 @@ digistuff.vertical_autoconnect = function(pos)
shouldbe = "digistuff:vertical_top" shouldbe = "digistuff:vertical_top"
end end
end end
if node.name == "digistuff:vertical_tap" then shouldbe = "digistuff:vertical_tap" end
if shouldbe ~= node.name or upnode.name == "digistuff:vertical_bottom" or dnnode.name == "digistuff:vertical_top" then if shouldbe ~= node.name or upnode.name == "digistuff:vertical_bottom" or dnnode.name == "digistuff:vertical_top" then
node.name = shouldbe node.name = shouldbe
minetest.set_node(pos,node) minetest.set_node(pos,node)
@ -183,6 +184,44 @@ digistuff.vertical_remove = function(pos)
digistuff.vertical_autoconnect(dnpos) digistuff.vertical_autoconnect(dnpos)
end end
minetest.register_node("digistuff:vertical_tap", {
description = "Vertical Digiline Intermediate Connection",
tiles = {"digistuff_digiline_full.png"},
paramtype = "light",
groups = {dig_immediate = 3,vertical_digiline = 1,},
is_ground_content = false,
paramtype = "light",
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
{-0.5,-0.5,-0.5,0.5,-0.4375,0.5},
{-0.05,-0.4375,-0.05,0.05,0.5,0.05},
},
},
collision_box = {
type = "fixed",
fixed = {
{-0.5,-0.5,-0.5,0.5,-0.4375,0.5},
},
},
after_place_node = digistuff.vertical_autoconnect,
after_destruct = digistuff.vertical_remove,
digiline = {
receptor = {},
wire = {
rules = {
{x = 1,y = 0,z = 0},
{x = -1,y = 0,z = 0},
{x = 0,y = 0,z = 1},
{x = 0,y = 0,z = -1},
{x = 0,y = 1,z = 0},
{x = 0,y = -1,z = 0},
},
},
},
})
minetest.register_node("digistuff:vertical_bottom", { minetest.register_node("digistuff:vertical_bottom", {
description = "Vertical Digiline", description = "Vertical Digiline",
tiles = {"digistuff_digiline_full.png"}, tiles = {"digistuff_digiline_full.png"},
@ -505,6 +544,15 @@ minetest.register_craft({
} }
}) })
minetest.register_craft({
output = "digistuff:vertical_tap 5",
recipe = {
{"","digistuff:vertical_bottom",""},
{"digilines:wire_std_00000000","digistuff:vertical_bottom","digilines:wire_std_00000000"},
{"","digistuff:vertical_bottom",""},
}
})
minetest.register_craft({ minetest.register_craft({
output = "digistuff:insulated_corner 3", output = "digistuff:insulated_corner 3",
recipe = { recipe = {

View File

@ -1,3 +1,5 @@
digistuff.mesecons_installed = minetest.get_modpath("mesecons")
digistuff.rotate_rules = function(rulesin,dir) digistuff.rotate_rules = function(rulesin,dir)
local rules = {} local rules = {}
for k,v in ipairs(rulesin) do rules[k] = v end for k,v in ipairs(rulesin) do rules[k] = v end
@ -42,3 +44,14 @@ digistuff.rotate_rules = function(rulesin,dir)
return {} return {}
end end
end end
digistuff.check_protection = function(pos,player)
assert(type(pos) == "table","Position must be a table")
assert(type(player) == "string" or type(player) == "userdata","Invalid player specified")
if type(player) == "userdata" then player = player:get_player_name() end
if minetest.is_protected(pos,player) and not minetest.check_player_privs(player,{protection_bypass=true}) then
minetest.record_protection_violation(pos,player)
return false
end
return true
end

View File

@ -1,7 +1,48 @@
digistuff.button_turnoff = function (pos) digistuff.button_turnoff = function(pos)
local node = minetest.get_node(pos) local node = minetest.get_node(pos)
minetest.swap_node(pos, {name = "digistuff:button_off", param2=node.param2}) local meta = minetest.get_meta(pos)
if minetest.get_modpath("mesecons") then minetest.sound_play("mesecons_button_pop", {pos=pos}) end local mlight = meta:get_int("mlight") == 1
if node.name == "digistuff:button_off_pushed" then node.name = "digistuff:button_off"
elseif node.name == "digistuff:button_on" and not mlight then node.name = "digistuff:button_off"
elseif node.name == "digistuff:button_on_pushed" then
if mlight then node.name = "digistuff:button_on"
else node.name = "digistuff:button_off" end
end
minetest.swap_node(pos,node)
if digistuff.mesecons_installed then minetest.sound_play("mesecons_button_pop", {pos=pos}) end
end
digistuff.button_push = function(pos,node,player)
local meta = minetest.get_meta(pos)
if meta:get_int("protected") == 1 and not digistuff.check_protection(pos,player) then return end
local mlight = meta:get_int("mlight") == 1
digiline:receptor_send(pos, digistuff.button_get_rules(node), meta:get_string("channel"), meta:get_string("msg"))
local newnode = "digistuff:button_on_pushed"
if meta:get_int("mlight") == 1 and (node.name == "digistuff:button_off" or node.name == "digistuff:button_off_pushed") then newnode = "digistuff:button_off_pushed" end
if node.name ~= newnode then minetest.swap_node(pos, {name = newnode, param2=node.param2}) end
if digistuff.mesecons_installed then minetest.sound_play("mesecons_button_push", {pos=pos}) end
minetest.get_node_timer(pos):start(0.25)
end
digistuff.button_handle_digilines = function(pos,node,channel,msg)
local meta = minetest.get_meta(pos)
if channel ~= meta:get_string("channel") then return end
if meta:get_int("mlight") == 0 then return end
if msg == "light_on" then
if node.name == "digistuff:button_off" then
node.name = "digistuff:button_on"
elseif node.name == "digistuff:button_off_pushed" then
node.name = "digistuff:button_on_pushed"
end
minetest.swap_node(pos,node)
elseif msg == "light_off" then
if node.name == "digistuff:button_on" then
node.name = "digistuff:button_off"
elseif node.name == "digistuff:button_on_pushed" then
node.name = "digistuff:button_off_pushed"
end
minetest.swap_node(pos,node)
end
end end
digistuff.button_get_rules = function(node) digistuff.button_get_rules = function(node)
@ -58,19 +99,26 @@ minetest.register_node("digistuff:button", {
description = "Digilines Button", description = "Digilines Button",
on_construct = function(pos) on_construct = function(pos)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
meta:set_string("formspec","size[8,4;]field[1,1;6,2;channel;Channel;${channel}]field[1,2;6,2;msg;Message;${msg}]button_exit[2.25,3;3,1;submit;Save]") meta:set_string("formspec","size[7.5,3]field[1,0;6,2;channel;Channel;${channel}]field[1,1;6,2;msg;Message;${msg}]checkbox[1,1.75;protected;Protected]checkbox[1,2;mlight;Manual Light Control]button_exit[3,2;3,1;submit;Save]")
end, end,
after_place_node = digistuff.place_receiver, after_place_node = digistuff.place_receiver,
after_destruct = digistuff.remove_receiver, after_destruct = digistuff.remove_receiver,
on_receive_fields = function(pos, formname, fields, sender) on_receive_fields = function(pos, formname, fields, sender)
print(dump(fields))
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
if fields.channel and fields.channel ~= "" then if fields.submit then
meta:set_string("channel",fields.channel) if fields.channel ~= "" then
meta:set_string("msg",fields.msg) meta:set_string("channel",fields.channel)
meta:set_string("formspec","") meta:set_string("msg",fields.msg)
minetest.swap_node(pos, {name = "digistuff:button_off", param2=minetest.get_node(pos).param2}) meta:set_string("formspec","")
else minetest.swap_node(pos, {name = "digistuff:button_off", param2=minetest.get_node(pos).param2})
minetest.chat_send_player(sender:get_player_name(),"Please set a channel!") else
minetest.chat_send_player(sender:get_player_name(),"Please set a channel!")
end
elseif fields.protected then
meta:set_int("protected",fields.protected == "true" and 1 or 0)
elseif fields.mlight then
meta:set_int("mlight",fields.mlight == "true" and 1 or 0)
end end
end, end,
sounds = default and default.node_sound_stone_defaults(), sounds = default and default.node_sound_stone_defaults(),
@ -108,22 +156,110 @@ minetest.register_node("digistuff:button_off", {
wire = { wire = {
rules = digistuff.button_get_rules, rules = digistuff.button_get_rules,
}, },
effector = {
action = digistuff.button_handle_digilines,
},
}, },
groups = {dig_immediate = 2,not_in_creative_inventory = 1,digiline_receiver = 1,}, groups = {dig_immediate = 2,not_in_creative_inventory = 1,digiline_receiver = 1,},
drop = "digistuff:button", drop = "digistuff:button",
after_destruct = digistuff.remove_receiver, after_destruct = digistuff.remove_receiver,
description = "Digilines Button (off state - you hacker you!)", description = "Digilines Button (off state - you hacker you!)",
on_rightclick = function (pos, node, clicker) on_rightclick = digistuff.button_push,
local meta = minetest.get_meta(pos) sounds = default and default.node_sound_stone_defaults(),
digiline:receptor_send(pos, digistuff.button_get_rules(node), meta:get_string("channel"), meta:get_string("msg")) })
minetest.swap_node(pos, {name = "digistuff:button_on", param2=node.param2})
if minetest.get_modpath("mesecons") then minetest.sound_play("mesecons_button_push", {pos=pos}) end minetest.register_node("digistuff:button_off_pushed", {
minetest.get_node_timer(pos):start(0.25) drawtype = "nodebox",
end, tiles = {
"digistuff_digibutton_sides.png",
"digistuff_digibutton_sides.png",
"digistuff_digibutton_sides.png",
"digistuff_digibutton_sides.png",
"digistuff_digibutton_sides.png",
"digistuff_digibutton_off.png"
},
paramtype = "light",
paramtype2 = "facedir",
legacy_wallmounted = true,
walkable = false,
sunlight_propagates = true,
selection_box = {
type = "fixed",
fixed = { -6/16, -6/16, 5/16, 6/16, 6/16, 8/16 }
},
node_box = {
type = "fixed",
fixed = {
{ -6/16, -6/16, 6/16, 6/16, 6/16, 8/16 },
{ -4/16, -2/16, 11/32, 4/16, 2/16, 6/16 }
}
},
digiline =
{
receptor = {},
wire = {
rules = digistuff.button_get_rules,
},
effector = {
action = digistuff.button_handle_digilines,
},
},
on_timer = digistuff.button_turnoff,
groups = {dig_immediate = 2,not_in_creative_inventory = 1,digiline_receiver = 1,},
drop = "digistuff:button",
after_destruct = digistuff.remove_receiver,
description = "Digilines Button (off, pushed state - you hacker you!)",
on_rightclick = digistuff.button_push,
sounds = default and default.node_sound_stone_defaults(), sounds = default and default.node_sound_stone_defaults(),
}) })
minetest.register_node("digistuff:button_on", { minetest.register_node("digistuff:button_on", {
drawtype = "nodebox",
tiles = {
"digistuff_digibutton_sides.png",
"digistuff_digibutton_sides.png",
"digistuff_digibutton_sides.png",
"digistuff_digibutton_sides.png",
"digistuff_digibutton_sides.png",
"digistuff_digibutton_on.png"
},
paramtype = "light",
paramtype2 = "facedir",
legacy_wallmounted = true,
walkable = false,
light_source = 7,
sunlight_propagates = true,
selection_box = {
type = "fixed",
fixed = { -6/16, -6/16, 5/16, 6/16, 6/16, 8/16 }
},
node_box = {
type = "fixed",
fixed = {
{ -6/16, -6/16, 6/16, 6/16, 6/16, 8/16 }, -- the thin plate behind the button
{ -4/16, -2/16, 4/16, 4/16, 2/16, 6/16 } -- the button itself
}
},
digiline =
{
receptor = {},
wire = {
rules = digistuff.button_get_rules,
},
effector = {
action = digistuff.button_handle_digilines,
},
},
on_timer = digistuff.button_turnoff,
groups = {dig_immediate = 2,not_in_creative_inventory = 1,digiline_receiver = 1,},
drop = 'digistuff:button',
after_destruct = digistuff.remove_receiver,
on_rightclick = digistuff.button_push,
description = "Digilines Button (on state - you hacker you!)",
sounds = default and default.node_sound_stone_defaults(),
})
minetest.register_node("digistuff:button_on_pushed", {
drawtype = "nodebox", drawtype = "nodebox",
tiles = { tiles = {
"digistuff_digibutton_sides.png", "digistuff_digibutton_sides.png",
@ -156,18 +292,16 @@ minetest.register_node("digistuff:button_on", {
wire = { wire = {
rules = digistuff.button_get_rules, rules = digistuff.button_get_rules,
}, },
effector = {
action = digistuff.button_handle_digilines,
},
}, },
on_timer = digistuff.button_turnoff, on_timer = digistuff.button_turnoff,
groups = {dig_immediate = 2,not_in_creative_inventory = 1,digiline_receiver = 1,}, groups = {dig_immediate = 2,not_in_creative_inventory = 1,digiline_receiver = 1,},
drop = 'digistuff:button', drop = 'digistuff:button',
after_destruct = digistuff.remove_receiver, after_destruct = digistuff.remove_receiver,
on_rightclick = function (pos, node, clicker) on_rightclick = digistuff.button_push,
local meta = minetest.get_meta(pos) description = "Digilines Button (on, pushed state - you hacker you!)",
digiline:receptor_send(pos, digistuff.button_get_rules(node), meta:get_string("channel"), meta:get_string("msg"))
if minetest.get_modpath("mesecons") then minetest.sound_play("mesecons_button_push", {pos=pos}) end
minetest.get_node_timer(pos):start(0.25)
end,
description = "Digilines Button (on state - you hacker you!)",
sounds = default and default.node_sound_stone_defaults(), sounds = default and default.node_sound_stone_defaults(),
}) })
@ -210,26 +344,30 @@ minetest.register_node("digistuff:wall_knob", {
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
meta:set_int("min",0) meta:set_int("min",0)
meta:set_int("max",14) meta:set_int("max",14)
meta:set_string("formspec","size[8,4;]field[1,1;6,2;channel;Channel;${channel}]field[1,2;3,2;min;Minimum;${min}]field[4,2;3,2;max;Maximum;${max}]button_exit[2.25,3;3,1;submit;Save]") meta:set_string("formspec","size[7.5,3;]field[1,0;6,2;channel;Channel;${channel}]field[1,1;3,2;min;Minimum;${min}]field[4,1;3,2;max;Maximum;${max}]checkbox[1,2;protected;Protected]button_exit[3,2;3,1;submit;Save]")
end, end,
after_place_node = digistuff.place_receiver, after_place_node = digistuff.place_receiver,
after_destruct = digistuff.remove_receiver, after_destruct = digistuff.remove_receiver,
on_receive_fields = function(pos, formname, fields, sender) on_receive_fields = function(pos, formname, fields, sender)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
if fields.channel and fields.channel ~= "" then if fields.submit then
if tonumber(fields.min) and tonumber(fields.max) and math.floor(fields.min) < math.floor(fields.max) then if fields.channel ~= "" then
meta:set_string("channel",fields.channel) if tonumber(fields.min) and tonumber(fields.max) and math.floor(fields.min) < math.floor(fields.max) then
meta:set_int("min",math.floor(tonumber(fields.min))) meta:set_string("channel",fields.channel)
meta:set_int("max",math.floor(tonumber(fields.max))) meta:set_int("min",math.floor(tonumber(fields.min)))
meta:set_int("value",math.floor(tonumber(fields.min))) meta:set_int("max",math.floor(tonumber(fields.max)))
meta:set_string("infotext",string.format("Current setting: %d\nLeft-click to turn down or right-click to turn up",math.floor(tonumber(fields.min)))) meta:set_int("value",math.floor(tonumber(fields.min)))
meta:set_string("formspec","") meta:set_string("infotext",string.format("Current setting: %d\nLeft-click to turn down or right-click to turn up",math.floor(tonumber(fields.min))))
minetest.swap_node(pos, {name = "digistuff:wall_knob_configured", param2=minetest.get_node(pos).param2}) meta:set_string("formspec","")
minetest.swap_node(pos, {name = "digistuff:wall_knob_configured", param2=minetest.get_node(pos).param2})
else
minetest.chat_send_player(sender:get_player_name(),"Minimum and maximum must both be numbers, and maximum must be greater than minimum")
end
else else
minetest.chat_send_player(sender:get_player_name(),"Minimum and maximum must both be numbers, and maximum must be greater than minimum") minetest.chat_send_player(sender:get_player_name(),"Please set a channel!")
end end
else elseif fields.protected then
minetest.chat_send_player(sender:get_player_name(),"Please set a channel!") meta:set_int("protected",fields.protected == "true" and 1 or 0)
end end
end, end,
sounds = default and default.node_sound_stone_defaults(), sounds = default and default.node_sound_stone_defaults(),
@ -266,6 +404,7 @@ minetest.register_node("digistuff:wall_knob_configured", {
after_destruct = digistuff.remove_receiver, after_destruct = digistuff.remove_receiver,
on_rightclick = function(pos,node,player) on_rightclick = function(pos,node,player)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
if meta:get_int("protected") == 1 and not digistuff.check_protection(pos,player) then return end
local max = meta:get_int("max") local max = meta:get_int("max")
local value = meta:get_int("value") local value = meta:get_int("value")
local full = player:get_player_control().aux1 local full = player:get_player_control().aux1
@ -276,6 +415,7 @@ minetest.register_node("digistuff:wall_knob_configured", {
end, end,
on_punch = function(pos,node,player) on_punch = function(pos,node,player)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
if meta:get_int("protected") == 1 and not digistuff.check_protection(pos,player) then return end
local min = meta:get_int("min") local min = meta:get_int("min")
local value = meta:get_int("value") local value = meta:get_int("value")
local full = player:get_player_control().aux1 local full = player:get_player_control().aux1