Add files via upload

This commit is contained in:
loosewheel
2021-11-06 21:46:50 +10:00
committed by GitHub
parent 53492183a1
commit 3692738a74
17 changed files with 3456 additions and 0 deletions

3
change.log Normal file
View File

@@ -0,0 +1,3 @@
v 0.1.0
* initial release

536
collector.lua Normal file
View File

@@ -0,0 +1,536 @@
local utils = ...
local S = utils.S
if utils.digilines_supported then
local collect_interval = 0.5
local function send_collect_message (pos, name, count)
if utils.digilines_supported then
local meta = minetest.get_meta (pos)
if meta then
local channel = meta:get_string ("channel")
if channel:len () > 0 then
utils.digilines_receptor_send (pos,
digiline.rules.default,
channel,
{ action = "collect",
name = name,
count = count })
end
end
end
end
local function filter_item (pos, item)
local meta = minetest.get_meta (pos)
if meta then
local inv = meta:get_inventory ()
if inv:is_empty ("filter") then
return true
end
local slots = inv:get_size ("filter")
for i = 1, slots do
local stack = inv:get_stack ("filter", i)
if stack and not stack:is_empty () and
stack:get_name () == item then
return true
end
end
end
return false
end
local function get_form_spec (is_off)
return
"formspec_version[3]\n"..
"size[11.75,13.75;true]\n"..
"field[1.0,1.0;4.0,0.8;channel;Channel;${channel}]\n"..
"button[5.5,1.0;2.0,0.8;setchannel;Set]\n"..
"button[8.25,1.0;2.5,0.8;"..((is_off and "start;Start") or "stop;Stop").."]\n"..
"list[context;filter;8.5,2.5;2,4;]\n"..
"list[context;main;1.0,2.5;4,4;]\n"..
"list[current_player;main;1.0,8.0;8,4;]\n"..
"listring[]"
end
local function start_collector (pos)
local node = minetest.get_node (pos)
if node then
if node.name == "lwcomponents:collector" then
local meta = minetest.get_meta (pos)
if meta then
node.name = "lwcomponents:collector_on"
minetest.swap_node (pos, node)
minetest.get_node_timer (pos):start (collect_interval)
meta:set_string ("formspec", get_form_spec (false))
end
elseif node.name == "lwcomponents:collector_locked" then
local meta = minetest.get_meta (pos)
if meta then
node.name = "lwcomponents:collector_locked_on"
minetest.swap_node (pos, node)
minetest.get_node_timer (pos):start (collect_interval)
meta:set_string ("formspec", get_form_spec (false))
end
end
end
end
local function stop_collector (pos)
local node = minetest.get_node (pos)
if node then
if node.name == "lwcomponents:collector_on" then
local meta = minetest.get_meta (pos)
if meta then
node.name = "lwcomponents:collector"
minetest.swap_node (pos, node)
minetest.get_node_timer (pos):stop ()
meta:set_string ("formspec", get_form_spec (true))
end
elseif node.name == "lwcomponents:collector_locked_on" then
local meta = minetest.get_meta (pos)
if meta then
node.name = "lwcomponents:collector_locked"
minetest.swap_node (pos, node)
minetest.get_node_timer (pos):stop ()
meta:set_string ("formspec", get_form_spec (true))
end
end
end
end
local function on_destruct (pos)
minetest.get_node_timer (pos):stop ()
end
local function after_place_node (pos, placer, itemstack, pointed_thing)
local meta = minetest.get_meta (pos)
local is_off = itemstack and (itemstack:get_name () == "lwcomponents:collector" or
itemstack:get_name () == "lwcomponents:collector_locked")
meta:set_string ("inventory", "{ main = { }, filter = { } }")
meta:set_string ("formspec", get_form_spec (is_off))
local inv = meta:get_inventory ()
inv:set_size ("main", 16)
inv:set_width ("main", 4)
inv:set_size ("filter", 8)
inv:set_width ("filter", 2)
-- If return true no item is taken from itemstack
return false
end
local function after_place_node_locked (pos, placer, itemstack, pointed_thing)
after_place_node (pos, placer, itemstack, pointed_thing)
if placer and placer:is_player () then
local meta = minetest.get_meta (pos)
meta:set_string ("owner", placer:get_player_name ())
meta:set_string ("infotext", "Collector (owned by "..placer:get_player_name ()..")")
end
-- If return true no item is taken from itemstack
return false
end
local function on_receive_fields (pos, formname, fields, sender)
if not utils.can_interact_with_node (pos, sender) then
return
end
if fields.setchannel then
local meta = minetest.get_meta (pos)
if meta then
meta:set_string ("channel", fields.channel)
end
elseif fields.start then
start_collector (pos)
elseif fields.stop then
stop_collector (pos)
end
end
local function can_dig (pos, player)
if not utils.can_interact_with_node (pos, player) then
return false
end
local meta = minetest.get_meta (pos)
if meta then
local inv = meta:get_inventory ()
if inv then
if not inv:is_empty ("main") then
return false
end
if not inv:is_empty ("filter") then
return false
end
end
end
return true
end
local function on_blast (pos, intensity)
local meta = minetest.get_meta (pos)
if meta then
if intensity >= 1.0 then
local inv = meta:get_inventory ()
if inv then
local slots = inv:get_size ("main")
for slot = 1, slots do
local stack = inv:get_stack ("main", slot)
if stack and not stack:is_empty () then
if math.floor (math.random (0, 5)) == 3 then
utils.item_drop (stack, nil, pos)
else
utils.on_destroy (stack)
end
end
end
slots = inv:get_size ("filter")
for slot = 1, slots do
local stack = inv:get_stack ("filter", slot)
if stack and not stack:is_empty () then
if math.floor (math.random (0, 5)) == 3 then
utils.item_drop (stack, nil, pos)
else
utils.on_destroy (stack)
end
end
end
end
on_destruct (pos)
minetest.remove_node (pos)
else -- intensity < 1.0
local inv = meta:get_inventory ()
if inv then
local slots = inv:get_size ("main")
for slot = 1, slots do
local stack = inv:get_stack ("main", slot)
if stack and not stack:is_empty () then
utils.item_drop (stack, nil, pos)
end
end
slots = inv:get_size ("filter")
for slot = 1, slots do
local stack = inv:get_stack ("filter", slot)
if stack and not stack:is_empty () then
utils.item_drop (stack, nil, pos)
end
end
end
local node = minetest.get_node_or_nil (pos)
if node then
local items = minetest.get_node_drops (node, nil)
if items and #items > 0 then
local stack = ItemStack (items[1])
if stack then
preserve_metadata (pos, node, meta, { stack })
utils.item_drop (stack, nil, pos)
on_destruct (pos)
minetest.remove_node (pos)
end
end
end
end
end
end
local function on_rightclick (pos, node, clicker, itemstack, pointed_thing)
if not utils.can_interact_with_node (pos, clicker) then
if clicker and clicker:is_player () then
local owner = "<unknown>"
local meta = minetest.get_meta (pos)
if meta then
owner = meta:get_string ("owner")
end
local spec =
"formspec_version[3]"..
"size[8.0,4.0,false]"..
"label[1.0,1.0;Owned by "..minetest.formspec_escape (owner).."]"..
"button_exit[3.0,2.0;2.0,1.0;close;Close]"
minetest.show_formspec (clicker:get_player_name (),
"lwcomponents:component_privately_owned",
spec)
end
end
return itemstack
end
local function on_timer (pos, elapsed)
local list = minetest.get_objects_inside_radius (pos, 2)
local meta = minetest.get_meta (pos)
if meta then
local inv = meta:get_inventory ()
if inv then
for i = 1, #list do
if list[i].get_luaentity and list[i]:get_luaentity () and
list[i]:get_luaentity ().name and
list[i]:get_luaentity ().name == "__builtin:item" then
local stack = utils.item_pickup (list[i]:get_luaentity (), false)
if stack and inv:room_for_item ("main", stack) and
filter_item (pos, stack:get_name ()) then
local name = stack:get_name ()
local count = stack:get_count ()
inv:add_item ("main", stack)
utils.item_pickup (list[i]:get_luaentity ())
send_collect_message (pos, name, count)
end
end
end
end
end
return true
end
local function digilines_support ()
if utils.digilines_supported then
return
{
wire =
{
rules = digiline.rules.default,
},
effector =
{
action = function (pos, node, channel, msg)
local meta = minetest.get_meta(pos)
if meta then
local this_channel = meta:get_string ("channel")
if this_channel == channel then
local m = { }
for w in string.gmatch(msg, "[^%s]+") do
m[#m + 1] = w
end
if m[1] == "start" then
start_collector (pos)
elseif m[1] == "stop" then
stop_collector (pos)
end
end
end
end,
}
}
end
return nil
end
minetest.register_node("lwcomponents:collector", {
description = S("Collector"),
tiles = { "lwcollector.png", "lwcollector.png", "lwcollector.png",
"lwcollector.png", "lwcollector.png", "lwcollector.png"},
is_ground_content = false,
groups = { cracky = 3 },
sounds = default.node_sound_stone_defaults (),
paramtype = "light",
param1 = 0,
floodable = false,
drop = "lwcomponents:collector",
_digistuff_channelcopier_fieldname = "channel",
digiline = digilines_support (),
on_destruct = on_destruct,
on_receive_fields = on_receive_fields,
after_place_node = after_place_node,
can_dig = can_dig,
on_blast = on_blast,
on_timer = on_timer,
on_rightclick = on_rightclick
})
minetest.register_node("lwcomponents:collector_locked", {
description = S("Collector (locked)"),
tiles = { "lwcollector.png", "lwcollector.png", "lwcollector.png",
"lwcollector.png", "lwcollector.png", "lwcollector.png"},
is_ground_content = false,
groups = { cracky = 3 },
sounds = default.node_sound_stone_defaults (),
paramtype = "light",
param1 = 0,
floodable = false,
drop = "lwcomponents:collector_locked",
_digistuff_channelcopier_fieldname = "channel",
digiline = digilines_support (),
on_destruct = on_destruct,
on_receive_fields = on_receive_fields,
after_place_node = after_place_node_locked,
can_dig = can_dig,
on_blast = on_blast,
on_timer = on_timer,
on_rightclick = on_rightclick
})
minetest.register_node("lwcomponents:collector_on", {
description = S("Collector"),
tiles = { "lwcollector_on.png", "lwcollector_on.png", "lwcollector_on.png",
"lwcollector_on.png", "lwcollector_on.png", "lwcollector_on.png"},
is_ground_content = false,
groups = { cracky = 3, not_in_creative_inventory = 1 },
sounds = default.node_sound_stone_defaults (),
paramtype = "light",
param1 = 0,
floodable = false,
drop = "lwcomponents:collector",
_digistuff_channelcopier_fieldname = "channel",
digiline = digilines_support (),
on_destruct = on_destruct,
on_receive_fields = on_receive_fields,
after_place_node = after_place_node,
can_dig = can_dig,
on_blast = on_blast,
on_timer = on_timer,
on_rightclick = on_rightclick
})
minetest.register_node("lwcomponents:collector_locked_on", {
description = S("Collector (locked)"),
tiles = { "lwcollector_on.png", "lwcollector_on.png", "lwcollector_on.png",
"lwcollector_on.png", "lwcollector_on.png", "lwcollector_on.png"},
is_ground_content = false,
groups = { cracky = 3, not_in_creative_inventory = 1 },
sounds = default.node_sound_stone_defaults (),
paramtype = "light",
param1 = 0,
floodable = false,
drop = "lwcomponents:collector_locked",
_digistuff_channelcopier_fieldname = "channel",
digiline = digilines_support (),
on_destruct = on_destruct,
on_receive_fields = on_receive_fields,
after_place_node = after_place_node_locked,
can_dig = can_dig,
on_blast = on_blast,
on_timer = on_timer,
on_rightclick = on_rightclick
})
end -- utils.digilines_supported
--

141
crafting.lua Normal file
View File

@@ -0,0 +1,141 @@
local utils = ...
local S = utils.S
if utils.digilines_supported or utils.mesecon_supported then
minetest.register_craft( {
output = "lwcomponents:dropper",
recipe = {
{ "default:stone", "default:chest" },
{ "default:copper_ingot", "default:steel_ingot" },
},
})
minetest.register_craft( {
output = "lwcomponents:dropper_locked",
recipe = {
{ "default:stone", "default:chest_locked" },
{ "default:copper_ingot", "default:steel_ingot" },
},
})
minetest.register_craft( {
output = "lwcomponents:dispenser",
recipe = {
{ "default:chest", "default:stone" },
{ "default:copper_ingot", "default:steel_ingot" },
},
})
minetest.register_craft( {
output = "lwcomponents:dispenser_locked",
recipe = {
{ "default:chest_locked", "default:stone" },
{ "default:copper_ingot", "default:steel_ingot" },
},
})
minetest.register_craft( {
output = "lwcomponents:detector",
recipe = {
{ "default:copper_ingot", "default:steel_ingot" },
{ "default:stone", "default:chest" },
},
})
minetest.register_craft( {
output = "lwcomponents:detector_locked",
recipe = {
{ "default:copper_ingot", "default:steel_ingot" },
{ "default:stone", "default:chest_locked" },
},
})
end -- utils.digilines_supported or utils.mesecon_supported
if utils.digilines_supported then
minetest.register_craft( {
output = "lwcomponents:collector",
recipe = {
{ "default:copper_ingot", "default:steel_ingot" },
{ "default:chest", "default:stone" },
},
})
minetest.register_craft( {
output = "lwcomponents:collector_locked",
recipe = {
{ "default:copper_ingot", "default:steel_ingot" },
{ "default:chest_locked", "default:stone" },
},
})
end -- utils.digilines_supported
if utils.mesecon_supported and mesecon.mvps_push then
minetest.register_craft ({
output = "lwcomponents:movefloor",
recipe = {
{ "default:stick", "default:stick", "default:stick" },
{ "default:stick", "default:steel_ingot", "default:stick" },
{ "default:stick", "default:stick", "default:stick" },
}
})
end -- utils.mesecon_supported and mesecon.mvps_push
if utils.digilines_supported and utils.mesecon_supported then
minetest.register_craft ({
output = "lwcomponents:digiswitch 2",
recipe = {
{ "default:stone", "default:stone" },
{ "default:copper_ingot", "default:mese_crystal_fragment" },
{ "default:stick", "default:stick" },
}
})
end -- utils.digilines_supported and utils.mesecon_supported
if utils.unifieddyes_supported and utils.mesecon_supported and utils.digilines_supported then
minetest.register_craft ({
output = "lwcomputers:solid_conductor_off 3",
recipe = {
{ "default:mese_crystal_fragment", "group:wood", ""},
{ "group:wood", "group:wood", "dye:white" },
},
})
minetest.register_craft ({
output = "lwcomputers:solid_horizontal_conductor_off 3",
recipe = {
{ "group:wood", "group:wood", ""},
{ "default:mese_crystal_fragment", "group:wood", "dye:white" },
},
})
end -- utils.unifieddyes_supported and utils.mesecon_supported and utils.digilines_supported then
--

6
depends.txt Normal file
View File

@@ -0,0 +1,6 @@
default
lwdrops?
mesecons?
digilines?
unifieddyes?
intllib?

1
description.txt Normal file
View File

@@ -0,0 +1 @@
Various components for mesecons and digilines.

782
detector.lua Normal file
View File

@@ -0,0 +1,782 @@
local utils = ...
local S = utils.S
if utils.digilines_supported or utils.mesecon_supported then
local detect_interval = 0.5
local function mesecons_on (pos)
local meta = minetest.get_meta (pos)
if meta then
if meta:get_int ("power_on") == 0 then
utils.mesecon_receptor_on (pos, utils.mesecon_default_rules)
meta:set_int ("power_on", 1)
end
end
end
local function mesecons_off (pos)
local meta = minetest.get_meta (pos)
if meta then
if meta:get_int ("power_on") ~= 0 then
utils.mesecon_receptor_off (pos, utils.mesecon_default_rules)
meta:set_int ("power_on", 0)
end
end
end
local function to_relative_coords (pos, testpos)
local base = { x = testpos.x - pos.x,
y = testpos.y - pos.y,
z = testpos.z - pos.z }
local node = minetest.get_node (pos)
if node then
if node.param2 == 3 then -- +x
return { x = (base.z * -1), y = base.y, z = base.x }
elseif node.param2 == 0 then -- -z
return { x = (base.x * -1), y = base.y, z = (base.z * -1) }
elseif node.param2 == 1 then -- -x
return { x = base.z, y = base.y, z = (base.x * -1) }
elseif node.param2 == 2 then -- +z
return { x = base.x, y = base.y, z = base.z }
end
end
return { x = 0, y = 0, z = 0 }
end
local function send_detect_message (pos, item_type, name, label, item_pos, count)
if utils.digilines_supported then
local meta = minetest.get_meta (pos)
if meta then
local channel = meta:get_string ("channel")
if channel:len () > 0 then
utils.digilines_receptor_send (pos,
digiline.rules.default,
channel,
{ action = "detect",
type = item_type,
name = name,
label = label,
pos = to_relative_coords (pos, item_pos),
count = count })
end
end
end
end
local function filter_item (pos, mode, testpos)
local base = { x = math.floor (testpos.x - pos.x + 0.5),
y = math.floor (testpos.y - pos.y + 0.5),
z = math.floor (testpos.z - pos.z + 0.5) }
if base.x == 0 and base.y == 0 and base.z == 0 then
return false
end
if mode == 1 then
-- all
return true
elseif mode == 2 then
-- forward
local node = minetest.get_node (pos)
if node then
if node.param2 == 0 then
-- -z
return (base.x == 0 and base.y == 0 and base.z < 0)
elseif node.param2 == 1 then
-- -x
return (base.x < 0 and base.y == 0 and base.z == 0)
elseif node.param2 == 2 then
-- +z
return (base.x == 0 and base.y == 0 and base.z > 0)
elseif node.param2 == 3 then
-- +x
return (base.x > 0 and base.y == 0 and base.z == 0)
end
end
elseif mode == 3 then
-- up
return (base.x == 0 and base.z == 0 and base.y > 0)
elseif mode == 4 then
-- down
return (base.x == 0 and base.z == 0 and base.y < 0)
end
return false
end
local function detect (pos)
local meta = minetest.get_meta (pos)
local detected = false
if meta then
local radius = meta:get_int ("radius")
local mode = meta:get_int ("mode")
local object = minetest.get_objects_inside_radius (pos, radius + 0.5)
for i = 1, #object do
if object[i]:is_player () then
-- player
if meta:get_string ("players") == "true" and
filter_item (pos, mode, object[i]:get_pos ()) then
send_detect_message (pos,
"player",
object[i]:get_player_name (),
object[i]:get_player_name (),
object[i]:get_pos (),
1)
detected = true
end
elseif object[i].get_luaentity and object[i]:get_luaentity () and
object[i]:get_luaentity ().name and
object[i]:get_luaentity ().name == "__builtin:item" then
-- drop
if meta:get_string ("drops") == "true" and
filter_item (pos, mode, object[i]:get_pos ()) then
local stack = ItemStack (object[i]:get_luaentity ().itemstring or "")
if stack and not stack:is_empty () then
send_detect_message (pos,
"drop",
stack:get_name (),
stack:get_name (),
object[i]:get_pos (),
stack:get_count ())
detected = true
end
end
elseif object[i].get_pos and object[i]:get_pos () then
-- entity
if meta:get_string ("entities") == "true" and
filter_item (pos, mode, object[i]:get_pos ()) then
local name = object[i]:get_nametag_attributes ()
local label = ""
if type (name) == "table" then
label = tostring (name.text or "")
end
name = (object[i].get_luaentity and
object[i]:get_luaentity () and
object[i]:get_luaentity ().name) or ""
send_detect_message (pos,
"entity",
name,
label,
object[i]:get_pos (),
1)
detected = true
end
end
end
if meta:get_string ("nodes") == "true" then
for y = (pos.y - radius), (pos.y + radius) do
for x = (pos.x - radius), (pos.x + radius) do
for z = (pos.z - radius), (pos.z + radius) do
local testpos = { x = x, y = y, z = z }
local node = minetest.get_node (testpos)
if node and node.name ~= "air" and node.name ~= "ignore" and
filter_item (pos, mode, testpos) then
send_detect_message (pos,
"node",
node.name,
node.name,
testpos,
1)
detected = true
end
end
end
end
end
if detected then
mesecons_on (pos)
else
mesecons_off (pos)
end
end
end
local function get_form_spec (is_off, radius, entities, players, drops, nodes, mode)
return
"formspec_version[3]\n"..
"size[11.75,9.0;true]\n"..
"field[1.0,1.0;4.0,0.8;channel;Channel;${channel}]\n"..
"button[5.5,1.0;2.0,0.8;setchannel;Set]\n"..
"button[8.25,1.0;2.5,0.8;"..((is_off and "start;Start") or "stop;Stop").."]\n"..
"field[1.0,2.5;4.0,0.8;radius;Radius;"..tostring (radius).."]\n"..
"button[5.5,2.5;2.0,0.8;setradius;Set]\n"..
"checkbox[1.0,4.4;entities;Entities;"..entities.."]\n"..
"checkbox[1.0,5.4;players;Players;"..players.."]\n"..
"checkbox[1.0,6.4;drops;Drops;"..drops.."]\n"..
"checkbox[1.0,7.4;nodes;Nodes;"..nodes.."]\n"..
"textlist[4.875,4.0;5.875,4.0;mode;All,Forward,Up,Down;"..tostring (mode)..";false]"
end
local function update_form_spec (pos)
local node = minetest.get_node (pos)
local meta = minetest.get_meta (pos)
if node and meta then
local is_off = node.name == "lwcomponents:detector" or
node.name == "lwcomponents:detector_locked"
meta:set_string ("formspec",
get_form_spec (is_off,
meta:get_int ("radius"),
meta:get_string ("entities"),
meta:get_string ("players"),
meta:get_string ("drops"),
meta:get_string ("nodes"),
meta:get_int ("mode")))
end
end
local function start_detector (pos)
local node = minetest.get_node (pos)
local meta = minetest.get_meta (pos)
if node and meta then
if node.name == "lwcomponents:detector" then
local meta = minetest.get_meta (pos)
if meta then
node.name = "lwcomponents:detector_on"
minetest.swap_node (pos, node)
minetest.get_node_timer (pos):start (detect_interval)
update_form_spec (pos)
end
elseif node.name == "lwcomponents:detector_locked" then
local meta = minetest.get_meta (pos)
if meta then
node.name = "lwcomponents:detector_locked_on"
minetest.swap_node (pos, node)
minetest.get_node_timer (pos):start (detect_interval)
update_form_spec (pos)
end
end
end
end
local function stop_detector (pos)
local node = minetest.get_node (pos)
local meta = minetest.get_meta (pos)
if node and meta then
if node.name == "lwcomponents:detector_on" then
local meta = minetest.get_meta (pos)
if meta then
node.name = "lwcomponents:detector"
minetest.swap_node (pos, node)
minetest.get_node_timer (pos):stop ()
mesecons_off (pos)
update_form_spec (pos)
end
elseif node.name == "lwcomponents:detector_locked_on" then
local meta = minetest.get_meta (pos)
if meta then
node.name = "lwcomponents:detector_locked"
minetest.swap_node (pos, node)
minetest.get_node_timer (pos):stop ()
mesecons_off (pos)
update_form_spec (pos)
end
end
end
end
local function on_destruct (pos)
minetest.get_node_timer (pos):stop ()
mesecons_off (pos)
end
local function after_place_node (pos, placer, itemstack, pointed_thing)
local meta = minetest.get_meta (pos)
local is_off = itemstack and (itemstack:get_name () == "lwcomponents:detector" or
itemstack:get_name () == "lwcomponents:detector_locked")
meta:set_string ("inventory", "{ main = { }, filter = { } }")
meta:set_string ("formspec", get_form_spec (is_off, 1, 0, 0, 0, 0, 1))
meta:set_string ("entities", "false")
meta:set_string ("players", "false")
meta:set_string ("drops", "false")
meta:set_string ("nodes", "false")
meta:set_int ("mode", 1)
meta:set_int ("radius", 1)
meta:set_int ("power_on", 0)
-- If return true no item is taken from itemstack
return false
end
local function after_place_node_locked (pos, placer, itemstack, pointed_thing)
after_place_node (pos, placer, itemstack, pointed_thing)
if placer and placer:is_player () then
local meta = minetest.get_meta (pos)
meta:set_string ("owner", placer:get_player_name ())
meta:set_string ("infotext", "Detector (owned by "..placer:get_player_name ()..")")
end
-- If return true no item is taken from itemstack
return false
end
local function on_receive_fields (pos, formname, fields, sender)
if not utils.can_interact_with_node (pos, sender) then
return
end
if fields.setchannel then
local meta = minetest.get_meta (pos)
if meta then
meta:set_string ("channel", fields.channel)
end
end
if fields.setradius then
local meta = minetest.get_meta (pos)
if meta then
local radius = math.min (math.max (tonumber (fields.radius) or 1, 1), 5)
meta:set_int ("radius", radius)
update_form_spec (pos)
end
end
if fields.start then
start_detector (pos)
end
if fields.stop then
stop_detector (pos)
end
if fields.entities ~= nil then
local meta = minetest.get_meta (pos)
if meta then
meta:set_string ("entities", fields.entities)
update_form_spec (pos)
end
end
if fields.players ~= nil then
local meta = minetest.get_meta (pos)
if meta then
meta:set_string ("players", fields.players)
update_form_spec (pos)
end
end
if fields.drops ~= nil then
local meta = minetest.get_meta (pos)
if meta then
meta:set_string ("drops", fields.drops)
update_form_spec (pos)
end
end
if fields.nodes ~= nil then
local meta = minetest.get_meta (pos)
if meta then
meta:set_string ("nodes", fields.nodes)
update_form_spec (pos)
end
end
if fields.mode then
local event = minetest.explode_textlist_event (fields.mode)
if event.type == "CHG" then
local meta = minetest.get_meta (pos)
if meta then
meta:set_int ("mode", event.index)
update_form_spec (pos)
end
end
end
end
local function can_dig (pos, player)
if not utils.can_interact_with_node (pos, player) then
return false
end
return true
end
local function on_blast (pos, intensity)
local meta = minetest.get_meta (pos)
if meta then
if intensity >= 1.0 then
on_destruct (pos)
minetest.remove_node (pos)
else -- intensity < 1.0
local node = minetest.get_node_or_nil (pos)
if node then
local items = minetest.get_node_drops (node, nil)
if items and #items > 0 then
local stack = ItemStack (items[1])
if stack then
preserve_metadata (pos, node, meta, { stack })
utils.item_drop (stack, nil, pos)
on_destruct (pos)
minetest.remove_node (pos)
end
end
end
end
end
end
local function on_timer (pos, elapsed)
detect (pos)
return true
end
local function on_rightclick (pos, node, clicker, itemstack, pointed_thing)
if not utils.can_interact_with_node (pos, clicker) then
if clicker and clicker:is_player () then
local owner = "<unknown>"
local meta = minetest.get_meta (pos)
if meta then
owner = meta:get_string ("owner")
end
local spec =
"formspec_version[3]"..
"size[8.0,4.0,false]"..
"label[1.0,1.0;Owned by "..minetest.formspec_escape (owner).."]"..
"button_exit[3.0,2.0;2.0,1.0;close;Close]"
minetest.show_formspec (clicker:get_player_name (),
"lwcomponents:component_privately_owned",
spec)
end
end
return itemstack
end
local function digilines_support ()
if utils.digilines_supported then
return
{
wire =
{
rules = digiline.rules.default,
},
effector =
{
action = function (pos, node, channel, msg)
local meta = minetest.get_meta(pos)
if meta then
local this_channel = meta:get_string ("channel")
if this_channel == channel then
local m = { }
for w in string.gmatch(msg, "[^%s]+") do
m[#m + 1] = w
end
if m[1] == "start" then
start_detector (pos)
elseif m[1] == "stop" then
stop_detector (pos)
elseif m[1] == "radius" then
local radius = math.min (math.max (tonumber (m[2] or 1) or 1, 1), 5)
meta:set_int ("radius", radius)
update_form_spec (pos)
elseif m[1] == "entities" then
meta:set_string ("entities", ((m[2] == "true") and "true") or "false")
update_form_spec (pos)
elseif m[1] == "players" then
meta:set_string ("players", ((m[2] == "true") and "true") or "false")
update_form_spec (pos)
elseif m[1] == "drops" then
meta:set_string ("drops", ((m[2] == "true") and "true") or "false")
update_form_spec (pos)
elseif m[1] == "nodes" then
meta:set_string ("nodes", ((m[2] == "true") and "true") or "false")
update_form_spec (pos)
elseif m[1] == "mode" then
if m[2] == "all" then
meta:set_int ("mode", 1)
update_form_spec (pos)
elseif m[2] == "forward" then
meta:set_int ("mode", 2)
update_form_spec (pos)
elseif m[2] == "up" then
meta:set_int ("mode", 3)
update_form_spec (pos)
elseif m[2] == "down" then
meta:set_int ("mode", 4)
update_form_spec (pos)
end
end
end
end
end,
}
}
end
return nil
end
local function mesecon_support ()
if utils.mesecon_supported then
return
{
receptor =
{
state = utils.mesecon_state_off,
rules = utils.mesecon_default_rules
}
}
end
return nil
end
minetest.register_node("lwcomponents:detector", {
description = S("Detector"),
tiles = { "lwdetector_face.png", "lwdetector_face.png", "lwdetector.png",
"lwdetector.png", "lwdetector.png", "lwdetector_face.png"},
is_ground_content = false,
groups = { cracky = 3 },
sounds = default.node_sound_stone_defaults (),
paramtype = "light",
param1 = 0,
paramtype2 = "facedir",
param2 = 1,
floodable = false,
drop = "lwcomponents:detector",
_digistuff_channelcopier_fieldname = "channel",
mesecons = mesecon_support (),
digiline = digilines_support (),
on_destruct = on_destruct,
on_receive_fields = on_receive_fields,
can_dig = can_dig,
after_place_node = after_place_node,
on_blast = on_blast,
on_timer = on_timer,
on_rightclick = on_rightclick
})
minetest.register_node("lwcomponents:detector_locked", {
description = S("Detector (locked)"),
tiles = { "lwdetector_face.png", "lwdetector_face.png", "lwdetector.png",
"lwdetector.png", "lwdetector.png", "lwdetector_face.png"},
is_ground_content = false,
groups = { cracky = 3 },
sounds = default.node_sound_stone_defaults (),
paramtype = "light",
param1 = 0,
paramtype2 = "facedir",
param2 = 1,
floodable = false,
drop = "lwcomponents:detector_locked",
_digistuff_channelcopier_fieldname = "channel",
mesecons = mesecon_support (),
digiline = digilines_support (),
on_destruct = on_destruct,
on_receive_fields = on_receive_fields,
can_dig = can_dig,
after_place_node = after_place_node_locked,
on_blast = on_blast,
on_timer = on_timer,
on_rightclick = on_rightclick
})
minetest.register_node("lwcomponents:detector_on", {
description = S("Detector"),
tiles = { "lwdetector_face_on.png", "lwdetector_face_on.png", "lwdetector.png",
"lwdetector.png", "lwdetector.png", "lwdetector_face_on.png"},
is_ground_content = false,
groups = { cracky = 3, not_in_creative_inventory = 1 },
sounds = default.node_sound_stone_defaults (),
paramtype = "light",
param1 = 0,
paramtype2 = "facedir",
param2 = 1,
floodable = false,
drop = "lwcomponents:detector",
_digistuff_channelcopier_fieldname = "channel",
mesecons = mesecon_support (),
digiline = digilines_support (),
on_destruct = on_destruct,
on_receive_fields = on_receive_fields,
can_dig = can_dig,
after_place_node = after_place_node,
on_blast = on_blast,
on_timer = on_timer,
on_rightclick = on_rightclick
})
minetest.register_node("lwcomponents:detector_locked_on", {
description = S("Detector (locked)"),
tiles = { "lwdetector_face_on.png", "lwdetector_face_on.png", "lwdetector.png",
"lwdetector.png", "lwdetector.png", "lwdetector_face_on.png"},
is_ground_content = false,
groups = { cracky = 3, not_in_creative_inventory = 1 },
sounds = default.node_sound_stone_defaults (),
paramtype = "light",
param1 = 0,
paramtype2 = "facedir",
param2 = 1,
floodable = false,
drop = "lwcomponents:detector_locked",
_digistuff_channelcopier_fieldname = "channel",
mesecons = mesecon_support (),
digiline = digilines_support (),
on_destruct = on_destruct,
on_receive_fields = on_receive_fields,
can_dig = can_dig,
after_place_node = after_place_node_locked,
on_blast = on_blast,
on_timer = on_timer,
on_rightclick = on_rightclick
})
end -- utils.digilines_supported or utils.mesecon_supported
--

188
digiswitch.lua Normal file
View File

@@ -0,0 +1,188 @@
local utils = ...
local S = utils.S
if utils.digilines_supported and utils.mesecon_supported then
local function get_mesecon_rule_for_side (side)
local base = nil
if side == "white" then
return { { x = 0, y = 1, z = 0 } }
elseif side == "black" then
return { { x = 0, y = -1, z = 0 } } -- down doesn't work
elseif side == "red" then
return { { x = -1, y = 0, z = 0 } }
elseif side == "green" then
return { { x = 1, y = 0, z = 0 } }
elseif side == "blue" then
return { { x = 0, y = 0, z = -1 } }
elseif side == "yellow" then
return { { x = 0, y = 0, z = 1 } }
elseif side == "switch" then
return nil
else
return
{
{ 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 }, -- down doesn't work
}
end
end
local function digilines_support ()
return
{
wire =
{
rules =
{
{ x = 0, y = 0, z = -1 },
{ x = 1, y = 0, z = 0 },
{ x = -1, y = 0, z = 0 },
{ x = 0, y = 0, z = 1 },
{ x = 1, y = 1, z = 0 },
{ x = 1, y = -1, z = 0 },
{ x = -1, y = 1, z = 0 },
{ x = -1, y = -1, z = 0 },
{ x = 0, y = 1, z = 1 },
{ x = 0, y = -1, z = 1 },
{ x = 0, y = 1, z = -1 },
{ x = 0, y = -1, z = -1 },
{ x = 0, y = 1, z = 0 },
{ x = 0, y = -1, z = 0 }
}
},
effector =
{
action = function (pos, node, channel, msg)
local meta = minetest.get_meta(pos)
if meta then
local mychannel = meta:get_string ("channel")
if mychannel == channel then
if type (msg) == "string" then
local words = { }
for word in string.gmatch (msg, "%S+") do
words[#words + 1] = word
end
if words[1] == "on" then
utils.mesecon_receptor_on (pos, get_mesecon_rule_for_side (words[2]))
elseif words[1] == "off" then
utils.mesecon_receptor_off (pos, get_mesecon_rule_for_side (words[2]))
end
end
end
end
end,
}
}
end
local function mesecon_support ()
return
{
receptor =
{
state = mesecon.state.off,
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 }, -- down doesn't work
}
},
}
end
local function on_construct (pos)
local meta = minetest.get_meta (pos)
if meta then
meta:set_string ("channel", "")
local formspec =
"formspec_version[3]\n"..
"size[6.0,4.0]\n"..
"field[1.0,0.8;4.0,1.0;channel;Channel;]\n"..
"button_exit[2.0,2.5;2.0,1.0;set;Set]\n"
meta:set_string ("formspec", formspec)
end
end
local function on_destruct (pos)
utils.mesecon_receptor_off (pos, get_mesecon_rule_for_side ())
end
local function on_receive_fields (pos, formname, fields, sender)
if fields.channel then
local meta = minetest.get_meta (pos)
if meta then
meta:set_string ("channel", fields.channel or "")
local formspec =
"formspec_version[3]\n"..
"size[6.0,4.0]\n"..
"field[1.0,0.8;4.0,1.0;channel;Channel;"..minetest.formspec_escape (meta:get_string ("channel")).."]\n"..
"button_exit[2.0,2.5;2.0,1.0;set;Set]\n"
meta:set_string ("formspec", formspec)
end
end
end
minetest.register_node ("lwcomponents:digiswitch", {
description = S("Digilines Switch"),
tiles = { "lwdigiswitch_white.png", "lwdigiswitch_black.png",
"lwdigiswitch_green.png", "lwdigiswitch_red.png",
"lwdigiswitch_yellow.png", "lwdigiswitch_blue.png" },
sunlight_propagates = false,
drawtype = "normal",
node_box = {
type = "fixed",
fixed = {
{-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
}
},
groups = { cracky = 2, oddly_breakable_by_hand = 2 },
sounds = default.node_sound_stone_defaults (),
mesecons = mesecon_support (),
digiline = digilines_support (),
_digistuff_channelcopier_fieldname = "channel",
on_construct = on_construct,
on_destruct = on_destruct,
on_receive_fields = on_receive_fields,
})
end -- utils.digilines_supported and utils.mesecon_supported

429
dispenser.lua Normal file
View File

@@ -0,0 +1,429 @@
local utils = ...
local S = utils.S
if utils.digilines_supported or utils.mesecon_supported then
local function dispense_pos (pos, node)
if node.param2 == 0 then
return { x = pos.x, y = pos.y, z = pos.z - 1 }
elseif node.param2 == 1 then
return { x = pos.x - 1, y = pos.y, z = pos.z }
elseif node.param2 == 2 then
return { x = pos.x, y = pos.y, z = pos.z + 1 }
elseif node.param2 == 3 then
return { x = pos.x + 1, y = pos.y, z = pos.z }
else
return { x = pos.x, y = pos.y, z = pos.z }
end
end
local function dispense_velocity (node)
local force = 25 --math.random (30 , 35)
local tilt = (math.random (1 , 2001) - 1001) / 1000
local sway = (math.random (1 , 4001) - 2001) / 1000
if node.param2 == 0 then
return { x = sway, y = tilt, z = -force }
elseif node.param2 == 1 then
return { x = -force, y = tilt, z = sway }
elseif node.param2 == 2 then
return { x = sway, y = tilt, z = force }
elseif node.param2 == 3 then
return { x = force, y = tilt, z = sway }
else
return { x = 0, y = 0, z = 0 }
end
end
local function send_dispense_message (pos, slot, name)
if utils.digilines_supported then
local meta = minetest.get_meta (pos)
if meta then
local channel = meta:get_string ("channel")
if channel:len () > 0 then
utils.digilines_receptor_send (pos,
digiline.rules.default,
channel,
{ action = "dispense",
name = name,
slot = slot })
end
end
end
end
-- slot:
-- nil - next item, no dispense if empty
-- number - 1 item from slot, no dispense if empty
-- string - name of item to dispense, no dispense if none
local function dispense_item (pos, node, slot)
local meta = minetest.get_meta (pos)
if meta then
local inv = meta:get_inventory ()
if inv then
if not slot then
local slots = inv:get_size ("main")
for i = 1, slots do
local stack = inv:get_stack ("main", i)
if not stack:is_empty () and stack:get_count () > 0 then
slot = i
break
end
end
elseif type (slot) == "string" then
local name = slot
slot = nil
local slots = inv:get_size ("main")
for i = 1, slots do
local stack = inv:get_stack ("main", i)
if not stack:is_empty () and stack:get_count () > 0 then
if name == stack:get_name () then
slot = i
break
end
end
end
else
slot = tonumber (slot)
end
if slot then
local stack = inv:get_stack ("main", slot)
if not stack:is_empty () and stack:get_count () > 0 then
local name = stack:get_name ()
local item = ItemStack (stack)
if item then
item:set_count (1)
local obj = minetest.add_item (dispense_pos (pos, node), item)
if obj then
obj:set_velocity (dispense_velocity (node))
stack:set_count (stack:get_count () - 1)
inv:set_stack ("main", slot, stack)
send_dispense_message (pos, slot, name)
return true, slot, name
end
end
end
end
end
end
return false
end
local function after_place_node (pos, placer, itemstack, pointed_thing)
local meta = minetest.get_meta (pos)
local spec =
"formspec_version[3]\n"..
"size[11.75,13.75;true]\n"..
"field[1.0,1.0;4.0,0.8;channel;Channel;${channel}]\n"..
"button[5.5,1.0;2.0,0.8;setchannel;Set]\n"..
"list[context;main;3.5,2.5;4,4;]\n"..
"list[current_player;main;1.0,8.0;8,4;]\n"..
"listring[]"
meta:set_string ("inventory", "{ main = { } }")
meta:set_string ("formspec", spec)
local inv = meta:get_inventory ()
inv:set_size ("main", 16)
inv:set_width ("main", 4)
-- If return true no item is taken from itemstack
return false
end
local function after_place_node_locked (pos, placer, itemstack, pointed_thing)
after_place_node (pos, placer, itemstack, pointed_thing)
if placer and placer:is_player () then
local meta = minetest.get_meta (pos)
meta:set_string ("owner", placer:get_player_name ())
meta:set_string ("infotext", "Dispenser (owned by "..placer:get_player_name ()..")")
end
-- If return true no item is taken from itemstack
return false
end
local function on_receive_fields (pos, formname, fields, sender)
if not utils.can_interact_with_node (pos, sender) then
return
end
if fields.setchannel then
local meta = minetest.get_meta (pos)
if meta then
meta:set_string ("channel", fields.channel)
end
end
end
local function can_dig (pos, player)
if not utils.can_interact_with_node (pos, player) then
return false
end
local meta = minetest.get_meta (pos)
if meta then
local inv = meta:get_inventory ()
if inv then
if not inv:is_empty ("main") then
return false
end
end
end
return true
end
local function on_blast (pos, intensity)
local meta = minetest.get_meta (pos)
if meta then
if intensity >= 1.0 then
local inv = meta:get_inventory ()
if inv then
local slots = inv:get_size ("main")
for slot = 1, slots do
local stack = inv:get_stack ("main", slot)
if stack and not stack:is_empty () then
if math.floor (math.random (0, 5)) == 3 then
utils.item_drop (stack, nil, pos)
else
utils.on_destroy (stack)
end
end
end
end
minetest.remove_node (pos)
else -- intensity < 1.0
local inv = meta:get_inventory ()
if inv then
local slots = inv:get_size ("main")
for slot = 1, slots do
local stack = inv:get_stack ("main", slot)
if stack and not stack:is_empty () then
utils.item_drop (stack, nil, pos)
end
end
end
local node = minetest.get_node_or_nil (pos)
if node then
local items = minetest.get_node_drops (node, nil)
if items and #items > 0 then
local stack = ItemStack (items[1])
if stack then
preserve_metadata (pos, node, meta, { stack })
utils.item_drop (stack, nil, pos)
minetest.remove_node (pos)
end
end
end
end
end
end
local function on_rightclick (pos, node, clicker, itemstack, pointed_thing)
if not utils.can_interact_with_node (pos, clicker) then
if clicker and clicker:is_player () then
local owner = "<unknown>"
local meta = minetest.get_meta (pos)
if meta then
owner = meta:get_string ("owner")
end
local spec =
"formspec_version[3]"..
"size[8.0,4.0,false]"..
"label[1.0,1.0;Owned by "..minetest.formspec_escape (owner).."]"..
"button_exit[3.0,2.0;2.0,1.0;close;Close]"
minetest.show_formspec (clicker:get_player_name (),
"lwcomponents:component_privately_owned",
spec)
end
end
return itemstack
end
local function digilines_support ()
if utils.digilines_supported then
return
{
wire =
{
rules = digiline.rules.default,
},
effector =
{
action = function (pos, node, channel, msg)
local meta = minetest.get_meta(pos)
if meta then
local this_channel = meta:get_string ("channel")
if this_channel == channel then
local m = { }
for w in string.gmatch(msg, "[^%s]+") do
m[#m + 1] = w
end
if m[1] == "dispense" then
if m[2] and tonumber (m[2]) then
m[2] = tonumber (m[2])
end
dispense_item (pos, node, m[2])
end
end
end
end,
}
}
end
return nil
end
local function mesecon_support ()
if utils.mesecon_supported then
return
{
effector =
{
rules = utils.mesecon_flat_rules,
action_on = function (pos, node)
dispense_item (pos, node)
end
}
}
end
return nil
end
minetest.register_node("lwcomponents:dispenser", {
description = S("Dispenser"),
tiles = { "lwdispenser.png", "lwdispenser.png", "lwdispenser.png",
"lwdispenser.png", "lwdispenser.png", "lwdispenser_face.png"},
is_ground_content = false,
groups = { cracky = 3 },
sounds = default.node_sound_stone_defaults (),
paramtype = "light",
param1 = 0,
paramtype2 = "facedir",
param2 = 1,
floodable = false,
_digistuff_channelcopier_fieldname = "channel",
mesecons = mesecon_support (),
digiline = digilines_support (),
on_receive_fields = on_receive_fields,
after_place_node = after_place_node,
can_dig = can_dig,
on_blast = on_blast,
on_rightclick = on_rightclick
})
minetest.register_node("lwcomponents:dispenser_locked", {
description = S("Dispenser (locked)"),
tiles = { "lwdispenser.png", "lwdispenser.png", "lwdispenser.png",
"lwdispenser.png", "lwdispenser.png", "lwdispenser_face.png"},
is_ground_content = false,
groups = { cracky = 3 },
sounds = default.node_sound_stone_defaults (),
paramtype = "light",
param1 = 0,
paramtype2 = "facedir",
param2 = 1,
floodable = false,
_digistuff_channelcopier_fieldname = "channel",
mesecons = mesecon_support (),
digiline = digilines_support (),
on_receive_fields = on_receive_fields,
after_place_node = after_place_node_locked,
can_dig = can_dig,
on_blast = on_blast,
on_rightclick = on_rightclick
})
end -- utils.digilines_supported or utils.mesecon_supported
--

405
dropper.lua Normal file
View File

@@ -0,0 +1,405 @@
local utils = ...
local S = utils.S
if utils.digilines_supported or utils.mesecon_supported then
local function drop_pos (pos, node)
if node.param2 == 0 then
return { x = pos.x, y = pos.y, z = pos.z - 1 }
elseif node.param2 == 1 then
return { x = pos.x - 1, y = pos.y, z = pos.z }
elseif node.param2 == 2 then
return { x = pos.x, y = pos.y, z = pos.z + 1 }
elseif node.param2 == 3 then
return { x = pos.x + 1, y = pos.y, z = pos.z }
else
return { x = pos.x, y = pos.y, z = pos.z }
end
end
local function send_drop_message (pos, slot, name)
if utils.digilines_supported then
local meta = minetest.get_meta (pos)
if meta then
local channel = meta:get_string ("channel")
if channel:len () > 0 then
utils.digilines_receptor_send (pos,
digiline.rules.default,
channel,
{ action = "drop",
name = name,
slot = slot })
end
end
end
end
-- slot:
-- nil - next item, no drop if empty
-- number - 1 item from slot, no drop if empty
-- string - name of item to drop, no drop if none
local function drop_item (pos, node, slot)
local meta = minetest.get_meta (pos)
if meta then
local inv = meta:get_inventory ()
if inv then
if not slot then
local slots = inv:get_size ("main")
for i = 1, slots do
local stack = inv:get_stack ("main", i)
if not stack:is_empty () and stack:get_count () > 0 then
slot = i
break
end
end
elseif type (slot) == "string" then
local name = slot
slot = nil
local slots = inv:get_size ("main")
for i = 1, slots do
local stack = inv:get_stack ("main", i)
if not stack:is_empty () and stack:get_count () > 0 then
if name == stack:get_name () then
slot = i
break
end
end
end
else
slot = tonumber (slot)
end
if slot then
local stack = inv:get_stack ("main", slot)
if not stack:is_empty () and stack:get_count () > 0 then
local name = stack:get_name ()
local item = ItemStack (stack)
if item then
item:set_count (1)
stack:set_count (stack:get_count () - 1)
inv:set_stack ("main", slot, stack)
utils.item_drop (item, nil, drop_pos (pos, node))
send_drop_message (pos, slot, name)
return true, slot, name
end
end
end
end
end
return false
end
local function after_place_node (pos, placer, itemstack, pointed_thing)
local meta = minetest.get_meta (pos)
local spec =
"formspec_version[3]\n"..
"size[11.75,13.75;true]\n"..
"field[1.0,1.0;4.0,0.8;channel;Channel;${channel}]\n"..
"button[5.5,1.0;2.0,0.8;setchannel;Set]\n"..
"list[context;main;3.5,2.5;4,4;]\n"..
"list[current_player;main;1.0,8.0;8,4;]\n"..
"listring[]"
meta:set_string ("inventory", "{ main = { } }")
meta:set_string ("formspec", spec)
local inv = meta:get_inventory ()
inv:set_size ("main", 16)
inv:set_width ("main", 4)
-- If return true no item is taken from itemstack
return false
end
local function after_place_node_locked (pos, placer, itemstack, pointed_thing)
after_place_node (pos, placer, itemstack, pointed_thing)
if placer and placer:is_player () then
local meta = minetest.get_meta (pos)
meta:set_string ("owner", placer:get_player_name ())
meta:set_string ("infotext", "Dropper (owned by "..placer:get_player_name ()..")")
end
-- If return true no item is taken from itemstack
return false
end
local function on_receive_fields (pos, formname, fields, sender)
if not utils.can_interact_with_node (pos, sender) then
return
end
if fields.setchannel then
local meta = minetest.get_meta (pos)
if meta then
meta:set_string ("channel", fields.channel)
end
end
end
local function can_dig (pos, player)
if not utils.can_interact_with_node (pos, player) then
return false
end
local meta = minetest.get_meta (pos)
if meta then
local inv = meta:get_inventory ()
if inv then
if not inv:is_empty ("main") then
return false
end
end
end
return true
end
local function on_blast (pos, intensity)
local meta = minetest.get_meta (pos)
if meta then
if intensity >= 1.0 then
local inv = meta:get_inventory ()
if inv then
local slots = inv:get_size ("main")
for slot = 1, slots do
local stack = inv:get_stack ("main", slot)
if stack and not stack:is_empty () then
if math.floor (math.random (0, 5)) == 3 then
utils.item_drop (stack, nil, pos)
else
utils.on_destroy (stack)
end
end
end
end
minetest.remove_node (pos)
else -- intensity < 1.0
local inv = meta:get_inventory ()
if inv then
local slots = inv:get_size ("main")
for slot = 1, slots do
local stack = inv:get_stack ("main", slot)
if stack and not stack:is_empty () then
utils.item_drop (stack, nil, pos)
end
end
end
local node = minetest.get_node_or_nil (pos)
if node then
local items = minetest.get_node_drops (node, nil)
if items and #items > 0 then
local stack = ItemStack (items[1])
if stack then
preserve_metadata (pos, node, meta, { stack })
utils.item_drop (stack, nil, pos)
minetest.remove_node (pos)
end
end
end
end
end
end
local function on_rightclick (pos, node, clicker, itemstack, pointed_thing)
if not utils.can_interact_with_node (pos, clicker) then
if clicker and clicker:is_player () then
local owner = "<unknown>"
local meta = minetest.get_meta (pos)
if meta then
owner = meta:get_string ("owner")
end
local spec =
"formspec_version[3]"..
"size[8.0,4.0,false]"..
"label[1.0,1.0;Owned by "..minetest.formspec_escape (owner).."]"..
"button_exit[3.0,2.0;2.0,1.0;close;Close]"
minetest.show_formspec (clicker:get_player_name (),
"lwcomponents:component_privately_owned",
spec)
end
end
return itemstack
end
local function digilines_support ()
if utils.digilines_supported then
return
{
wire =
{
rules = digiline.rules.default,
},
effector =
{
action = function (pos, node, channel, msg)
local meta = minetest.get_meta(pos)
if meta then
local this_channel = meta:get_string ("channel")
if this_channel == channel then
local m = { }
for w in string.gmatch(msg, "[^%s]+") do
m[#m + 1] = w
end
if m[1] == "drop" then
if m[2] and tonumber (m[2]) then
m[2] = tonumber (m[2])
end
drop_item (pos, node, m[2])
end
end
end
end,
}
}
end
return nil
end
local function mesecon_support ()
if utils.mesecon_supported then
return
{
effector =
{
rules = utils.mesecon_flat_rules,
action_on = function (pos, node)
drop_item (pos, node)
end
}
}
end
return nil
end
minetest.register_node("lwcomponents:dropper", {
description = S("Dropper"),
tiles = { "lwdropper.png", "lwdropper.png", "lwdropper.png",
"lwdropper.png", "lwdropper.png", "lwdropper_face.png"},
is_ground_content = false,
groups = { cracky = 3 },
sounds = default.node_sound_stone_defaults (),
paramtype = "light",
param1 = 0,
paramtype2 = "facedir",
param2 = 1,
floodable = false,
_digistuff_channelcopier_fieldname = "channel",
mesecons = mesecon_support (),
digiline = digilines_support (),
on_receive_fields = on_receive_fields,
after_place_node = after_place_node,
can_dig = can_dig,
on_blast = on_blast,
on_rightclick = on_rightclick
})
minetest.register_node("lwcomponents:dropper_locked", {
description = S("Dropper (locked)"),
tiles = { "lwdropper.png", "lwdropper.png", "lwdropper.png",
"lwdropper.png", "lwdropper.png", "lwdropper_face.png"},
is_ground_content = false,
groups = { cracky = 3 },
sounds = default.node_sound_stone_defaults (),
paramtype = "light",
param1 = 0,
paramtype2 = "facedir",
param2 = 1,
floodable = false,
_digistuff_channelcopier_fieldname = "channel",
mesecons = mesecon_support (),
digiline = digilines_support (),
on_receive_fields = on_receive_fields,
after_place_node = after_place_node_locked,
can_dig = can_dig,
on_blast = on_blast,
on_rightclick = on_rightclick
})
end -- utils.digilines_supported or utils.mesecon_supported
--

88
extras.lua Normal file
View File

@@ -0,0 +1,88 @@
local utils = ...
local S = utils.S
local touchscreen = minetest.registered_nodes["digistuff:touchscreen"]
if touchscreen then
local touchblock = table.copy (touchscreen)
touchblock.description = S("LWComponents Touchscreen")
touchblock.node_box = {
type = "fixed",
fixed = {
{ -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 }
}
}
touchblock.selection_box = {
type = "fixed",
fixed = {
{ -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 }
}
}
touchblock.collision_box = {
type = "fixed",
fixed = {
{ -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 }
}
}
minetest.register_node ("lwcomponents:touchscreen", touchblock)
minetest.register_craft({
output = "lwcomponents:touchscreen",
recipe = {
{"mesecons_luacontroller:luacontroller0000","default:glass","default:glass"},
{"default:glass","digilines:lcd","default:glass"},
{"default:glass","default:glass","default:stone"}
}
})
end
local panel = minetest.registered_nodes["digistuff:panel"]
if panel then
local panelblock = table.copy (panel)
panelblock.description = S("LWComponents Control Panel")
panelblock.node_box = {
type = "fixed",
fixed = {
{ -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 }
}
}
panelblock.selection_box = {
type = "fixed",
fixed = {
{ -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 }
}
}
panelblock.collision_box = {
type = "fixed",
fixed = {
{ -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 }
}
}
minetest.register_node ("lwcomponents:panel", panelblock)
minetest.register_craft({
output = "lwcomponents:panel",
recipe = {
{"","digistuff:button",""},
{"digistuff:button","digilines:lcd","digistuff:button"},
{"","digistuff:button","default:stone"}
}
})
end
--

31
init.lua Normal file
View File

@@ -0,0 +1,31 @@
local version = "0.1.0"
local mod_storage = minetest.get_mod_storage ()
lwcomponents = { }
function lwcomponents.version ()
return version
end
local utils = { }
local modpath = minetest.get_modpath ("lwcomponents")
loadfile (modpath.."/utils.lua") (utils, mod_storage)
loadfile (modpath.."/dropper.lua") (utils)
loadfile (modpath.."/collector.lua") (utils)
loadfile (modpath.."/dispenser.lua") (utils)
loadfile (modpath.."/detector.lua") (utils)
loadfile (modpath.."/extras.lua") (utils)
loadfile (modpath.."/digiswitch.lua") (utils)
loadfile (modpath.."/movefloor.lua") (utils)
loadfile (modpath.."/solid_conductor.lua") (utils)
loadfile (modpath.."/crafting.lua") (utils)
--

38
license.txt Normal file
View File

@@ -0,0 +1,38 @@
Source code license
-------------------
GNU Lesser General Public License, version 2.1
Copyright (C) 2021 loosewheel
This program is free software; you can redistribute it and/or modify it under the terms
of the GNU Lesser General Public License as published by the Free Software Foundation;
either version 2.1 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details:
https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
Media license
-------------
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
You are free to:
Share — copy and redistribute the material in any medium or format.
Adapt — remix, transform, and build upon the material for any purpose, even commercially.
The licensor cannot revoke these freedoms as long as you follow the license terms.
Under the following terms:
Attribution — You must give appropriate credit, provide a link to the license, and
indicate if changes were made. You may do so in any reasonable manner, but not in any way
that suggests the licensor endorses you or your use.
ShareAlike — If you remix, transform, or build upon the material, you must distribute
your contributions under the same license as the original.
No additional restrictions — You may not apply legal terms or technological measures that
legally restrict others from doing anything the license permits.
See http://creativecommons.org/licenses/by-sa/3.0/

6
mod.conf Normal file
View File

@@ -0,0 +1,6 @@
author = loosewheel
description = Various components for mesecons and digilines.
title = LWComponents
name = lwcomponents
depends = default
optional_depends = lwdrops, mesecons, digilines, unifieddyes, intllib

199
movefloor.lua Normal file
View File

@@ -0,0 +1,199 @@
local utils = ...
local S = utils.S
if utils.mesecon_supported and mesecon.mvps_push then
local mesecon_rules =
{
{ x = 1, y = 1, z = 0 },
{ x = -1, y = 1, z = 0 },
{ x = 0, y = 1, z = 1 },
{ x = 0, y = 1, z = -1 },
{ x = 1, y = -1, z = 0 },
{ x = -1, y = -1, z = 0 },
{ x = 0, y = -1, z = 1 },
{ x = 0, y = -1, z = -1 },
}
-- use mesecons movestone settings
local timer_interval = 1 / mesecon.setting ("movestone_speed", 3)
local max_push = 3
local max_pull = 3
-- helper functions:
local function get_movefloor_direction (rulename)
if rulename.y > 0 then
return { x = 0, y = 1, z = 0 }
elseif rulename.y < 0 then
return { x = 0, y = -1, z = 0 }
end
end
local function add_movefloor_list (pos, list)
for i = 1, #list do
if list[i].x == pos.x and
list[i].y == pos.y and
list[i].z == pos.z then
return false
end
end
list[#list + 1] = { x = pos.x, y = pos.y, z = pos.z }
return true
end
local function find_adjoining_movefloor (pos, list)
local tpos =
{
{ x = pos.x + 1, y = pos.y, z = pos.z },
{ x = pos.x - 1, y = pos.y, z = pos.z },
{ x = pos.x, y = pos.y, z = pos.z + 1 },
{ x = pos.x, y = pos.y, z = pos.z - 1 }
}
for i = 1, #tpos do
local node = minetest.get_node (tpos[i])
if node and node.name == "lwcomponents:movefloor" then
if add_movefloor_list (tpos[i], list) then
find_adjoining_movefloor (tpos[i], list)
end
end
end
end
-- copied from mesecons movestone
local function movefloor_move (pos, node, rulename, is_sticky)
local direction = get_movefloor_direction (rulename)
local play_sound = false
local list =
{
{ x = pos.x, y = pos.y, z = pos.z }
}
find_adjoining_movefloor (pos, list)
for i = 1, #list do
local frontpos = vector.add (list[i], direction)
local meta = minetest.get_meta (list[i])
local owner = meta:get_string ("owner")
local continue = true
-- ### Step 1: Push nodes in front ###
local success, stack, oldstack = mesecon.mvps_push (frontpos, direction, max_push, owner)
if not success then
if stack == "protected" then
meta:set_string ("infotext", "Can't move: protected area on the way")
else
minetest.get_node_timer (list[i]):start (timer_interval)
continue = false
end
end
if continue then
mesecon.mvps_move_objects (frontpos, direction, oldstack)
-- ### Step 2: Move the movestone ###
minetest.set_node (frontpos, node)
local meta2 = minetest.get_meta (frontpos)
meta2:set_string ("owner", owner)
minetest.remove_node (list[i])
mesecon.on_dignode (list[i], node)
mesecon.on_placenode (frontpos, node)
minetest.get_node_timer (frontpos):start (timer_interval)
play_sound = true
-- ### Step 3: If sticky, pull stack behind ###
if is_sticky and direction.y < 0 then
local backpos = vector.subtract (list[i], direction)
success, stack, oldstack = mesecon.mvps_pull_all (backpos, direction, max_pull, owner)
if success then
mesecon.mvps_move_objects (backpos, vector.multiply (direction, -1), oldstack, -1)
end
end
-- ### Step 4: Let things fall ###
minetest.check_for_falling (vector.add (list[i], { x = 0, y = 1, z = 0 }))
end
end
if play_sound then
minetest.sound_play("movestone", { pos = list[i], max_hear_distance = 20, gain = 0.5 }, true)
end
end
local function on_timer (pos, elapsed)
local sourcepos = mesecon.is_powered (pos)
if not sourcepos then
return
end
local rulename = vector.subtract (sourcepos[1], pos)
mesecon.activate (pos, minetest.get_node (pos), rulename, 0)
end
local function mesecon_support ()
return
{
effector =
{
rules = table.copy (mesecon_rules),
action_on = function (pos, node, rulename)
-- do something to turn the effector on
if rulename and not minetest.get_node_timer (pos):is_started () then
movefloor_move (pos, node, rulename, true)
end
end
}
}
end
minetest.register_node("lwcomponents:movefloor", {
description = S("Moving Floor"),
tiles = { "lwmovefloortop.png", "lwmovefloortop.png",
"lwmovefloorside.png", "lwmovefloorside.png",
"lwmovefloorside.png", "lwmovefloorside.png" },
sunlight_propagates = false,
drawtype = "normal",
node_box = {
type = "fixed",
fixed = {
{-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
}
},
groups = { cracky = 2 },
sounds = default.node_sound_wood_defaults (),
mesecons = mesecon_support (),
on_timer = on_timer,
})
end

330
readme.txt Normal file
View File

@@ -0,0 +1,330 @@
LWComponents
by loosewheel
Licence
=======
Code licence:
LGPL 2.1
Media licence
CC BY-SA 3.0
Version
=======
0.1.0
Minetest Version
================
This mod was developed on version 5.4.0
Dependencies
============
default
Optional Dependencies
=====================
lwdrops
mesecons
digilines
unifieddyes
intllib
Installation
============
Copy the 'lwcomponents' folder to your mods folder.
Bug Report
==========
Description
===========
Various components for mesecons and digilines.
Dropper
-------
* This block is only available if digilines and/or mesecons are loaded.
Contains an inventory and drops an item on command. Also acts as a
digilines conductor.
UI
Channel - digilines channel of dropper.
Top 16 slot inventory - storage of items to drop.
Bottom 32 slot inventory - player's inventory.
Mesecons
Drops the next item when power is turned on.
Digilines messages
"drop"
Drops the next item. No drop if dropper is empty.
"drop <slot>"
Drops 1 item from the given slot (1 to 16). No drop if slot is empty.
eg. "drop 7"
"drop <itemname>"
Drops 1 item of the given name. No drop if dropper does not contain the
item.
eg. "drop default:stone"
When an item is dropped a digilines message is sent with the dropper's
channel. The message is a table with the following keys:
{
action = "drop",
name = "<itemname>", -- name of dropped item
slot = <slot> -- slot number the item was taken from (1 to 16).
}
Dispenser
---------
* This block is only available if digilines and/or mesecons are loaded.
Contains an inventory and dispenses (with velocity) an item on command.
Also acts as a digilines conductor.
UI
Channel - digilines channel of dispenser.
Top 16 slot inventory - storage of items to dispense.
Bottom 32 slot inventory - player's inventory.
Mesecons
Dispenses the next item when power is turned on.
Digilines messages
"dispense"
Dispenses the next item. No dispense if dispenser is empty.
"dispense <slot>"
Dispenses 1 item from the given slot (1 to 16). No dispense if slot is
empty.
eg. "dispense 7"
"dispense <itemname>"
Dispenses 1 item of the given name. No dispense if dispenser does not
contain the item.
eg. "dispense default:stone"
When an item is dropped a digilines message is sent with the dropper's
channel. The message is a table with the following keys:
{
action = "dispense",
name = "<itemname>", -- name of dropped item
slot = <slot> -- slot number the item was taken from (1 to 16).
}
Collector
---------
* This block is only available if digilines is loaded.
Picks up dropped items in adjacent block, with optional filtering. Also
acts as a digilines conductor.
UI
Channel - digilines channel of collector.
Left 16 slot inventory - storage of picked up items.
Right 8 slot inventory - Filter list. Place what items should be picked
up in this list. Leave empty to pick up all.
Bottom 32 slot inventory - player's inventory.
Digilines messages
"start"
Start the collector.
"stop"
Stop the collector.
When items are picked up a digilines message is sent with the collector's
channel. The message is a table with the following keys:
{
action = "collect",
name = "<itemname>", -- name of picked up items.
count = <count> -- number of the item picked up.
}
Detector
--------
* This block is only available if digilines and/or mesecons are loaded.
Detects items or entities within a given radius. Also acts as a
digilines conductor.
UI
Channel - digilines channel of detector.
Radius - block distance from detector to detect.
Entities - if checked detects entities.
Players - if checked detects players.
Drops - if checked detects drops.
Nodes - if checked detects nodes.
mode:
All - detects to radius in all directions, including diagonal.
Forward - detects to radius directly in front of the detector (one block high).
Up - detects to radius directly above the detector (one block wide).
Down - detects to radius directly below the detector (one block wide).
Mesecons
Mesecons power is turned on when something is detected, and turned off
when nothing is detected.
Digilines messages
"start"
Start the detector.
"stop"
Stop the detector.
"radius <n>"
Set radius of the detector. <n> should be a number from 1 to 5, and is
trimmed to this range.
"entities <true|false>"
Set detection of entities on or off.
"players <true|false>"
Set detection of players on or off.
"drops <true|false>"
Set detection of drops on or off.
"nodes <true|false>"
Set detection of nodes on or off.
"mode all"
"mode forward"
"mode up"
"mode down"
Set the detector's mode.
When items or entities are detected a digilines message is sent with the
detector's channel. A message is sent for each found item/entity. The
message is a table with the following keys:
{
action = "detect",
type = "<type>", -- will be "entity", "player", "drop" or "node"
name = "<name>",
label = "<label>",
pos = { x = n, y = n, z = n },
count = <count>
}
type
Will be "entity", "player", "drop" or "node".
name
For "entity" the registered entity name.
For "player" the player's name.
For "drop" the registered item name.
For "node" the registered item name.
label
For "entity" the name tag text.
For "player" the player's name.
For "drop" the registered item name.
For "node" the registered item name.
pos
The relative position of the detected item/entity from the detector,
facing the direction of the detector.
+x = right
-x = left
+z = forward
-z = behind
+y = above
-y = below
count
The count of items for a "drop", or 1 for everything else.
DigiSwitch
----------
* This block is only available if both digilines and mesecons are loaded.
Digiswitches act as both a digilines message target and a digilines cable,
as well as a mesecons power source. They can be placed beside each other
to form a bank, horizontally or vertically.
Right click the digiswitch to give it a channel.
Mesecon power can be delivered at 6 sides of the digiswitch, the adjacent
4 in the (x, z), above and below. Around the connector on these sides are a
colored border indicating the side. The sides are named "red", "green",
"blue", "yellow", "white" and "black".
The digilines message sent to the digiswitch dictates the action, "on" or
"off". The action can be followed with the side to act upon, separated by
a space. eg. "on white". If a side is stated only that side is acted upon.
If the side is omitted (or is invalid) all 6 sides are acted upon. If the
side name "switch" is give the power is supplied the same as a mesecons
switch (all horizontal sides, one below, this height and one above).
MoveFloor
---------
* This block is only available if mesecons and mesecons_mvps is loaded.
The MoveFloor block responds to a mesecons power source in the 4 horizontal
directions. If the power source is one higher the MoveFloor moves up to
that height. If the power source is one lower the MoveFloor moves down to
that height. Powering an adjacent block has no effect. The power source
should be turned off before another move or the MoveFloor will oscillate.
Any horizontally adjoining MoveFloor acts as a single block (only one
needs to be powered).
The MoveFloor will move up to 3 blocks stacked on it.
If using a DigiSwitch as the power source use the side name "switch" or
the MoveFloor will not move.
Solid Color Conductors
----------------------
* These blocks are only defined if mesecons, digilines, and unifieddyes are
loaded.
Provides 2 blocks that can be colored the same as Solid Color Block (with
the air brush) and is both a mesecons and digilines conductor.
The Solid Color Conductor block conducts in the 'default' directions and
the Solid Color Horizontal Conductor only conducts horizontally.
The following are also defined as variants of the original mod item, if
the relevant mod is loaded.
+ lwcomponents:touchscreen - digistuff:touchscreen as full sized node.
+ lwcomponents:panel - digistuff:panel as full sized node.
------------------------------------------------------------------------

142
solid_conductor.lua Normal file
View File

@@ -0,0 +1,142 @@
local utils = ...
local S = utils.S
if utils.unifieddyes_supported and utils.mesecon_supported and utils.digilines_supported then
mesecon.register_node (":lwcomponents:solid_conductor",
{
description = S("Solid Color Conductor"),
tiles = { "lwsolid_conductor.png" },
is_ground_content = false,
sounds = ( default and default.node_sound_wood_defaults() ),
paramtype2 = "color",
palette = "unifieddyes_palette_extended.png",
on_rotate = false,
drop = "lwcomponents:solid_conductor_off",
digiline = { wire = { rules = mesecon.rules.default } },
on_construct = unifieddyes.on_construct,
on_dig = unifieddyes.on_dig,
},
{
tiles = { "lwsolid_conductor.png" },
mesecons =
{
conductor =
{
rules = mesecon.rules.default,
state = mesecon.state.off,
onstate = "lwcomponents:solid_conductor_on",
}
},
groups = {
dig_immediate = 2,
ud_param2_colorable = 1,
},
},
{
tiles = { "lwsolid_conductor.png" },
mesecons =
{
conductor =
{
rules = mesecon.rules.default,
state = mesecon.state.on,
offstate = "lwcomponents:solid_conductor_off",
}
},
groups = {
dig_immediate = 2,
ud_param2_colorable = 1,
not_in_creative_inventory = 1
},
}
)
unifieddyes.register_color_craft ({
output = "lwcomponents:solid_conductor_off 3",
palette = "extended",
type = "shapeless",
neutral_node = "lwcomponents:solid_conductor_off",
recipe = {
"NEUTRAL_NODE",
"NEUTRAL_NODE",
"NEUTRAL_NODE",
"MAIN_DYE"
}
})
mesecon.register_node (":lwcomponents:solid_horizontal_conductor",
{
description = S("Solid Color Horizontal Conductor"),
tiles = { "lwsolid_conductor.png" },
is_ground_content = false,
sounds = ( default and default.node_sound_wood_defaults() ),
paramtype2 = "color",
palette = "unifieddyes_palette_extended.png",
on_rotate = false,
drop = "lwcomponents:solid_horizontal_conductor_off",
digiline = { wire = { rules = mesecon.rules.flat } },
on_construct = unifieddyes.on_construct,
on_dig = unifieddyes.on_dig,
},
{
tiles = { "lwsolid_conductor.png" },
mesecons =
{
conductor =
{
rules = mesecon.rules.flat,
state = mesecon.state.off,
onstate = "lwcomponents:solid_horizontal_conductor_on",
}
},
groups = {
dig_immediate = 2,
ud_param2_colorable = 1,
},
},
{
tiles = { "lwsolid_conductor.png" },
mesecons =
{
conductor =
{
rules = mesecon.rules.flat,
state = mesecon.state.on,
offstate = "lwcomponents:solid_horizontal_conductor_off",
}
},
groups = {
dig_immediate = 2,
ud_param2_colorable = 1,
not_in_creative_inventory = 1
},
}
)
unifieddyes.register_color_craft ({
output = "lwcomponents:solid_horizontal_conductor_off 3",
palette = "extended",
type = "shapeless",
neutral_node = "lwcomponents:solid_horizontal_conductor_off",
recipe = {
"NEUTRAL_NODE",
"NEUTRAL_NODE",
"NEUTRAL_NODE",
"MAIN_DYE"
}
})
end -- utils.unifieddyes_supported and utils.mesecon_supported and utils.digilines_supported then

131
utils.lua Normal file
View File

@@ -0,0 +1,131 @@
local utils, mod_storage = ...
if minetest.get_translator and minetest.get_translator ("lwcomponents") then
utils.S = minetest.get_translator ("lwcomponents")
elseif minetest.global_exists ("intllib") then
if intllib.make_gettext_pair then
utils.S = intllib.make_gettext_pair ()
else
utils.S = intllib.Getter ()
end
else
utils.S = function (s) return s end
end
-- check for mesecon
if minetest.global_exists ("mesecon") then
utils.mesecon_supported = true
utils.mesecon_state_on = mesecon.state.on
utils.mesecon_state_off = mesecon.state.off
utils.mesecon_receptor_on = mesecon.receptor_on
utils.mesecon_receptor_off = mesecon.receptor_off
utils.mesecon_default_rules = mesecon.rules.default
utils.mesecon_flat_rules = mesecon.rules.flat
else
utils.mesecon_supported = false
utils.mesecon_state_on = "on"
utils.mesecon_state_off = "off"
utils.mesecon_default_rules = { }
utils.mesecon_flat_rules = { }
-- dummies
utils.mesecon_receptor_on = function (pos, rules)
end
utils.mesecon_receptor_off = function (pos, rules)
end
end
-- check for digilines
if minetest.global_exists ("digilines") then
utils.digilines_supported = true
utils.digilines_receptor_send = digilines.receptor_send
else
utils.digilines_supported = false
-- dummy
utils.digilines_receptor_send = function (pos, rules, channel, msg)
end
end
-- check for lwdrops
if minetest.global_exists ("lwdrops") then
utils.lwdrops_supported = true
utils.on_destroy = lwdrops.on_destroy
utils.item_pickup = lwdrops.item_pickup
utils.item_drop = lwdrops.item_drop
else
utils.lwdrops_supported = false
-- dummy
utils.on_destroy = function (itemstack)
end
utils.item_pickup = function (entity, cleanup)
local stack = nil
if entity and entity.name and entity.name == "__builtin:item" and
entity.itemstring and entity.itemstring ~= "" then
stack = ItemStack (entity.itemstring)
if cleanup ~= false then
entity.itemstring = ""
entity.object:remove ()
end
end
return stack
end
utils.item_drop = function (itemstack, dropper, pos)
return minetest.item_drop (itemstack, dropper, pos)
end
end
-- check for unifieddyes
if minetest.global_exists ("unifieddyes") then
utils.unifieddyes_supported = true
else
utils.unifieddyes_supported = false
end
function utils.can_interact_with_node (pos, player)
if not player or not player:is_player () then
return false
end
if minetest.check_player_privs (player, "protection_bypass") then
return true
end
local meta = minetest.get_meta (pos)
if meta then
local owner = meta:get_string ("owner")
local name = player:get_player_name ()
if not owner or owner == "" or owner == name then
return true
end
end
return false
end
--