8f9322050f
Prevent player from accidentally sending a chat message as a user that should not exist.
137 lines
4.1 KiB
Lua
137 lines
4.1 KiB
Lua
-- LUALOCALS < ---------------------------------------------------------
|
|
local minetest, pairs, string, table, type
|
|
= minetest, pairs, string, table, type
|
|
local string_gmatch, string_match, string_sub, table_concat
|
|
= string.gmatch, string.match, string.sub, table.concat
|
|
-- LUALOCALS > ---------------------------------------------------------
|
|
|
|
local modname = minetest.get_current_modname()
|
|
|
|
local keepinteract = minetest.settings:get_bool(modname .. "_keep_interact")
|
|
local keepshout = minetest.settings:get_bool(modname .. "_keep_shout")
|
|
|
|
local function hasprivs(player, ...)
|
|
if type(player) == "string" then
|
|
player = minetest.get_player_by_name(player)
|
|
end
|
|
if not (player and player.is_player and player:is_player()) then return end
|
|
return minetest.check_player_privs(player, ...)
|
|
end
|
|
local function isstealth(player) return hasprivs(player, "stealth") end
|
|
|
|
local saved = {}
|
|
local function nonzero(t)
|
|
for _, v in pairs(t) do if v ~= 0 then return true end end
|
|
end
|
|
local function updatevisible(player)
|
|
local props = player:get_properties()
|
|
if not props then return end
|
|
local pname = player:get_player_name()
|
|
local atts = player:get_nametag_attributes()
|
|
|
|
local isvis = nonzero(props.visual_size)
|
|
or props.pointable
|
|
or atts.color.a > 0
|
|
or props.makes_footstep_sound
|
|
|
|
if isvis and not saved[pname] then
|
|
saved[pname] = {p = props, a = atts}
|
|
end
|
|
local needvis = not isstealth(player)
|
|
if isvis == needvis then return end
|
|
|
|
player:set_properties({
|
|
visual_size = needvis and saved[pname].p.visual_size or {x = 0, y = 0},
|
|
pointable = needvis and saved[pname].p.pointable or false,
|
|
makes_footstep_sound = needvis and saved[pname].p.makes_footstep_sound or false
|
|
})
|
|
player:set_nametag_attributes({
|
|
color = needvis and saved[pname].a.color or {r = 0, g = 0, b = 0, a = 0}
|
|
})
|
|
minetest.after(0, function() return updatevisible(player) end)
|
|
end
|
|
|
|
local function grantrevoke(pname)
|
|
return minetest.after(0, function()
|
|
local player = minetest.get_player_by_name(pname)
|
|
if player then return updatevisible(player) end
|
|
end)
|
|
end
|
|
|
|
minetest.register_privilege("stealth", {
|
|
description = "Invisibility",
|
|
give_to_singleplayer = false,
|
|
give_to_admin = false,
|
|
on_grant = grantrevoke,
|
|
on_revoke = grantrevoke
|
|
})
|
|
|
|
local function auto_remove_priv(player, priv)
|
|
if hasprivs(player, {stealth = true, [priv] = true, privs = true}) then
|
|
local cc = minetest.registered_chatcommands.revoke
|
|
if cc and cc.func then
|
|
local pname = player:get_player_name()
|
|
minetest.after(0, function()
|
|
cc.func(pname, pname .. " " .. priv)
|
|
end)
|
|
end
|
|
end
|
|
end
|
|
|
|
minetest.register_on_joinplayer(function(player)
|
|
if not keepinteract then auto_remove_priv(player, "interact") end
|
|
if not keepshout then auto_remove_priv(player, "shout") end
|
|
return updatevisible(player)
|
|
end)
|
|
|
|
local timer = 0
|
|
minetest.register_globalstep(function(dtime)
|
|
timer = timer - dtime
|
|
if timer <= 0 then
|
|
for _, player in pairs(minetest.get_connected_players()) do
|
|
if isstealth(player) then updatevisible(player) end
|
|
end
|
|
timer = 1
|
|
end
|
|
end)
|
|
|
|
minetest.after(0, function()
|
|
local oldjoin = minetest.send_join_message
|
|
function minetest.send_join_message(pname, ...)
|
|
if not minetest.check_player_privs(pname, "stealth") then
|
|
return oldjoin(pname, ...)
|
|
end
|
|
end
|
|
local oldleave = minetest.send_leave_message
|
|
function minetest.send_leave_message(pname, ...)
|
|
if not minetest.check_player_privs(pname, "stealth") then
|
|
return oldleave(pname, ...)
|
|
end
|
|
end
|
|
end)
|
|
|
|
local function stripfirstline(msg)
|
|
local pref, clients, suff = string_match(msg, "^(.*clients[^%w_]+)([^}]*)(.*)$")
|
|
if not clients then return msg end
|
|
local clist = {}
|
|
for pname in string_gmatch(clients, "%S+") do
|
|
if string_sub(pname, -1) == "," then
|
|
pname = string_sub(pname, 1, #pname - 1)
|
|
end
|
|
if not isstealth(pname) then
|
|
clist[#clist + 1] = pname
|
|
end
|
|
end
|
|
msg = pref .. table_concat(clist, ", ") .. suff
|
|
return msg
|
|
end
|
|
local function stripstatus(rawmsg, ...)
|
|
local lines = rawmsg:split("\n")
|
|
lines[1] = stripfirstline(lines[1])
|
|
return table_concat(lines, "\n"), ...
|
|
end
|
|
local oldstatus = minetest.get_server_status
|
|
function minetest.get_server_status(...)
|
|
return stripstatus(oldstatus(...))
|
|
end
|