This repository has been archived by the owner on Dec 24, 2023. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
functions.lua
366 lines (327 loc) · 12.1 KB
/
functions.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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
--[[
Re-write some functions (from builtin).
Copyright (C) 2019 David Leal (halfpacho@gmail.com)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
--]]
local S = enhanced_builtin_commands.intllib
function enhanced_builtin_commands.grant_command(caller, grantname, grantprivstr)
local caller_privs = core.get_player_privs(caller)
if not (caller_privs.privs or caller_privs.basic_privs) then
return false, S("Your privileges are insufficient.")
end
if not core.get_auth_handler().get_auth(grantname) then
return false, S("Player @1 does not exist.", grantname)
end
local grantprivs = core.string_to_privs(grantprivstr)
if grantprivstr == "all" then
grantprivs = core.registered_privileges
end
local privs = core.get_player_privs(grantname)
local privs_unknown = ""
local basic_privs =
core.string_to_privs(core.settings:get("basic_privs") or "interact,shout")
for priv, _ in pairs(grantprivs) do
if not basic_privs[priv] and not caller_privs.privs then
return false, S("Your privileges are insufficient.")
end
if not core.registered_privileges[priv] then
privs_unknown = privs_unknown .. S("Unknown privilege: @1\n", priv)
end
privs[priv] = true
end
if privs_unknown ~= "" then
return false, privs_unknown
end
for priv, _ in pairs(grantprivs) do
core.run_priv_callbacks(grantname, priv, caller, "grant")
end
core.set_player_privs(grantname, privs)
core.log("action", caller..' granted ('..core.privs_to_string(grantprivs, ', ')..') privileges to '..grantname)
if grantname ~= caller then
core.chat_send_player(grantname, S("@1 granted you privileges: @2", caller, core.privs_to_string(grantprivs, ' ')))
end
return true, S("Privileges of @1: @2", grantname, core.privs_to_string(core.get_player_privs(grantname), ' '))
end
function enhanced_builtin_commands.emergeblocks_callback(pos, action, num_calls_remaining, ctx)
if ctx.total_blocks == 0 then
ctx.total_blocks = num_calls_remaining + 1
ctx.current_blocks = 0
end
ctx.current_blocks = ctx.current_blocks + 1
if ctx.current_blocks == ctx.total_blocks then
core.chat_send_player(ctx.requestor_name,
string.format(S("Finished emerging %d blocks in %.2fms.",
ctx.total_blocks, (os.clock() - ctx.start_time) * 1000)))
end
end
function enhanced_builtin_commands.emergeblocks_progress_update(ctx)
if ctx.current_blocks ~= ctx.total_blocks then
core.chat_send_player(ctx.requestor_name,
string.format(S("emergeblocks update: %d/%d blocks emerged (%.1f%%)",
ctx.current_blocks, ctx.total_blocks,
(ctx.current_blocks / ctx.total_blocks) * 100)))
core.after(2, emergeblocks_progress_update, ctx)
end
end
function enhanced_builtin_commands.handle_give_command(cmd, giver, receiver, stackstring)
core.log("action", giver .. " invoked " .. cmd
.. ', stackstring="' .. stackstring .. '"')
local itemstack = ItemStack(stackstring)
if itemstack:is_empty() then
return false, S("Cannot give an empty item")
elseif (not itemstack:is_known()) or (itemstack:get_name() == "unknown") then
return false, S("Cannot give an unknown item")
-- Forbid giving 'ignore' due to unwanted side effects
elseif itemstack:get_name() == "ignore" then
return false, S("Giving 'ignore' is not allowed")
end
local receiverref = core.get_player_by_name(receiver)
if receiverref == nil then
return false, S("@1 is not a known player", receiver)
end
local leftover = receiverref:get_inventory():add_item("main", itemstack)
local partiality
if leftover:is_empty() then
partiality = ""
elseif leftover:get_count() == itemstack:get_count() then
partiality = S("could not be ")
else
partiality = S("partially ")
end
-- The actual item stack string may be different from what the "giver"
-- entered (e.g. big numbers are always interpreted as 2^16-1).
stackstring = itemstack:to_string()
if giver == receiver then
local msg = S("%q %sadded to inventory.")
return true, msg:format(stackstring, partiality)
else
core.chat_send_player(receiver, S("%q %sadded to inventory.", format(stackstring, partiality)))
local msg = S("%q %sadded to %s's inventory.")
return true, msg:format(stackstring, partiality, receiver)
end
end
function enhanced_builtin_commands.handle_kill_command(killer, victim)
if core.settings:get_bool("enable_damage") == false then
return false, S("Players can't be killed, damage has been disabled.")
end
local victimref = core.get_player_by_name(victim)
if victimref == nil then
return false, S("Player @1 is not online.", victim)
elseif victimref:get_hp() <= 0 then
if killer == victim then
return false, S("You are already dead.")
else
return false, S("@1 is already dead.", victim)
end
end
if not killer == victim then
core.log("action", string.format("%s killed %s", killer, victim))
end
-- Kill victim
victimref:set_hp(0)
return true, S("@1 has been killed.", victim)
end
function enhanced_builtin_commands.parse_range_str(player_name, str)
local p1, p2
local args = str:split(" ")
if args[1] == "here" then
p1, p2 = core.get_player_radius_area(player_name, tonumber(args[2]))
if p1 == nil then
return false, S("Unable to get player @1 position", player_name)
end
else
p1, p2 = core.string_to_area(str)
if p1 == nil then
return false, S("Incorrect area format. Expected: (x1,y1,z1) (x2,y2,z2)")
end
end
return p1, p2
end
local cmd_marker = "/"
function enhanced_builtin_commands.do_help_cmd(name, param)
function enhanced_builtin_commands.format_help_line(cmd, def)
local msg = core.colorize("#00ffff", cmd_marker .. cmd)
if def.params and def.params ~= "" then
msg = msg .. " " .. def.params
end
if def.description and def.description ~= "" then
msg = msg .. ": " .. def.description
end
return msg
end
if param == "" then
local cmds = {}
for cmd, def in pairs(core.registered_chatcommands) do
if INIT == "client" or core.check_player_privs(name, def.privs) then
cmds[#cmds + 1] = cmd
end
end
table.sort(cmds)
return true, S("Available commands: @1", table.concat(cmds, " ")) .. "\n" .. S("Use '@1help <cmd>' to get more information, or '@1help all' to list everything.", cmd_marker)
elseif param == "all" then
local cmds = {}
for cmd, def in pairs(core.registered_chatcommands) do
if INIT == "client" or core.check_player_privs(name, def.privs) then
cmds[#cmds + 1] = enhanced_builtin_commands.format_help_line(cmd, def)
end
end
table.sort(cmds)
return true, S("Available commands: @1", "\n"..table.concat(cmds, "\n"))
elseif INIT == "game" and param == "privs" then
local privs = {}
for priv, def in pairs(core.registered_privileges) do
privs[#privs + 1] = priv .. ": " .. def.description
end
table.sort(privs)
return true, S("Available privileges:\n@1", table.concat(privs, "\n"))
else
local cmd = param
local def = core.registered_chatcommands[cmd]
if not def then
return false, S("Command not available: @1", cmd)
else
return true, enhanced_builtin_commands.format_help_line(cmd, def)
end
end
end
-- Create a function to override a privilege
function enhanced_builtin_commands.override_privilege(name, redefinition)
local privilege = core.registered_privileges[name]
if not privilege then
error("Attempt to override non-existent privilege " .. name)
end
for k, v in pairs(redefinition) do
rawset(privilege, k, v)
end
core.registered_privileges[name] = privilege
end
-- Override builtin privileges
-- Primary privileges
enhanced_builtin_commands.override_privilege("interact", {
description = S("Can interact with things and modify the world"),
give_to_singleplayer = true,
give_to_admin = true,
})
enhanced_builtin_commands.override_privilege("shout", {
description = S("Can speak in chat"),
give_to_singleplayer = true,
give_to_admin = true,
})
enhanced_builtin_commands.override_privilege("basic_privs", {
description = S("Can modify 'shout' and 'interact' privileges"),
give_to_singleplayer = true,
give_to_admin = true,
})
enhanced_builtin_commands.override_privilege("privs", {
description = S("Can modify privileges"),
give_to_singleplayer = true,
give_to_admin = true,
})
-- Other privileges
enhanced_builtin_commands.override_privilege("teleport", {
description = S("Can teleport self"),
give_to_singleplayer = false,
})
enhanced_builtin_commands.override_privilege("bring", {
description = S("Can teleport other players"),
give_to_singleplayer = false,
})
enhanced_builtin_commands.override_privilege("settime", {
description = S("Can set the time of day using /time"),
give_to_singleplayer = false,
})
enhanced_builtin_commands.override_privilege("server", {
description = S("Can do server maintenance stuff"),
give_to_singleplayer = false,
give_to_admin = true,
})
enhanced_builtin_commands.override_privilege("protection_bypass", {
description = S("Can bypass node protection in the world"),
give_to_singleplayer = false,
})
enhanced_builtin_commands.override_privilege("ban", {
description = S("Can ban and unban players"),
give_to_singleplayer = false,
give_to_admin = true,
})
enhanced_builtin_commands.override_privilege("kick", {
description = S("Can kick players"),
give_to_singleplayer = false,
give_to_admin = true,
})
enhanced_builtin_commands.override_privilege("give", {
description = S("Can use /give and /giveme"),
give_to_singleplayer = false,
})
enhanced_builtin_commands.override_privilege("password", {
description = S("Can use /setpassword and /clearpassword"),
give_to_singleplayer = false,
give_to_admin = true,
})
enhanced_builtin_commands.override_privilege("fly", {
description = S("Can use fly mode"),
give_to_singleplayer = false,
})
enhanced_builtin_commands.override_privilege("fast", {
description = S("Can use fast mode"),
give_to_singleplayer = false,
})
enhanced_builtin_commands.override_privilege("noclip", {
description = S("Can fly through solid nodes using noclip mode"),
give_to_singleplayer = false,
})
enhanced_builtin_commands.override_privilege("rollback", {
description = S("Can use the rollback functionality"),
give_to_singleplayer = false,
})
enhanced_builtin_commands.override_privilege("debug", {
description = S("Allows enabling various debug options that may affect gameplay"),
give_to_singleplayer = false,
give_to_admin = true,
})
-- When player joins/leaves, send a translated message
function core.send_join_message(player_name)
if not core.is_singleplayer() then
core.chat_send_all(S("*** @1 joined the game.", player_name))
end
end
function core.send_leave_message(player_name, timed_out)
local announcement = S("*** @1 left the game.", player_name)
if timed_out then
announcement = S("@1 (timed out)", announcement)
end
core.chat_send_all(announcement)
end
-- Override "core.register_privilege"
function core.register_privilege(name, param)
local function fill_defaults(def)
if def.give_to_singleplayer == nil then
def.give_to_singleplayer = true
end
if def.give_to_admin == nil then
def.give_to_admin = def.give_to_singleplayer
end
if def.description == nil then
def.description = S("(no description)") -- This makes the difference! :)
end
end
local def = {}
if type(param) == "table" then
def = param
else
def = {description = param}
end
fill_defaults(def)
core.registered_privileges[name] = def
end