Update cloaking (#42)

This commit is contained in:
luk3yx 2019-03-03 08:34:36 +13:00 committed by Billy S
parent 8ef0976578
commit 8dbb0ab5d1
11 changed files with 190 additions and 24 deletions

View File

@ -1,6 +1,6 @@
# The MIT License (MIT) # The MIT License (MIT)
*Copyright © 2018 by luk3yx* Copyright © 2019 by luk3yx
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@ -1,6 +1,6 @@
# Minetest cloaking mod # Minetest cloaking mod
Allows players to cloak and uncloak. Allows players to cloak and uncloak, inspired by Star Trek's [cloaking device].
## What is cloaking? ## What is cloaking?
@ -27,6 +27,9 @@ privileges.
- `/cloak [victim]`: Cloaks yourself, alternatively an unsuspecting `victim`. - `/cloak [victim]`: Cloaks yourself, alternatively an unsuspecting `victim`.
- `/uncloak [victim]`: Uncloaks yourself, or a `victim`. - `/uncloak [victim]`: Uncloaks yourself, or a `victim`.
- `/cloak_chat <message>`: Sends `<message>` to all online players with the
`cloaking` privilege. You can disable cloaked chat by setting
`cloaking.enable_cloaked_chat` to `false` in `minetest.conf`.
## How do I download cloaking? ## How do I download cloaking?
@ -44,10 +47,16 @@ Cloaking adds the following functions:
- `cloaking.cloak_player(player)`: Cloaks a player. - `cloaking.cloak_player(player)`: Cloaks a player.
- `cloaking.uncloak_player(player)`: Uncloaks a player. - `cloaking.uncloak_player(player)`: Uncloaks a player.
- `cloaking.get_cloaked_players()`: Gets a list of cloaked player names. - `cloaking.get_cloaked_players()`: Gets a list of cloaked player names.
- `cloaking.get_connected_names()`: Gets a list of cloaked and uncloaked player
names.
- `cloaking.is_cloaked(player)`: Checks if a player is cloaked. - `cloaking.is_cloaked(player)`: Checks if a player is cloaked.
- `cloaking.on_chat_message(player, message)`: Returns `true` and warns `player` - `cloaking.on_chat_message(player, message)`: Returns `true` and warns `player`
if they are cloaked and trying to send a chat message, otherwise returns if they are cloaked and trying to send a chat message, otherwise returns
`nil`. `nil`.
- `cloaking.chat`: Cloaked chat API, this is `nil` if cloaked chat is disabled.
- `cloaking.chat.send(message)`: Sends a message to cloaked chat.
- `cloaking.chat.prefix`: The text (`-Cloaked-`) that is prepended to cloaked
chat messages before they are sent to players.
It also adds the following functions that ignore cloaked players and can It also adds the following functions that ignore cloaked players and can
interact with them: interact with them:
@ -60,3 +69,5 @@ don't want your chatcommand working with cloaked players, you can add
`_disallow_while_cloaked = true` to the definition. `_disallow_while_cloaked = true` to the definition.
These modifications do not require that you add `cloaking` to `depends.txt`, as These modifications do not require that you add `cloaking` to `depends.txt`, as
when cloaking is not loaded this parameter is simply ignored. when cloaking is not loaded this parameter is simply ignored.
[cloaking device]: https://memory-alpha.fandom.com/wiki/Cloaking_device

View File

@ -1,14 +1,14 @@
-- --
-- Minetest cloaking mod: chat3 fixes -- Minetest cloaking mod: chat3 fixes
-- --
-- © 2018 by luk3yx -- © 2019 by luk3yx
-- --
-- Override minetest.get_connected_players() so it lists cloaked players for -- Override minetest.get_connected_players() so it lists cloaked players for
-- chat3. -- chat3.
local get_uncloaked_players = minetest.get_connected_players local get_uncloaked_players = minetest.get_connected_players
minetest.get_connected_players = function() function minetest.get_connected_players()
local d = debug.getinfo(2) local d = debug.getinfo(2)
if d.func == chat3.send or d.func == minetest.chatcommands['me'].func then if d.func == chat3.send or d.func == minetest.chatcommands['me'].func then
return cloaking.get_connected_players() return cloaking.get_connected_players()
@ -20,7 +20,7 @@ end
-- Override get_player_by_name() to allow chat3 to access cloaked players. -- Override get_player_by_name() to allow chat3 to access cloaked players.
local get_uncloaked_player_by_name = minetest.get_player_by_name local get_uncloaked_player_by_name = minetest.get_player_by_name
minetest.get_player_by_name = function(player) function minetest.get_player_by_name(player)
local d = debug.getinfo(2) local d = debug.getinfo(2)
if d.func == chat3.send or d.func == minetest.chatcommands["me"].func then if d.func == chat3.send or d.func == minetest.chatcommands["me"].func then
return cloaking.get_player_by_name(player) return cloaking.get_player_by_name(player)

View File

@ -1,7 +1,7 @@
-- --
-- Minetest cloaking mod: chatcommands -- Minetest cloaking mod: chatcommands
-- --
-- © 2018 by luk3yx -- © 2019 by luk3yx
-- --
minetest.register_privilege('cloaking', minetest.register_privilege('cloaking',
@ -26,6 +26,7 @@ minetest.register_chatcommand("cloak", {
return false, victim .. " is already cloaked!" return false, victim .. " is already cloaked!"
end end
minetest.log('action', player .. ' cloaks ' .. victim .. '.')
cloaking.cloak(p) cloaking.cloak(p)
return true, "Cloaked!" return true, "Cloaked!"
end end
@ -42,14 +43,16 @@ minetest.register_chatcommand("uncloak", {
return false, "You don't have permission to uncloak someone else." return false, "You don't have permission to uncloak someone else."
end end
if victim == '*' then if victim == '*' then
minetest.log('action', player .. ' uncloaks everyone.')
for _, player in ipairs(cloaking.get_cloaked_players()) do for _, player in ipairs(cloaking.get_cloaked_players()) do
cloaking.uncloak(player) cloaking.uncloak(player)
end end
return true, "Uncloaked everyone!" return true, "Uncloaked everyone!"
end end
p = cloaking.get_player_by_name(victim) local p = cloaking.get_player_by_name(victim)
if not p then if not p then
return false, "Could not find a player with the name '" .. victim .. "'!" return false, "Could not find a player with the name '" .. victim .. "'!"
end end
@ -58,7 +61,27 @@ minetest.register_chatcommand("uncloak", {
return false, victim .. " is not cloaked!" return false, victim .. " is not cloaked!"
end end
minetest.log('action', player .. ' uncloaks ' .. victim .. '.')
cloaking.uncloak(p) cloaking.uncloak(p)
return true, "Uncloaked!" return true, "Uncloaked!"
end end
}) })
-- Allow /teleport to be used on cloaked players if you have the "cloaking"
-- privilege.
local tp = minetest.registered_chatcommands['teleport'].func
minetest.override_chatcommand('teleport', {
func = function(name, param)
if minetest.check_player_privs(name, 'cloaking') then
local g = minetest.get_player_by_name
minetest.get_player_by_name = cloaking.get_player_by_name
local err, msg = tp(name, param)
minetest.get_player_by_name = g
return err, msg
else
return tp(name, param)
end
end
})

View File

@ -0,0 +1,53 @@
--
-- Minetest player cloaking mod: "Cloaked chat"
--
-- © 2019 by luk3yx
--
cloaking.chat = {prefix = '-Cloaked-'}
-- Send a message to all players with the "cloaking" privilege.
function cloaking.chat.send(msg)
-- Add the "cloaked chat" prefix and remove newlines.
msg = msg:gsub('[\r\n]', ' ')
-- Log the chat message
minetest.log('action', 'CLOAKED CHAT: ' .. msg)
-- Send the message to everyone with the "cloaking" priv.
msg = cloaking.chat.prefix .. ' ' .. msg
for _, name in ipairs(cloaking.get_connected_names()) do
if minetest.check_player_privs(name, 'cloaking') then
minetest.chat_send_player(name, msg)
end
end
end
-- Create a '/cloak_chat' command
minetest.register_chatcommand('cloak_chat', {
params = '<message>',
description = 'Send a chat message to cloaked players.',
privs = {cloaking = true},
_allow_while_cloaked = true,
func = function(name, param)
cloaking.chat.send('<' .. name .. '> ' .. param)
end
})
minetest.registered_chatcommands['cloak-chat'] =
minetest.registered_chatcommands['cloak_chat']
-- Override cloaking.on_chat_message
function cloaking.on_chat_message(name, message)
if message:sub(1, 1) ~= "/" and cloaking.is_cloaked(name) then
if minetest.check_player_privs(name, 'cloaking') then
cloaking.chat.send('<' .. name .. '> ' .. message)
else
minetest.chat_send_player(name, "You cannot use chat while" ..
" cloaked. Please use /uncloak if you want to use chat.")
end
return true
end
end
minetest.registered_on_chat_messages[1] = cloaking.on_chat_message

View File

@ -1,7 +1,7 @@
-- --
-- Minetest player cloaking mod: Core functions -- Minetest player cloaking mod: Core functions
-- --
-- © 2018 by luk3yx -- © 2019 by luk3yx
-- --
cloaking = {} cloaking = {}
@ -16,7 +16,7 @@ local cloaked_players = {}
local chatcommands_modified = false local chatcommands_modified = false
-- Override built-in functions -- Override built-in functions
minetest.get_player_by_name = function(player) function minetest.get_player_by_name(player)
if cloaked_players[player] then if cloaked_players[player] then
return nil return nil
else else
@ -24,7 +24,7 @@ minetest.get_player_by_name = function(player)
end end
end end
minetest.get_objects_inside_radius = function(pos, radius) function minetest.get_objects_inside_radius(pos, radius)
local objs = {} local objs = {}
for _, obj in ipairs(cloaking.get_objects_inside_radius(pos, radius)) do for _, obj in ipairs(cloaking.get_objects_inside_radius(pos, radius)) do
if not cloaked_players[obj:get_player_name()] then if not cloaked_players[obj:get_player_name()] then
@ -34,7 +34,7 @@ minetest.get_objects_inside_radius = function(pos, radius)
return objs return objs
end end
minetest.get_server_status = function() function minetest.get_server_status()
local status = cloaking.get_server_status() local status = cloaking.get_server_status()
local motd = status:sub(status:find('}', 1, true) + 0) local motd = status:sub(status:find('}', 1, true) + 0)
status = status:sub(1, status:find('{', 1, true)) status = status:sub(1, status:find('{', 1, true))
@ -98,7 +98,8 @@ local override_chatcommands = function()
end end
end end
cloaking.on_chat_message = function(name, message) -- Handle chat messages
function cloaking.on_chat_message(name, message)
if message:sub(1, 1) ~= "/" and cloaked_players[name] then if message:sub(1, 1) ~= "/" and cloaked_players[name] then
minetest.chat_send_player(name, "You cannot use chat while cloaked." .. minetest.chat_send_player(name, "You cannot use chat while cloaked." ..
" Please use /uncloak if you want to use chat.") " Please use /uncloak if you want to use chat.")
@ -106,7 +107,11 @@ cloaking.on_chat_message = function(name, message)
end end
end end
minetest.register_on_chat_message(cloaking.on_chat_message) table.insert(minetest.registered_on_chat_messages, 1, cloaking.on_chat_message)
minetest.callback_origins[cloaking.on_chat_message] = {
mod = 'cloaking',
name = 'on_chat_message'
}
-- Disallow some built-in commands. -- Disallow some built-in commands.
for _, cmd in ipairs({'me', 'msg'}) do for _, cmd in ipairs({'me', 'msg'}) do
@ -118,7 +123,8 @@ for _, cmd in ipairs({'me', 'msg'}) do
end end
-- The cloak and uncloak functions -- The cloak and uncloak functions
cloaking.cloak = function(player) local use_areas = minetest.get_modpath('areas') and areas and areas.hud
function cloaking.cloak(player)
if not chatcommands_modified then override_chatcommands() end if not chatcommands_modified then override_chatcommands() end
if type(player) == "string" then if type(player) == "string" then
player = cloaking.get_player_by_name(player) player = cloaking.get_player_by_name(player)
@ -133,7 +139,7 @@ cloaking.cloak = function(player)
player:set_nametag_attributes({text = " "}) player:set_nametag_attributes({text = " "})
local t = nil local t = nil
if areas and areas.hud and areas.hud[victim] then if use_areas and areas.hud[victim] then
t = areas.hud[victim] t = areas.hud[victim]
end end
@ -145,14 +151,24 @@ cloaking.cloak = function(player)
cloaked_players[victim] = true cloaked_players[victim] = true
-- TODO: Get the highest ID somehow
local t_id = t and t.areasId
for id = 0, 20 do
if id ~= t_id and player:hud_get(id) then
player:hud_remove(id)
end
end
if t then if t then
areas.hud[victim] = t areas.hud[victim] = t
player:hud_change(areas.hud[victim].areasId, "text", "Cloaked") player:hud_change(areas.hud[victim].areasId, "text", "Cloaked")
areas.hud[victim].oldAreas = "" areas.hud[victim].oldAreas = ""
end end
minetest.log('verbose', victim .. ' was cloaked.')
end end
cloaking.uncloak = function(player) function cloaking.uncloak(player)
if type(player) == "string" then if type(player) == "string" then
player = cloaking.get_player_by_name(player) player = cloaking.get_player_by_name(player)
end end
@ -176,10 +192,12 @@ cloaking.uncloak = function(player)
for _, f in ipairs(minetest.registered_on_joinplayers) do for _, f in ipairs(minetest.registered_on_joinplayers) do
f(player) f(player)
end end
minetest.log('verbose', victim .. ' was uncloaked.')
end end
-- API functions -- API functions
cloaking.auto_uncloak = function(player) function cloaking.auto_uncloak(player)
if type(player) ~= "string" then if type(player) ~= "string" then
player = player:get_player_name() player = player:get_player_name()
end end
@ -188,7 +206,7 @@ cloaking.auto_uncloak = function(player)
end end
end end
cloaking.delayed_uncloak = function(player) function cloaking.delayed_uncloak(player)
local victim = player:get_player_name() local victim = player:get_player_name()
if cloaked_players[victim] then if cloaked_players[victim] then
minetest.after(0.5, function() minetest.after(0.5, function()
@ -211,7 +229,7 @@ minetest.callback_origins[cloaking.delayed_uncloak] = {
-- The cloaking mod is so good it fools the built-in get_connected_players, so -- The cloaking mod is so good it fools the built-in get_connected_players, so
-- overlay that with one that adds cloaked players in. -- overlay that with one that adds cloaked players in.
cloaking.get_connected_players = function() function cloaking.get_connected_players()
local a = minetest.get_connected_players() local a = minetest.get_connected_players()
for player, cloaked in pairs(cloaked_players) do for player, cloaked in pairs(cloaked_players) do
if cloaked then if cloaked then
@ -221,7 +239,7 @@ cloaking.get_connected_players = function()
return a return a
end end
cloaking.get_cloaked_players = function() function cloaking.get_cloaked_players()
local players = {} local players = {}
for player, cloaked in pairs(cloaked_players) do for player, cloaked in pairs(cloaked_players) do
if cloaked then if cloaked then
@ -231,7 +249,27 @@ cloaking.get_cloaked_players = function()
return players return players
end end
cloaking.is_cloaked = function(player) -- Allow mods to get a list of cloaked and uncloaked player names.
function cloaking.get_connected_names()
local a = cloaking.get_cloaked_players()
for _, player in ipairs(minetest.get_connected_players()) do
table.insert(a, player:get_player_name())
end
return a
end
function cloaking.is_cloaked(player)
if type(player) ~= "string" then player = player:get_player_name() end if type(player) ~= "string" then player = player:get_player_name() end
return cloaked_players[player] and true or false return cloaked_players[player] and true or false
end end
-- Prevent cloaked players dying
minetest.register_on_player_hpchange(function(player, hp_change)
if player and hp_change < 0 then
local name = player:get_player_name()
if cloaked_players[name] then
hp_change = 0
end
end
return hp_change
end, true)

View File

@ -1,2 +1,3 @@
areas?
chat3? chat3?
irc? irc?

View File

@ -1,7 +1,7 @@
-- --
-- Minetest player cloaking mod -- Minetest player cloaking mod
-- --
-- © 2018 by luk3yx -- © 2019 by luk3yx
-- --
local path = minetest.get_modpath('cloaking') local path = minetest.get_modpath('cloaking')
dofile(path .. '/core.lua') dofile(path .. '/core.lua')
@ -14,3 +14,37 @@ end
if minetest.get_modpath('irc') then if minetest.get_modpath('irc') then
dofile(path .. '/irc.lua') dofile(path .. '/irc.lua')
end end
-- Attempt to support older versions of Minetest
local cloaked_chat = 'cloaking.enable_cloaked_chat'
if minetest.settings and minetest.settings.get_bool then
cloaked_chat = minetest.settings:get_bool(cloaked_chat)
else
cloaked_chat = minetest.setting_getbool(cloaked_chat)
end
-- Load cloaked chat if enabled
if cloaked_chat or cloaked_chat == nil then
dofile(path .. '/cloaked-chat.lua')
end
-- Enforce security of logs
table.insert(minetest.registered_on_chat_messages, 1, function(name, msg)
if msg:find('[\r\n]') then
minetest.chat_send_player(name,
'You cannot use newlines in chat messages.')
return true
end
end)
local log = minetest.log
function minetest.log(level, text)
level = level:gsub('[\r\n]', ' ')
if text then
text = text:gsub('[\r\n]', ' ')
else
text = level
level = 'none'
end
return log(level, text)
end

View File

@ -1,12 +1,12 @@
-- --
-- Minetest cloaking mod: IRC fixes -- Minetest cloaking mod: IRC fixes
-- --
-- © 2018 by luk3yx -- © 2019 by luk3yx
-- --
local irc_sendLocal = irc.sendLocal local irc_sendLocal = irc.sendLocal
irc.sendLocal = function(msg) function irc.sendLocal(msg)
for _, player in ipairs(cloaking.get_cloaked_players()) do for _, player in ipairs(cloaking.get_cloaked_players()) do
minetest.chat_send_player(player, msg) minetest.chat_send_player(player, msg)
end end

3
mods/cloaking/mod.conf Normal file
View File

@ -0,0 +1,3 @@
name = cloaking
description = Allows admins to become invisible to both mods and other players.
optional_depends = areas,chat3,irc

View File

@ -0,0 +1,3 @@
# Cloaked chat - Allow cloaked players with the "cloaking" priv to use a special
# chat channel.
cloaking.enable_cloaked_chat (Cloaked chat) bool true