Add files via upload
This commit is contained in:
3
change.log
Normal file
3
change.log
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
v 0.1.0
|
||||
* initial release
|
536
collector.lua
Normal file
536
collector.lua
Normal 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
141
crafting.lua
Normal 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
6
depends.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
default
|
||||
lwdrops?
|
||||
mesecons?
|
||||
digilines?
|
||||
unifieddyes?
|
||||
intllib?
|
1
description.txt
Normal file
1
description.txt
Normal file
@@ -0,0 +1 @@
|
||||
Various components for mesecons and digilines.
|
782
detector.lua
Normal file
782
detector.lua
Normal 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
188
digiswitch.lua
Normal 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
429
dispenser.lua
Normal 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
405
dropper.lua
Normal 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
88
extras.lua
Normal 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
31
init.lua
Normal 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
38
license.txt
Normal 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
6
mod.conf
Normal 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
199
movefloor.lua
Normal 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
330
readme.txt
Normal 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
142
solid_conductor.lua
Normal 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
131
utils.lua
Normal 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
|
||||
|
||||
|
||||
|
||||
--
|
Reference in New Issue
Block a user