Skip to content

Commit 2554164

Browse files
Josh MarsJeija
Josh Mars
authored andcommittedMar 31, 2017
Improve object and node detectors
* Support detection of multiple players in object detector * Add distance parameter to node detector * Fix area protection
1 parent 967bde2 commit 2554164

File tree

3 files changed

+38
-13
lines changed

3 files changed

+38
-13
lines changed
 

Diff for: ‎mesecons_detector/doc/nodedetector/description.html

+1
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44
respond with the detected nodename or you can send any other string and it will
55
set this string as the node to scan for.
66
Nodenames must include the mod they reside in, so for instance default:dirt, not just dirt.
7+
The distance parameter specifies how many blocks are between the node detector and the node to detect.
+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
The object detector is a receptor. It changes its state when a player approaches.
22
Right-click it to set a name to scan for.
3+
You can also search for comma-separated lists of players where the detector gets activated if any of the names in the list are found.
34
It can also receive digiline signals which are the name to scan for on the specified channel in the right-click menu.

Diff for: ‎mesecons_detector/init.lua

+36-13
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,18 @@ local GET_COMMAND = "GET"
55
-- The radius can be specified in mesecons/settings.lua
66

77
local function object_detector_make_formspec(pos)
8-
minetest.get_meta(pos):set_string("formspec", "size[9,2.5]" ..
8+
local meta = minetest.get_meta(pos)
9+
meta:set_string("formspec", "size[9,2.5]" ..
910
"field[0.3, 0;9,2;scanname;Name of player to scan for (empty for any):;${scanname}]"..
1011
"field[0.3,1.5;4,2;digiline_channel;Digiline Channel (optional):;${digiline_channel}]"..
1112
"button_exit[7,0.75;2,3;;Save]")
1213
end
1314

14-
local function object_detector_on_receive_fields(pos, _, fields)
15+
local function object_detector_on_receive_fields(pos, formname, fields, sender)
1516
if not fields.scanname or not fields.digiline_channel then return end
1617

18+
if minetest.is_protected(pos, sender:get_player_name()) then return end
19+
1720
local meta = minetest.get_meta(pos)
1821
meta:set_string("scanname", fields.scanname)
1922
meta:set_string("digiline_channel", fields.digiline_channel)
@@ -28,14 +31,17 @@ local function object_detector_scan(pos)
2831
if next(objs) == nil then return false end
2932

3033
local scanname = minetest.get_meta(pos):get_string("scanname")
34+
local scan_for = {}
35+
for _, str in pairs(string.split(scanname:gsub(" ", ""), ",")) do
36+
scan_for[str] = true
37+
end
38+
3139
local every_player = scanname == ""
3240
for _, obj in pairs(objs) do
3341
-- "" is returned if it is not a player; "" ~= nil; so only handle objects with foundname ~= ""
3442
local foundname = obj:get_player_name()
35-
3643
if foundname ~= "" then
37-
-- return true if scanning for any player or if specific playername was detected
38-
if scanname == "" or foundname == scanname then
44+
if every_player or scan_for[foundname] then
3945
return true
4046
end
4147
end
@@ -128,17 +134,23 @@ minetest.register_abm({
128134
-- Detects the node in front of it
129135

130136
local function node_detector_make_formspec(pos)
131-
minetest.get_meta(pos):set_string("formspec", "size[9,2.5]" ..
137+
local meta = minetest.get_meta(pos)
138+
if meta:get_string("distance") == "" then meta:set_string("distance", "0") end
139+
meta:set_string("formspec", "size[9,2.5]" ..
132140
"field[0.3, 0;9,2;scanname;Name of node to scan for (empty for any):;${scanname}]"..
133-
"field[0.3,1.5;4,2;digiline_channel;Digiline Channel (optional):;${digiline_channel}]"..
141+
"field[0.3,1.5;2.5,2;distance;Distance (0-"..mesecon.setting("node_detector_distance_max", 10).."):;${distance}]"..
142+
"field[3,1.5;4,2;digiline_channel;Digiline Channel (optional):;${digiline_channel}]"..
134143
"button_exit[7,0.75;2,3;;Save]")
135144
end
136145

137-
local function node_detector_on_receive_fields(pos, _, fields)
146+
local function node_detector_on_receive_fields(pos, fieldname, fields, sender)
138147
if not fields.scanname or not fields.digiline_channel then return end
139148

149+
if minetest.is_protected(pos, sender:get_player_name()) then return end
150+
140151
local meta = minetest.get_meta(pos)
141152
meta:set_string("scanname", fields.scanname)
153+
meta:set_string("distance", fields.distance or "0")
142154
meta:set_string("digiline_channel", fields.digiline_channel)
143155
node_detector_make_formspec(pos)
144156
end
@@ -148,10 +160,17 @@ local function node_detector_scan(pos)
148160
local node = minetest.get_node_or_nil(pos)
149161
if not node then return end
150162

163+
local meta = minetest.get_meta(pos)
164+
165+
local distance = meta:get_int("distance")
166+
local distance_max = mesecon.setting("node_detector_distance_max", 10)
167+
if distance < 0 then distance = 0 end
168+
if distance > distance_max then distance = distance_max end
169+
151170
local frontname = minetest.get_node(
152-
vector.subtract(pos, minetest.facedir_to_dir(node.param2))
171+
vector.subtract(pos, vector.multiply(minetest.facedir_to_dir(node.param2), distance + 1))
153172
).name
154-
local scanname = minetest.get_meta(pos):get_string("scanname")
173+
local scanname = meta:get_string("scanname")
155174

156175
return (frontname == scanname) or
157176
(frontname ~= "air" and frontname ~= "ignore" and scanname == "")
@@ -162,11 +181,17 @@ local node_detector_digiline = {
162181
effector = {
163182
action = function(pos, node, channel, msg)
164183
local meta = minetest.get_meta(pos)
184+
185+
local distance = meta:get_int("distance")
186+
local distance_max = mesecon.setting("node_detector_distance_max", 10)
187+
if distance < 0 then distance = 0 end
188+
if distance > distance_max then distance = distance_max end
189+
165190
if channel ~= meta:get_string("digiline_channel") then return end
166191

167192
if msg == GET_COMMAND then
168193
local nodename = minetest.get_node(
169-
vector.subtract(pos, minetest.facedir_to_dir(node.param2))
194+
vector.subtract(pos, vector.multiply(minetest.facedir_to_dir(node.param2), distance + 1))
170195
).name
171196

172197
digiline:receptor_send(pos, digiline.rules.default, channel, nodename)
@@ -208,7 +233,6 @@ minetest.register_node("mesecons_detector:node_detector_off", {
208233
}},
209234
on_construct = node_detector_make_formspec,
210235
on_receive_fields = node_detector_on_receive_fields,
211-
after_place_node = after_place_node_detector,
212236
sounds = default.node_sound_stone_defaults(),
213237
digiline = node_detector_digiline
214238
})
@@ -225,7 +249,6 @@ minetest.register_node("mesecons_detector:node_detector_on", {
225249
}},
226250
on_construct = node_detector_make_formspec,
227251
on_receive_fields = node_detector_on_receive_fields,
228-
after_place_node = after_place_node_detector,
229252
sounds = default.node_sound_stone_defaults(),
230253
digiline = node_detector_digiline
231254
})

0 commit comments

Comments
 (0)
Please sign in to comment.