-
Notifications
You must be signed in to change notification settings - Fork 6
/
camera.lua
175 lines (167 loc) · 5.09 KB
/
camera.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
local formspec = "size[8,4]"..
"field[1.3,1;6,1;channel;Channel;${channel}]"..
"field[1.3,2;3,1.3;radius;Radius;${radius}]"..
"field[4.3,2;3,1.3;distance;Distance;${distance}]"..
"button_exit[4,3;3,1;submit;Save]"
local function get_formspec(enabled)
if enabled then
return formspec.."button[1,3;3,1;disable;Disable]"
else
return formspec.."button[1,3;3,1;enable;Enable]"
end
end
local function get_search_spot(pos, meta)
local distance = meta:get_int("distance")
local dir = minetest.facedir_to_dir(minetest.get_node(pos).param2)
local spot = vector.add(pos, vector.multiply(dir, -distance))
local node = minetest.get_node(spot)
while node.name == "air" and pos.y - spot.y < 10 do
spot.y = spot.y - 1
node = minetest.get_node(spot)
end
if node.name == "air" or node.name == "ignore" then
-- Default to directly in front of camera if ground is not found.
spot.y = pos.y
end
return spot
end
local function search_for_players(pos, send_empty)
local meta = minetest.get_meta(pos)
local spot = get_search_spot(pos, meta)
local radius = meta:get_int("radius")
local found = {}
for _,player in pairs(minetest.get_connected_players()) do
if vector.distance(spot, player:get_pos()) <= radius then
table.insert(found, player:get_player_name())
end
end
if #found > 0 or send_empty == true then
local channel = meta:get_string("channel")
digilines.receptor_send(pos, digilines.rules.default, channel, found)
end
return true
end
local function show_area(pos, node, player)
if not player or player:get_wielded_item():get_name() ~= "" then
-- Only show area when using an empty hand
return
end
local meta = minetest.get_meta(pos)
local spot = get_search_spot(pos, meta)
local radius = meta:get_int("radius")
vizlib.draw_sphere(spot, radius, {player = player})
end
minetest.register_node("digistuff:camera", {
description = "Digilines Camera",
tiles = {
"digistuff_camera_top.png",
"digistuff_camera_bottom.png",
"digistuff_camera_right.png",
"digistuff_camera_left.png",
"digistuff_camera_back.png",
"digistuff_camera_front.png",
},
paramtype = "light",
paramtype2 = "facedir",
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
{-0.1,-0.5,-0.28,0.1,-0.3,0.3}, -- Camera Body
{-0.045,-0.42,-0.34,0.045,-0.36,-0.28}, -- Lens
{-0.05,-0.9,-0.05,0.05,-0.5,0.05}, -- Pole
}
},
selection_box = {
type = "fixed",
fixed = {
{-0.1,-0.5,-0.34,0.1,-0.3,0.3},
}
},
sounds = default and default.node_sound_stone_defaults(),
groups = {cracky = 2},
is_ground_content = false,
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("formspec", get_formspec(true))
meta:set_int("radius", 1)
meta:set_int("distance", 0)
minetest.get_node_timer(pos):start(1)
end,
on_receive_fields = function(pos, _, fields, player)
if minetest.is_protected(pos, player:get_player_name()) then
return
end
local meta = minetest.get_meta(pos)
if fields.channel then
meta:set_string("channel", fields.channel)
end
if fields.radius then
local value = math.max(1, math.min(10, tonumber(fields.radius) or 1))
meta:set_int("radius", value)
end
if fields.distance then
local value = math.max(0, math.min(20, tonumber(fields.distance) or 0))
meta:set_int("distance", value)
end
if fields.enable then
meta:set_string("formspec", get_formspec(true))
minetest.get_node_timer(pos):start(1)
elseif fields.disable then
meta:set_string("formspec", get_formspec(false))
minetest.get_node_timer(pos):stop()
end
end,
on_timer = search_for_players,
on_punch = minetest.get_modpath("vizlib") and show_area or nil,
digiline = {
receptor = {},
effector = {
action = function(pos, node, channel, msg)
local meta = minetest.get_meta(pos)
if channel ~= meta:get_string("channel") then return end
if type(msg) == "table" then
if msg.radius then
local value = math.max(1, math.min(10, tonumber(msg.radius) or 1))
meta:set_int("radius", value)
end
if msg.distance then
local value = math.max(0, math.min(20, tonumber(msg.distance) or 0))
meta:set_int("distance", value)
end
if msg.command == "get" then
search_for_players(pos, true)
end
elseif msg == "GET" or msg == "get" then
search_for_players(pos, true)
end
end,
},
},
_digistuff_channelcopier_fieldname = "channel",
})
minetest.register_lbm({
label = "Digistuff camera update",
name = "digistuff:camera_update",
nodenames = {"digistuff:camera"},
run_at_every_load = false,
action = function(pos)
local meta = minetest.get_meta(pos)
if not meta:get("radius") then
meta:set_int("radius", 1)
end
if not meta:get("distance") then
meta:set_int("distance", 0)
end
meta:set_string("formspec", get_formspec(true))
minetest.get_node_timer(pos):start(1)
end,
})
minetest.register_craft({
output = "digistuff:camera",
recipe = {
{"homedecor:plastic_sheeting","homedecor:plastic_sheeting","homedecor:plastic_sheeting"},
{"default:glass","homedecor:ic","mesecons_luacontroller:luacontroller0000"},
{"homedecor:plastic_sheeting","homedecor:plastic_sheeting","homedecor:plastic_sheeting"},
}
})