337 lines
11 KiB
Lua
337 lines
11 KiB
Lua
--[[
|
|
Re-write functions (from builtin commands).
|
|
Copyright (C) 2019 Panquesito7
|
|
|
|
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,
|
|
})
|
|
|
|
-- Minetest Game privileges
|
|
if core.get_modpath("sethome") then
|
|
enhanced_builtin_commands.override_privilege("home", {
|
|
description = S("Can use /sethome and /home"),
|
|
give_to_singleplayer = false,
|
|
})
|
|
end
|