Compare commits

..

6 Commits

Author SHA1 Message Date
loosewheel
b3d0f4ebce Delete foo 2021-11-10 01:01:52 +10:00
loosewheel
a17e128f79 Add files via upload 2021-11-10 01:01:36 +10:00
loosewheel
44a3d9f80f Create foo 2021-11-10 01:01:02 +10:00
loosewheel
d027b10c21 Add files via upload 2021-11-10 00:59:52 +10:00
loosewheel
1aed7e8b78 Add files via upload 2021-11-10 00:58:25 +10:00
loosewheel
2b90c573eb Add files via upload 2021-11-10 00:57:32 +10:00
26 changed files with 1497 additions and 35 deletions

View File

@@ -1,3 +1,11 @@
v 0.1.0
* initial release
v0.1.1
* Fixed receiving digilines message on "" channel.
* Added siren.
* Made digilines optional for solid conductor blocks.
* Fixed lighting
* Added puncher

View File

@@ -400,7 +400,7 @@ local function digilines_support ()
if meta then
local this_channel = meta:get_string ("channel")
if this_channel == channel then
if this_channel ~= "" and this_channel == channel then
local m = { }
for w in string.gmatch(msg, "[^%s]+") do
m[#m + 1] = w
@@ -432,7 +432,7 @@ minetest.register_node("lwcomponents:collector", {
is_ground_content = false,
groups = { cracky = 3 },
sounds = default.node_sound_stone_defaults (),
paramtype = "light",
paramtype = "none",
param1 = 0,
floodable = false,
drop = "lwcomponents:collector",
@@ -458,7 +458,7 @@ minetest.register_node("lwcomponents:collector_locked", {
is_ground_content = false,
groups = { cracky = 3 },
sounds = default.node_sound_stone_defaults (),
paramtype = "light",
paramtype = "none",
param1 = 0,
floodable = false,
drop = "lwcomponents:collector_locked",
@@ -484,7 +484,7 @@ minetest.register_node("lwcomponents:collector_on", {
is_ground_content = false,
groups = { cracky = 3, not_in_creative_inventory = 1 },
sounds = default.node_sound_stone_defaults (),
paramtype = "light",
paramtype = "none",
param1 = 0,
floodable = false,
drop = "lwcomponents:collector",
@@ -510,7 +510,7 @@ minetest.register_node("lwcomponents:collector_locked_on", {
is_ground_content = false,
groups = { cracky = 3, not_in_creative_inventory = 1 },
sounds = default.node_sound_stone_defaults (),
paramtype = "light",
paramtype = "none",
param1 = 0,
floodable = false,
drop = "lwcomponents:collector_locked",

View File

@@ -58,6 +58,42 @@ minetest.register_craft( {
},
})
minetest.register_craft( {
output = "lwcomponents:siren",
recipe = {
{ "group:wood", "default:chest" },
{ "default:copper_ingot", "default:steel_ingot" },
},
})
minetest.register_craft( {
output = "lwcomponents:siren_locked",
recipe = {
{ "group:wood", "default:chest_locked" },
{ "default:copper_ingot", "default:steel_ingot" },
},
})
minetest.register_craft( {
output = "lwcomponents:puncher",
recipe = {
{ "default:chest", "default:sword_stone" },
{ "default:copper_ingot", "default:steel_ingot" },
},
})
minetest.register_craft( {
output = "lwcomponents:puncher_locked",
recipe = {
{ "default:chest_locked", "default:sword_stone" },
{ "default:copper_ingot", "default:steel_ingot" },
},
})
end -- utils.digilines_supported or utils.mesecon_supported
@@ -115,7 +151,7 @@ end -- utils.digilines_supported and utils.mesecon_supported
if utils.unifieddyes_supported and utils.mesecon_supported and utils.digilines_supported then
if utils.unifieddyes_supported and utils.mesecon_supported then
minetest.register_craft ({
output = "lwcomputers:solid_conductor_off 3",
@@ -134,7 +170,7 @@ minetest.register_craft ({
},
})
end -- utils.unifieddyes_supported and utils.mesecon_supported and utils.digilines_supported then
end -- utils.unifieddyes_supported and utils.mesecon_supported then

View File

@@ -576,7 +576,7 @@ local function digilines_support ()
if meta then
local this_channel = meta:get_string ("channel")
if this_channel == channel then
if this_channel ~= "" and this_channel == channel then
local m = { }
for w in string.gmatch(msg, "[^%s]+") do
m[#m + 1] = w
@@ -666,7 +666,7 @@ minetest.register_node("lwcomponents:detector", {
is_ground_content = false,
groups = { cracky = 3 },
sounds = default.node_sound_stone_defaults (),
paramtype = "light",
paramtype = "none",
param1 = 0,
paramtype2 = "facedir",
param2 = 1,
@@ -695,7 +695,7 @@ minetest.register_node("lwcomponents:detector_locked", {
is_ground_content = false,
groups = { cracky = 3 },
sounds = default.node_sound_stone_defaults (),
paramtype = "light",
paramtype = "none",
param1 = 0,
paramtype2 = "facedir",
param2 = 1,
@@ -724,7 +724,7 @@ minetest.register_node("lwcomponents:detector_on", {
is_ground_content = false,
groups = { cracky = 3, not_in_creative_inventory = 1 },
sounds = default.node_sound_stone_defaults (),
paramtype = "light",
paramtype = "none",
param1 = 0,
paramtype2 = "facedir",
param2 = 1,
@@ -753,7 +753,7 @@ minetest.register_node("lwcomponents:detector_locked_on", {
is_ground_content = false,
groups = { cracky = 3, not_in_creative_inventory = 1 },
sounds = default.node_sound_stone_defaults (),
paramtype = "light",
paramtype = "none",
param1 = 0,
paramtype2 = "facedir",
param2 = 1,

View File

@@ -71,7 +71,7 @@ local function digilines_support ()
if meta then
local mychannel = meta:get_string ("channel")
if mychannel == channel then
if mychannel ~= "" and mychannel == channel then
if type (msg) == "string" then
local words = { }

View File

@@ -325,7 +325,7 @@ local function digilines_support ()
if meta then
local this_channel = meta:get_string ("channel")
if this_channel == channel then
if this_channel ~= "" and this_channel == channel then
local m = { }
for w in string.gmatch(msg, "[^%s]+") do
m[#m + 1] = w
@@ -377,7 +377,7 @@ minetest.register_node("lwcomponents:dispenser", {
is_ground_content = false,
groups = { cracky = 3 },
sounds = default.node_sound_stone_defaults (),
paramtype = "light",
paramtype = "none",
param1 = 0,
paramtype2 = "facedir",
param2 = 1,
@@ -403,7 +403,7 @@ minetest.register_node("lwcomponents:dispenser_locked", {
is_ground_content = false,
groups = { cracky = 3 },
sounds = default.node_sound_stone_defaults (),
paramtype = "light",
paramtype = "none",
param1 = 0,
paramtype2 = "facedir",
param2 = 1,

View File

@@ -301,7 +301,7 @@ local function digilines_support ()
if meta then
local this_channel = meta:get_string ("channel")
if this_channel == channel then
if this_channel ~= "" and this_channel == channel then
local m = { }
for w in string.gmatch(msg, "[^%s]+") do
m[#m + 1] = w
@@ -353,7 +353,7 @@ minetest.register_node("lwcomponents:dropper", {
is_ground_content = false,
groups = { cracky = 3 },
sounds = default.node_sound_stone_defaults (),
paramtype = "light",
paramtype = "none",
param1 = 0,
paramtype2 = "facedir",
param2 = 1,
@@ -379,7 +379,7 @@ minetest.register_node("lwcomponents:dropper_locked", {
is_ground_content = false,
groups = { cracky = 3 },
sounds = default.node_sound_stone_defaults (),
paramtype = "light",
paramtype = "none",
param1 = 0,
paramtype2 = "facedir",
param2 = 1,

View File

@@ -1,4 +1,4 @@
local version = "0.1.0"
local version = "0.1.1"
local mod_storage = minetest.get_mod_storage ()
@@ -20,6 +20,8 @@ loadfile (modpath.."/dropper.lua") (utils)
loadfile (modpath.."/collector.lua") (utils)
loadfile (modpath.."/dispenser.lua") (utils)
loadfile (modpath.."/detector.lua") (utils)
loadfile (modpath.."/siren.lua") (utils)
loadfile (modpath.."/puncher.lua") (utils)
loadfile (modpath.."/extras.lua") (utils)
loadfile (modpath.."/digiswitch.lua") (utils)
loadfile (modpath.."/movefloor.lua") (utils)

View File

@@ -14,8 +14,57 @@ See the GNU Lesser General Public License for more details:
https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
lwsiren-buzz.ogg
----------------
derived from https://www.freesoundslibrary.com/alarm-sound-effect/
License: Attribution 4.0 International (CC BY 4.0). You are allowed to use
sound effects free of charge and royalty free in your multimedia projects
for commercial or non-commercial purposes.
https://creativecommons.org/licenses/by/4.0/
lwsiren-horn.ogg
----------------
derived from https://www.freesoundslibrary.com/ahooga-horn/
License: Attribution 4.0 International (CC BY 4.0). You are allowed to use
sound effects free of charge and royalty free in your multimedia projects
for commercial or non-commercial purposes.
https://creativecommons.org/licenses/by/4.0/
lwsiren-siren.ogg
------------------
https://www.freesoundslibrary.com/cop-siren/
License: Attribution 4.0 International (CC BY 4.0). You are allowed to use
sound effects free of charge and royalty free in your multimedia projects
for commercial or non-commercial purposes.
https://creativecommons.org/licenses/by/4.0/
lwsiren-raid.ogg
-----------------
derived from https://www.freesoundslibrary.com/space-ship-siren-sound/
License: Attribution 4.0 International (CC BY 4.0). You are allowed to use
sound effects free of charge and royalty free in your multimedia projects
for commercial or non-commercial purposes.
https://creativecommons.org/licenses/by/4.0/
Media license
-------------
siren images derived from images from https://openclipart.org, which is
public domain.
All other media, or media not covered by a licence, is licensed
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
You are free to:

572
puncher.lua Normal file
View File

@@ -0,0 +1,572 @@
local utils = ...
local S = utils.S
if utils.digilines_supported or utils.mesecon_supported then
local function direction_vector (pos)
local meta = minetest.get_meta (pos)
if meta then
local mode = meta:get_int ("mode")
if mode == 2 then
return { x = 0, y = 1, z = 0 }
elseif mode == 3 then
return { x = 0, y = -1, z = 0 }
else
local node = minetest.get_node (pos)
if node then
if node.param2 == 0 then
return { x = 0, y = 0, z = -1 }
elseif node.param2 == 1 then
return { x = -1, y = 0, z = 0 }
elseif node.param2 == 2 then
return { x = 0, y = 0, z = 1 }
elseif node.param2 == 3 then
return { x = 1, y = 0, z = 0 }
end
end
end
end
return { x = 0, y = 0, z = 0 }
end
local function punch (pos)
local meta = minetest.get_meta (pos)
local node = minetest.get_node (pos)
if meta and node and
(node.name == "lwcomponents:puncher_on" or
node.name == "lwcomponents:puncher_locked_on") then
local reach = tonumber (meta:get_string ("reach")) or 1
local dir = direction_vector (pos)
local punched = false
for r = 1, reach do
local tpos = vector.add (pos, vector.multiply (dir, r))
local object = minetest.get_objects_inside_radius (tpos, 0.68)
for i = 1, #object do
if object[i]:is_player () then
-- player
if meta:get_string ("players") == "true" then
object[i]:punch (object[i],
1.0,
{ full_punch_interval = 1.0,
damage_groups = { fleshy = 4 } },
vector.direction (pos, object[i]:get_pos ()))
punched = 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
-- don't punch drops
elseif object[i].get_pos and object[i]:get_pos () then
-- entity
if meta:get_string ("entities") == "true" then
object[i]:punch (object[i],
1.0,
{ full_punch_interval = 1.0,
damage_groups = { fleshy = 4 } },
vector.direction (pos, object[i]:get_pos ()))
punched = true
end
end
end
if punched then
break
end
end
end
end
local function get_form_spec (is_off, mode, entities, players)
return
"formspec_version[3]\n"..
"size[11.75,7.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;reach;Reach;${reach}]\n"..
"button[5.5,2.5;2.0,0.8;setreach;Set]\n"..
"checkbox[1.0,4.4;entities;Entities;"..entities.."]\n"..
"checkbox[1.0,5.4;players;Players;"..players.."]\n"..
"textlist[4.875,4.0;5.875,2.0;mode;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:puncher" or
node.name == "lwcomponents:puncher_locked"
meta:set_string ("formspec", get_form_spec (is_off,
meta:get_int ("mode"),
meta:get_string ("entities"),
meta:get_string ("players")))
end
end
local function start_puncher (pos)
local node = minetest.get_node (pos)
local meta = minetest.get_meta (pos)
if node and meta then
if node.name == "lwcomponents:puncher" then
local meta = minetest.get_meta (pos)
if meta then
node.name = "lwcomponents:puncher_on"
minetest.swap_node (pos, node)
update_form_spec (pos)
end
elseif node.name == "lwcomponents:puncher_locked" then
local meta = minetest.get_meta (pos)
if meta then
node.name = "lwcomponents:puncher_locked_on"
minetest.swap_node (pos, node)
update_form_spec (pos)
end
end
end
end
local function stop_puncher (pos)
local node = minetest.get_node (pos)
local meta = minetest.get_meta (pos)
if node and meta then
if node.name == "lwcomponents:puncher_on" then
local meta = minetest.get_meta (pos)
if meta then
node.name = "lwcomponents:puncher"
minetest.swap_node (pos, node)
update_form_spec (pos)
end
elseif node.name == "lwcomponents:puncher_locked_on" then
local meta = minetest.get_meta (pos)
if meta then
node.name = "lwcomponents:puncher_locked"
minetest.swap_node (pos, node)
update_form_spec (pos)
end
end
end
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:puncher" or
itemstack:get_name () == "lwcomponents:puncher_locked")
meta:set_string ("formspec", get_form_spec (is_off, 1, "false", "false"))
meta:set_string ("reach", "1")
meta:set_int ("mode", 1)
meta:set_string ("entities", "false")
meta:set_string ("players", "false")
-- 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", "Puncher (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.setreach then
local meta = minetest.get_meta (pos)
if meta then
local reach = math.min (math.max (tonumber (fields.reach) or 1, 1), 5)
meta:set_string ("reach", tostring (reach))
end
end
if fields.start then
start_puncher (pos)
end
if fields.stop then
stop_puncher (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.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
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)
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 ~= "" and 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_puncher (pos)
elseif m[1] == "stop" then
stop_puncher (pos)
elseif m[1] == "reach" then
local reach = math.min (math.max (tonumber (m[2]) or 1, 1), 5)
meta:set_string ("reach", tostring (reach))
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] == "mode" then
if m[2] == "forward" then
meta:set_int ("mode", 1)
update_form_spec (pos)
elseif m[2] == "up" then
meta:set_int ("mode", 2)
update_form_spec (pos)
elseif m[2] == "down" then
meta:set_int ("mode", 3)
update_form_spec (pos)
end
elseif m[1] == "punch" then
punch (pos)
end
end
end
end,
}
}
end
return nil
end
local function mesecon_support ()
if utils.mesecon_supported then
return
{
effector =
{
rules = utils.mesecon_default_rules,
action_on = function (pos, node)
-- do something to turn the effector on
punch (pos)
end
}
}
end
return nil
end
minetest.register_node("lwcomponents:puncher", {
description = S("Puncher"),
tiles = { "lwpuncher_face.png", "lwpuncher_face.png", "lwpuncher.png",
"lwpuncher.png", "lwpuncher.png", "lwpuncher_face.png"},
is_ground_content = false,
groups = { cracky = 3 },
sounds = default.node_sound_stone_defaults (),
paramtype = "none",
param1 = 0,
paramtype2 = "facedir",
param2 = 1,
floodable = false,
drop = "lwcomponents:puncher",
_digistuff_channelcopier_fieldname = "channel",
mesecons = mesecon_support (),
digiline = digilines_support (),
on_receive_fields = on_receive_fields,
can_dig = can_dig,
after_place_node = after_place_node,
on_blast = on_blast,
on_rightclick = on_rightclick
})
minetest.register_node("lwcomponents:puncher_locked", {
description = S("Puncher (locked)"),
tiles = { "lwpuncher_face.png", "lwpuncher_face.png", "lwpuncher.png",
"lwpuncher.png", "lwpuncher.png", "lwpuncher_face.png"},
is_ground_content = false,
groups = { cracky = 3 },
sounds = default.node_sound_stone_defaults (),
paramtype = "none",
param1 = 0,
paramtype2 = "facedir",
param2 = 1,
floodable = false,
drop = "lwcomponents:puncher_locked",
_digistuff_channelcopier_fieldname = "channel",
mesecons = mesecon_support (),
digiline = digilines_support (),
on_receive_fields = on_receive_fields,
can_dig = can_dig,
after_place_node = after_place_node_locked,
on_blast = on_blast,
on_rightclick = on_rightclick
})
minetest.register_node("lwcomponents:puncher_on", {
description = S("Puncher"),
tiles = { "lwpuncher_face_on.png", "lwpuncher_face_on.png", "lwpuncher.png",
"lwpuncher.png", "lwpuncher.png", "lwpuncher_face_on.png"},
is_ground_content = false,
groups = { cracky = 3, not_in_creative_inventory = 1 },
sounds = default.node_sound_stone_defaults (),
paramtype = "none",
param1 = 0,
paramtype2 = "facedir",
param2 = 1,
floodable = false,
drop = "lwcomponents:puncher",
_digistuff_channelcopier_fieldname = "channel",
mesecons = mesecon_support (),
digiline = digilines_support (),
on_receive_fields = on_receive_fields,
can_dig = can_dig,
after_place_node = after_place_node,
on_blast = on_blast,
on_rightclick = on_rightclick
})
minetest.register_node("lwcomponents:puncher_locked_on", {
description = S("Puncher (locked)"),
tiles = { "lwpuncher_face_on.png", "lwpuncher_face_on.png", "lwpuncher.png",
"lwpuncher.png", "lwpuncher.png", "lwpuncher_face_on.png"},
is_ground_content = false,
groups = { cracky = 3, not_in_creative_inventory = 1 },
sounds = default.node_sound_stone_defaults (),
paramtype = "none",
param1 = 0,
paramtype2 = "facedir",
param2 = 1,
floodable = false,
drop = "lwcomponents:puncher_locked",
_digistuff_channelcopier_fieldname = "channel",
mesecons = mesecon_support (),
digiline = digilines_support (),
on_receive_fields = on_receive_fields,
can_dig = can_dig,
after_place_node = after_place_node_locked,
on_blast = on_blast,
on_rightclick = on_rightclick
})
end -- utils.digilines_supported or utils.mesecon_supported
--

View File

@@ -13,7 +13,7 @@ CC BY-SA 3.0
Version
=======
0.1.0
0.1.1
Minetest Version
@@ -263,6 +263,101 @@ count
Siren
-----
* This block is only available if digilines and/or mesecons are loaded.
Plays a sound repeatedly while active. Also acts as a digilines conductor.
UI
Channel - digilines channel of siren.
Distance - block distance the sound can be heard (range 0 to 100).
Volume - volume the sound is played.
Sound - select Buzzer, Horn, Raid or Siren.
Mesecons
Sound plays while mesecons power is applied.
Digilines messages
"start"
Start the siren (turn on).
"stop"
Stop the siren (turn off).
"distance <n>"
Set block distance the sound can be heard. <n> should be a number
from 1 to 100, and is trimmed to this range.
"volume <n>"
Set the sound volume. <n> should be a number from 1 to 100, and is
trimmed to this range.
"sound buzzer"
"sound horn"
"sound raid"
"sound siren"
Set the sound of the siren.
"siren on"
Activate the siren, if its on.
"siren off"
deactivate the siren.
Puncher
-------
* This block is only available if digilines and/or mesecons are loaded.
Punches players or entities within a given reach. Also acts as a
digilines conductor.
UI
Channel - digilines channel of detector.
Reach - block distance from puncher to punch.
Entities - if checked punches entities.
Players - if checked punches players.
mode:
Forward - punches to reach extent directly in front of the puncher (one block high).
Up - detects to reach extent directly above the puncher (one block wide).
Down - detects to reach extent directly below the puncher (one block wide).
Mesecons
Punches the next item when power is turned on.
Digilines messages
"start"
Start the puncher.
"stop"
Stop the puncher.
"reach <n>"
Set reach of the puncher. <n> should be a number from 1 to 5, and is
trimmed to this range.
"entities <true|false>"
Set punching of entities on or off.
"players <true|false>"
Set punching of players on or off.
"mode forward"
"mode up"
"mode down"
Set the puncher's mode.
"punch"
Action a single punch if the puncher is turned on.
DigiSwitch
----------
* This block is only available if both digilines and mesecons are loaded.
@@ -309,8 +404,7 @@ the MoveFloor will not move.
Solid Color Conductors
----------------------
* These blocks are only defined if mesecons, digilines, and unifieddyes are
loaded.
* These blocks are only defined if mesecons 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.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 70 KiB

692
siren.lua Normal file
View File

@@ -0,0 +1,692 @@
local utils = ...
local S = utils.S
if utils.digilines_supported or utils.mesecon_supported then
local sound_interval = 5.0
local siren_sounds =
{
"lwsiren-buzz",
"lwsiren-horn",
"lwsiren-raid",
"lwsiren-siren",
}
local function start_sound (pos)
local meta = minetest.get_meta (pos)
if meta then
local handle = meta:get_int ("sound_handle")
if handle ~= 0 then
minetest.sound_stop (handle)
meta:set_int ("sound_handle", 0)
end
local sound = siren_sounds[meta:get_int ("sound")]
if sound then
handle = minetest.sound_play (
sound,
{
pos = pos,
max_hear_distance = meta:get_int ("distance"),
gain = meta:get_int ("gain") / 100
})
meta:set_int ("sound_handle", handle)
end
end
end
local function stop_sound (pos)
local meta = minetest.get_meta (pos)
if meta then
local handle = meta:get_int ("sound_handle")
if handle ~= 0 then
minetest.sound_stop (handle)
meta:set_int ("sound_handle", 0)
end
end
end
local function get_form_spec (is_off, distance, gain, sound)
return
"formspec_version[3]\n"..
"size[11.75,6.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"..
"label[1.0,2.5;Distance]\n"..
"scrollbaroptions[min=0;max=100;smallstep=10;largestep=10;thumbsize=10]\n"..
"scrollbar[1.0,2.9;6.0,0.5;horizontal;distance;"..tostring (distance).."]\n"..
"label[1.0,4.2;Volume]\n"..
"scrollbaroptions[min=0;max=100;smallstep=10;largestep=10;thumbsize=10]\n"..
"scrollbar[1.0,4.5;6.0,0.5;horizontal;gain;"..tostring (gain).."]\n"..
"textlist[7.75,2.25;3.0,2.75;sound;Buzzer,Horn,Raid,Siren;"..tostring (sound)..";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:siren" or
node.name == "lwcomponents:siren_locked"
meta:set_string ("formspec",
get_form_spec (is_off,
meta:get_int ("distance"),
meta:get_int ("gain"),
meta:get_int ("sound")))
end
end
local function start_siren (pos)
local node = minetest.get_node (pos)
local meta = minetest.get_meta (pos)
if node and meta then
if node.name == "lwcomponents:siren" then
local meta = minetest.get_meta (pos)
if meta then
node.name = "lwcomponents:siren_on"
stop_sound (pos)
minetest.swap_node (pos, node)
update_form_spec (pos)
end
elseif node.name == "lwcomponents:siren_locked" then
local meta = minetest.get_meta (pos)
if meta then
node.name = "lwcomponents:siren_locked_on"
stop_sound (pos)
minetest.swap_node (pos, node)
update_form_spec (pos)
end
end
end
end
local function stop_siren (pos)
local node = minetest.get_node (pos)
local meta = minetest.get_meta (pos)
if node and meta then
if node.name == "lwcomponents:siren_on" or
node.name == "lwcomponents:siren_alarm" then
local meta = minetest.get_meta (pos)
if meta then
node.name = "lwcomponents:siren"
minetest.get_node_timer (pos):stop ()
stop_sound (pos)
minetest.swap_node (pos, node)
update_form_spec (pos)
end
elseif node.name == "lwcomponents:siren_locked_on" or
node.name == "lwcomponents:siren_locked_alarm" then
local meta = minetest.get_meta (pos)
if meta then
node.name = "lwcomponents:siren_locked"
minetest.get_node_timer (pos):stop ()
stop_sound (pos)
minetest.swap_node (pos, node)
update_form_spec (pos)
end
end
end
end
local function start_alarm (pos)
local node = minetest.get_node (pos)
local meta = minetest.get_meta (pos)
if node and meta then
if node.name == "lwcomponents:siren_on" then
local meta = minetest.get_meta (pos)
if meta then
node.name = "lwcomponents:siren_alarm"
minetest.get_node_timer (pos):start (sound_interval)
start_sound (pos)
minetest.swap_node (pos, node)
end
elseif node.name == "lwcomponents:siren_locked_on" then
local meta = minetest.get_meta (pos)
if meta then
node.name = "lwcomponents:siren_locked_alarm"
minetest.get_node_timer (pos):start (sound_interval)
start_sound (pos)
minetest.swap_node (pos, node)
end
end
end
end
local function stop_alarm (pos)
local node = minetest.get_node (pos)
local meta = minetest.get_meta (pos)
if node and meta then
if node.name == "lwcomponents:siren_alarm" then
local meta = minetest.get_meta (pos)
if meta then
node.name = "lwcomponents:siren_on"
minetest.get_node_timer (pos):stop ()
stop_sound (pos)
minetest.swap_node (pos, node)
end
elseif node.name == "lwcomponents:siren_locked_alarm" then
local meta = minetest.get_meta (pos)
if meta then
node.name = "lwcomponents:siren_locked_on"
minetest.get_node_timer (pos):stop ()
stop_sound (pos)
minetest.swap_node (pos, node)
end
end
end
end
local function on_destruct (pos)
minetest.get_node_timer (pos):stop ()
stop_sound (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:siren" or
itemstack:get_name () == "lwcomponents:siren_locked")
meta:set_string ("formspec", get_form_spec (is_off, 10, 50, 1))
meta:set_int ("sound", 1)
meta:set_int ("distance", 10)
meta:set_int ("gain", 50)
meta:set_int ("sound_handle", 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.start then
start_siren (pos)
end
if fields.stop then
stop_siren (pos)
end
if fields.sound then
local event = minetest.explode_textlist_event (fields.sound)
if event.type == "CHG" then
local meta = minetest.get_meta (pos)
if meta then
meta:set_int ("sound", event.index)
end
end
end
if fields.gain then
local event = minetest.explode_scrollbar_event (fields.gain)
if event.type == "CHG" then
local meta = minetest.get_meta (pos)
if meta then
meta:set_int ("gain", event.value)
end
end
end
if fields.distance then
local event = minetest.explode_scrollbar_event (fields.distance)
if event.type == "CHG" then
local meta = minetest.get_meta (pos)
if meta then
meta:set_int ("distance", event.value)
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)
start_sound (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
else
update_form_spec (pos)
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 ~= "" and 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_siren (pos)
elseif m[1] == "stop" then
stop_siren (pos)
elseif m[1] == "siren" then
if m[2] == "on" then
start_alarm (pos)
elseif m[2] == "off" then
stop_alarm (pos)
end
elseif m[1] == "distance" then
local distance = math.min (math.max (tonumber (m[2] or 1) or 1, 1), 100)
meta:set_int ("distance", distance)
elseif m[1] == "volume" then
local volume = math.min (math.max (tonumber (m[2] or 1) or 1, 1), 100)
meta:set_int ("gain", volume)
elseif m[1] == "sound" then
if m[2] == "buzzer" then
meta:set_int ("sound", 1)
update_form_spec (pos)
elseif m[2] == "horn" then
meta:set_int ("sound", 2)
update_form_spec (pos)
elseif m[2] == "raid" then
meta:set_int ("sound", 3)
update_form_spec (pos)
elseif m[2] == "siren" then
meta:set_int ("sound", 4)
update_form_spec (pos)
end
end
end
end
end,
}
}
end
return nil
end
local function mesecon_support ()
if utils.mesecon_supported then
return
{
effector =
{
rules = utils.mesecon_default_rules,
action_on = function (pos, node)
-- do something to turn the effector on
start_alarm (pos)
end,
action_off = function (pos, node)
-- do something to turn the effector off
stop_alarm (pos)
end,
}
}
end
return nil
end
minetest.register_node("lwcomponents:siren", {
description = S("Siren"),
tiles = { "lwsiren_base.png", "lwsiren_base.png", "lwsiren.png",
"lwsiren.png", "lwsiren.png", "lwsiren.png"},
is_ground_content = false,
groups = { cracky = 3 },
sounds = default.node_sound_stone_defaults (),
paramtype = "none",
param1 = 0,
floodable = false,
drop = "lwcomponents:siren",
_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:siren_locked", {
description = S("Siren (locked)"),
tiles = { "lwsiren_base.png", "lwsiren_base.png", "lwsiren.png",
"lwsiren.png", "lwsiren.png", "lwsiren.png"},
is_ground_content = false,
groups = { cracky = 3 },
sounds = default.node_sound_stone_defaults (),
paramtype = "none",
param1 = 0,
floodable = false,
drop = "lwcomponents:siren_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:siren_on", {
description = S("Siren"),
tiles = { "lwsiren_base.png", "lwsiren_base.png", "lwsiren_on.png",
"lwsiren_on.png", "lwsiren_on.png", "lwsiren_on.png"},
is_ground_content = false,
groups = { cracky = 3, not_in_creative_inventory = 1 },
sounds = default.node_sound_stone_defaults (),
paramtype = "none",
param1 = 0,
floodable = false,
drop = "lwcomponents:siren",
_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:siren_locked_on", {
description = S("Siren (locked)"),
tiles = { "lwsiren_base.png", "lwsiren_base.png", "lwsiren_on.png",
"lwsiren_on.png", "lwsiren_on.png", "lwsiren_on.png"},
is_ground_content = false,
groups = { cracky = 3, not_in_creative_inventory = 1 },
sounds = default.node_sound_stone_defaults (),
paramtype = "none",
param1 = 0,
floodable = false,
drop = "lwcomponents:siren_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:siren_alarm", {
description = S("Siren"),
tiles = { "lwsiren_base.png", "lwsiren_base.png", "lwsiren_alarm.png",
"lwsiren_alarm.png", "lwsiren_alarm.png", "lwsiren_alarm.png"},
is_ground_content = false,
groups = { cracky = 3, not_in_creative_inventory = 1 },
sounds = default.node_sound_stone_defaults (),
paramtype = "none",
param1 = 0,
light_source = 3,
floodable = false,
drop = "lwcomponents:siren",
_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:siren_locked_alarm", {
description = S("Siren (locked)"),
tiles = { "lwsiren_base.png", "lwsiren_base.png", "lwsiren_alarm.png",
"lwsiren_alarm.png", "lwsiren_alarm.png", "lwsiren_alarm.png"},
is_ground_content = false,
groups = { cracky = 3, not_in_creative_inventory = 1 },
sounds = default.node_sound_stone_defaults (),
paramtype = "none",
param1 = 0,
light_source = 3,
floodable = false,
drop = "lwcomponents:siren_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
--

View File

@@ -3,7 +3,7 @@ local S = utils.S
if utils.unifieddyes_supported and utils.mesecon_supported and utils.digilines_supported then
if utils.unifieddyes_supported and utils.mesecon_supported then
@@ -17,7 +17,7 @@ mesecon.register_node (":lwcomponents:solid_conductor",
palette = "unifieddyes_palette_extended.png",
on_rotate = false,
drop = "lwcomponents:solid_conductor_off",
digiline = { wire = { rules = mesecon.rules.default } },
digiline = { wire = { rules = utils.digilines_default_rules } },
on_construct = unifieddyes.on_construct,
on_dig = unifieddyes.on_dig,
},
@@ -27,8 +27,8 @@ mesecon.register_node (":lwcomponents:solid_conductor",
{
conductor =
{
rules = mesecon.rules.default,
state = mesecon.state.off,
rules = utils.mesecon_default_rules,
state = utils.mesecon_state_off,
onstate = "lwcomponents:solid_conductor_on",
}
},
@@ -43,8 +43,8 @@ mesecon.register_node (":lwcomponents:solid_conductor",
{
conductor =
{
rules = mesecon.rules.default,
state = mesecon.state.on,
rules = utils.mesecon_default_rules,
state = utils.mesecon_state_on,
offstate = "lwcomponents:solid_conductor_off",
}
},
@@ -83,7 +83,7 @@ mesecon.register_node (":lwcomponents:solid_horizontal_conductor",
palette = "unifieddyes_palette_extended.png",
on_rotate = false,
drop = "lwcomponents:solid_horizontal_conductor_off",
digiline = { wire = { rules = mesecon.rules.flat } },
digiline = { wire = { rules = utils.digilines_flat_rules } },
on_construct = unifieddyes.on_construct,
on_dig = unifieddyes.on_dig,
},
@@ -93,8 +93,8 @@ mesecon.register_node (":lwcomponents:solid_horizontal_conductor",
{
conductor =
{
rules = mesecon.rules.flat,
state = mesecon.state.off,
rules = utils.mesecon_flat_rules,
state = utils.mesecon_state_off,
onstate = "lwcomponents:solid_horizontal_conductor_on",
}
},
@@ -109,8 +109,8 @@ mesecon.register_node (":lwcomponents:solid_horizontal_conductor",
{
conductor =
{
rules = mesecon.rules.flat,
state = mesecon.state.on,
rules = utils.mesecon_flat_rules,
state = utils.mesecon_state_on,
offstate = "lwcomponents:solid_horizontal_conductor_off",
}
},
@@ -139,4 +139,4 @@ unifieddyes.register_color_craft ({
end -- utils.unifieddyes_supported and utils.mesecon_supported and utils.digilines_supported then
end -- utils.unifieddyes_supported and utils.mesecon_supported then

BIN
sounds/lwsiren-buzz.ogg Normal file

Binary file not shown.

BIN
sounds/lwsiren-horn.ogg Normal file

Binary file not shown.

BIN
sounds/lwsiren-raid.ogg Normal file

Binary file not shown.

BIN
sounds/lwsiren-siren.ogg Normal file

Binary file not shown.

BIN
textures/lwpuncher.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 495 B

BIN
textures/lwpuncher_face.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 437 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 477 B

BIN
textures/lwsiren.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 793 B

BIN
textures/lwsiren_alarm.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 826 B

BIN
textures/lwsiren_base.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 495 B

BIN
textures/lwsiren_on.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 794 B

View File

@@ -47,9 +47,18 @@ end
-- check for digilines
if minetest.global_exists ("digilines") then
utils.digilines_supported = true
utils.digilines_default_rules = digiline.rules.default
utils.digilines_flat_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 },
}
utils.digilines_receptor_send = digilines.receptor_send
else
utils.digilines_supported = false
utils.digilines_default_rules = { }
utils.digilines_flat_rules = { }
-- dummy
utils.digilines_receptor_send = function (pos, rules, channel, msg)