-
Notifications
You must be signed in to change notification settings - Fork 12
/
init.lua
180 lines (159 loc) · 5.86 KB
/
init.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
176
177
178
179
180
local strip_color_codes = minetest.settings:get_bool("strip_color_codes", false)
local function initialize_data(meta)
local NEAREST_MAX_DISTANCE = moremesecons.setting("commandblock", "nearest_max_distance", 8, 1)
local commands = meta:get_string("commands")
meta:set_string("formspec",
"invsize[9,5;]" ..
"textarea[0.5,0.5;8.5,4;commands;Commands;"..minetest.formspec_escape(commands).."]" ..
"label[1,3.8;@nearest is replaced by the nearest player name ("..tostring(NEAREST_MAX_DISTANCE).." nodes max for the nearest distance)".."]" ..
"button_exit[3.3,4.5;2,1;submit;Submit]")
local owner = meta:get_string("owner")
if owner == "" then
owner = "not owned"
else
owner = "owned by " .. owner
end
meta:set_string("infotext", "Command Block\n" ..
"(" .. owner .. ")\n" ..
"Commands: "..commands)
end
local function construct(pos)
local meta = minetest.get_meta(pos)
meta:set_string("commands", "tell @nearest Commandblock unconfigured")
meta:set_string("owner", "")
initialize_data(meta)
end
local function after_place(pos, placer)
if placer then
local meta = minetest.get_meta(pos)
meta:set_string("owner", placer:get_player_name())
initialize_data(meta)
end
end
local function receive_fields(pos, _, fields, player)
if not fields.submit then
return
end
local meta = minetest.get_meta(pos)
local owner = meta:get_string("owner")
if owner ~= ""
and player:get_player_name() ~= owner then
return
end
if strip_color_codes then
meta:set_string("commands", minetest.strip_colors(fields.commands))
else
meta:set_string("commands", fields.commands)
end
initialize_data(meta)
end
local function resolve_commands(commands, pos)
local nearest = ""
local min_distance = math.huge
local players = minetest.get_connected_players()
for _, player in pairs(players) do
local distance = vector.distance(pos, player:get_pos())
if distance < min_distance then
min_distance = distance
nearest = player:get_player_name()
end
end
local new_commands = commands:gsub("@nearest", nearest)
return new_commands, min_distance, new_commands ~= commands
end
local function commandblock_action_on(pos, node)
local NEAREST_MAX_DISTANCE = moremesecons.setting("commandblock", "nearest_max_distance", 8, 1)
local accepted_commands = {}
do
local commands_str = moremesecons.setting("commandblock", "authorized_commands", "tell")
for command in string.gmatch(commands_str, "([^ ]+)") do
accepted_commands[command] = true
end
end
if node.name ~= "moremesecons_commandblock:commandblock_off" then
return
end
minetest.swap_node(pos, {name = "moremesecons_commandblock:commandblock_on"})
local meta = minetest.get_meta(pos)
local owner = meta:get_string("owner")
if owner == "" then
return
end
local commands, distance, nearest_in_commands = resolve_commands(meta:get_string("commands"), pos)
if distance > NEAREST_MAX_DISTANCE and nearest_in_commands then
minetest.chat_send_player(owner, "The nearest player is too far to use his name in the commands of a craftable command block.")
return
end
for _, command in pairs(commands:split("\n")) do
local pos = command:find(" ")
local cmd, param = command, ""
if pos then
cmd = command:sub(1, pos - 1)
param = command:sub(pos + 1)
end
local cmddef = minetest.chatcommands[cmd]
if not accepted_commands[cmd] and next(accepted_commands) then
minetest.chat_send_player(owner, "You can not execute the command "..cmd.." with a craftable command block ! This event will be reported.")
minetest.log("action", "Player "..owner.." tryed to execute an unauthorized command with a craftable command block.")
return
end
if not cmddef then
minetest.chat_send_player(owner, "The command "..cmd.." does not exist")
return
end
local has_privs, missing_privs = minetest.check_player_privs(owner, cmddef.privs)
if not has_privs then
minetest.chat_send_player(owner, "You don't have permission "
.."to run "..cmd
.." (missing privileges: "
..table.concat(missing_privs, ", ")..")")
return
end
cmddef.func(owner, param)
end
end
local function commandblock_action_off(pos, node)
if node.name == "moremesecons_commandblock:commandblock_on" then
minetest.swap_node(pos, {name = "moremesecons_commandblock:commandblock_off"})
end
end
local function can_dig(pos, player)
local meta = minetest.get_meta(pos)
local owner = meta:get_string("owner")
return owner == "" or owner == player:get_player_name()
end
minetest.register_node("moremesecons_commandblock:commandblock_off", {
description = "Craftable Command Block",
tiles = {"moremesecons_commandblock_off.png"},
groups = {cracky=2, mesecon_effector_off=1},
on_construct = construct,
after_place_node = after_place,
on_receive_fields = receive_fields,
can_dig = can_dig,
sounds = default.node_sound_stone_defaults(),
mesecons = {effector = {
action_on = commandblock_action_on
}}
})
minetest.register_node("moremesecons_commandblock:commandblock_on", {
tiles = {"moremesecons_commandblock_on.png"},
groups = {cracky=2, mesecon_effector_on=1, not_in_creative_inventory=1},
light_source = 10,
drop = "moremesecons_commandblock:commandblock_off",
on_construct = construct,
after_place_node = after_place,
on_receive_fields = receive_fields,
can_dig = can_dig,
sounds = default.node_sound_stone_defaults(),
mesecons = {effector = {
action_off = commandblock_action_off
}}
})
minetest.register_craft({
output = "moremesecons_commandblock:commandblock_off",
recipe = {
{"group:mesecon_conductor_craftable","default:mese_crystal","group:mesecon_conductor_craftable"},
{"default:mese_crystal","group:mesecon_conductor_craftable","default:mese_crystal"},
{"group:mesecon_conductor_craftable","default:mese_crystal","group:mesecon_conductor_craftable"}
}
})