1+
2+ local formspec = " size[8,4]" ..
3+ " field[1.3,1;6,1;channel;Channel;${channel}]" ..
4+ " field[1.3,2;3,1.3;radius;Radius;${radius}]" ..
5+ " field[4.3,2;3,1.3;distance;Distance;${distance}]" ..
6+ " button_exit[4,3;3,1;submit;Save]"
7+
8+ local function get_formspec (enabled )
9+ if enabled then
10+ return formspec .. " button[1,3;3,1;disable;Disable]"
11+ else
12+ return formspec .. " button[1,3;3,1;enable;Enable]"
13+ end
14+ end
15+
16+ local function search_for_players (pos , send_empty )
17+ local meta = minetest .get_meta (pos )
18+ local distance = meta :get_int (" distance" )
19+ local dir = minetest .facedir_to_dir (minetest .get_node (pos ).param2 )
20+ local spot = vector .add (pos , vector .multiply (dir , - distance ))
21+ local node = minetest .get_node (spot )
22+ while node .name == " air" and pos .y - spot .y < 10 do
23+ spot .y = spot .y - 1
24+ node = minetest .get_node (spot )
25+ end
26+ if node .name == " air" or node .name == " ignore" then
27+ return true
28+ end
29+ local radius = meta :get_int (" radius" )
30+ local found = {}
31+ for _ ,player in pairs (minetest .get_connected_players ()) do
32+ if vector .distance (spot , player :get_pos ()) <= radius then
33+ table.insert (found , player :get_player_name ())
34+ end
35+ end
36+ if # found > 0 or send_empty == true then
37+ local channel = meta :get_string (" channel" )
38+ digilines .receptor_send (pos , digilines .rules .default , channel , found )
39+ end
40+ return true
41+ end
42+
143minetest .register_node (" digistuff:camera" , {
44+ description = " Digilines Camera" ,
245 tiles = {
346 " digistuff_camera_top.png" ,
447 " digistuff_camera_bottom.png" ,
@@ -7,84 +50,100 @@ minetest.register_node("digistuff:camera", {
750 " digistuff_camera_back.png" ,
851 " digistuff_camera_front.png" ,
952 },
10- digiline = {
11- receptor = {}
12- },
13- _digistuff_channelcopier_fieldname = " channel" ,
14- groups = {cracky = 2 },
1553 paramtype = " light" ,
1654 paramtype2 = " facedir" ,
1755 drawtype = " nodebox" ,
1856 node_box = {
1957 type = " fixed" ,
2058 fixed = {
21- {- 0.1 ,- 0.5 ,- 0.28 ,0.1 ,- 0.3 ,0.3 }, -- Camera Body
22- {- 0.045 ,- 0.42 ,- 0.34 ,0.045 ,- 0.36 ,- 0.28 }, -- Lens
23- {- 0.05 ,- 0.9 ,- 0.05 ,0.05 ,- 0.5 ,0.05 }, -- Pole
24- }
59+ {- 0.1 ,- 0.5 ,- 0.28 ,0.1 ,- 0.3 ,0.3 }, -- Camera Body
60+ {- 0.045 ,- 0.42 ,- 0.34 ,0.045 ,- 0.36 ,- 0.28 }, -- Lens
61+ {- 0.05 ,- 0.9 ,- 0.05 ,0.05 ,- 0.5 ,0.05 }, -- Pole
62+ }
2563 },
2664 selection_box = {
2765 type = " fixed" ,
2866 fixed = {
29- {- 0.1 ,- 0.5 ,- 0.34 ,0.1 ,- 0.3 ,0.3 }, -- Camera Body
30- }
67+ {- 0.1 ,- 0.5 ,- 0.34 ,0.1 ,- 0.3 ,0.3 },
68+ }
3169 },
32- description = " Digilines Camera" ,
70+ sounds = default and default .node_sound_stone_defaults (),
71+ groups = {cracky = 2 },
3372 on_construct = function (pos )
3473 local meta = minetest .get_meta (pos )
35- meta :set_string (" formspec" ," size[8,6;]field[1,1;6,2;channel;Channel;${channel}]field[1,2;6,2;radius;Radius (max 10);${radius}]field[1,3;6,2;distance;Distance (max 20);${distance}]button_exit[2.25,4;3,1;submit;Save]" )
74+ meta :set_string (" formspec" , get_formspec (true ))
75+ meta :set_int (" radius" , 1 )
76+ meta :set_int (" distance" , 0 )
77+ minetest .get_node_timer (pos ):start (1 )
3678 end ,
37- on_receive_fields = function (pos , formname , fields , sender )
38- local name = sender :get_player_name ()
39- if minetest .is_protected (pos ,name ) and not minetest .check_player_privs (name ,{protection_bypass = true }) then
40- minetest .record_protection_violation (pos ,name )
79+ on_receive_fields = function (pos , _ , fields , player )
80+ if minetest .is_protected (pos , player :get_player_name ()) then
4181 return
4282 end
4383 local meta = minetest .get_meta (pos )
44- if fields .channel then meta :set_string (" channel" ,fields .channel ) end
45- if fields .distance and tonumber (fields .distance ) then meta :set_int (" distance" ,math.max (math.min (20 ,fields .distance ),0 )) end
46- if fields .radius and tonumber (fields .radius ) then meta :set_int (" radius" ,math.max (math.min (10 ,fields .radius ),1 )) end
84+ if fields .channel then
85+ meta :set_string (" channel" , fields .channel )
86+ end
87+ if fields .radius then
88+ local value = math.max (1 , math.min (10 , tonumber (fields .radius ) or 1 ))
89+ meta :set_int (" radius" , value )
90+ end
91+ if fields .distance then
92+ local value = math.max (0 , math.min (20 , tonumber (fields .distance ) or 0 ))
93+ meta :set_int (" distance" , value )
94+ end
95+ if fields .enable then
96+ meta :set_string (" formspec" , get_formspec (true ))
97+ minetest .get_node_timer (pos ):start (1 )
98+ elseif fields .disable then
99+ meta :set_string (" formspec" , get_formspec (false ))
100+ minetest .get_node_timer (pos ):stop ()
101+ end
47102 end ,
48- sounds = default and default .node_sound_stone_defaults ()
103+ on_timer = search_for_players ,
104+ digiline = {
105+ receptor = {},
106+ effector = {
107+ action = function (pos , node , channel , msg )
108+ local meta = minetest .get_meta (pos )
109+ if channel ~= meta :get_string (" channel" ) then return end
110+ if type (msg ) == " table" then
111+ if msg .radius then
112+ local value = math.max (1 , math.min (10 , tonumber (msg .radius ) or 1 ))
113+ meta :set_int (" radius" , value )
114+ end
115+ if msg .distance then
116+ local value = math.max (0 , math.min (20 , tonumber (msg .distance ) or 0 ))
117+ meta :set_int (" distance" , value )
118+ end
119+ if msg .command == " get" then
120+ search_for_players (pos , true )
121+ end
122+ elseif msg == " GET" or msg == " get" then
123+ search_for_players (pos , true )
124+ end
125+ end ,
126+ },
127+ },
128+ _digistuff_channelcopier_fieldname = " channel" ,
49129})
50130
51- minetest .register_abm ({
131+ minetest .register_lbm ({
132+ label = " Digistuff camera update" ,
133+ name = " digistuff:camera_update" ,
52134 nodenames = {" digistuff:camera" },
53- interval = 1.0 ,
54- chance = 1 ,
55- action = function (pos ,node )
56- local meta = minetest .get_meta (pos )
57- local channel = meta :get_string (" channel" )
58- local radius = meta :get_int (" radius" )
59- local distance = meta :get_int (" distance" )
60- local dir = vector .multiply (minetest .facedir_to_dir (node .param2 ),- 1 )
61- local spot = vector .add (pos ,vector .multiply (dir ,distance ))
62- local i = 0
63- while i <= 10 and minetest .get_node (spot ).name == " air" do
64- -- Downward search for ground level
65- spot = vector .add (spot ,vector .new (0 ,- 1 ,0 ))
66- i = i + 1
67- end
68- if minetest .get_node (spot ).name == " air" or minetest .get_node (spot ).name == " ignore" then
69- -- Ground not in range
70- return
71- end
72-
73- local found_any = false
74- local players_found = {}
75- local objs = minetest .get_objects_inside_radius (spot ,radius )
76- if objs then
77- for _ ,obj in ipairs (objs ) do
78- if obj :is_player () then
79- table.insert (players_found ,obj :get_player_name ())
80- found_any = true
81- end
82- end
83- if found_any then
84- digilines .receptor_send ({x = pos .x ,y = pos .y - 1 ,z = pos .z }, digilines .rules .default , channel , players_found )
85- end
86- end
135+ run_at_every_load = false ,
136+ action = function (pos )
137+ local meta = minetest .get_meta (pos )
138+ if not meta :get (" radius" ) then
139+ meta :set_int (" radius" , 1 )
140+ end
141+ if not meta :get (" distance" ) then
142+ meta :set_int (" distance" , 0 )
87143 end
144+ meta :set_string (" formspec" , get_formspec (true ))
145+ minetest .get_node_timer (pos ):start (1 )
146+ end ,
88147})
89148
90149minetest .register_craft ({
0 commit comments