Add luacheck and /shadow.

This commit is contained in:
luk3yx 2021-02-06 13:35:28 +13:00
parent 305f1c54cb
commit bdd68b0e32
12 changed files with 136 additions and 71 deletions

11
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,11 @@
on: [push, pull_request]
name: build
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: lint
uses: Roang-zero1/factorio-mod-luacheck@master
with:
luacheckrc_url: ""

14
.luacheckrc Normal file
View File

@ -0,0 +1,14 @@
max_line_length = 80
globals = {
'areas',
'chat3',
'cloaking',
'minetest',
'irc',
}
read_globals = {
string = {fields = {'split', 'trim'}},
table = {fields = {'copy'}},
}

View File

@ -1,6 +1,6 @@
# The MIT License (MIT) # The MIT License (MIT)
Copyright © 2019 by luk3yx Copyright © 2018-2021 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,9 @@
# Minetest cloaking mod # Minetest cloaking mod
Allows players to cloak and uncloak, inspired by Star Trek's [cloaking device]. Allows admins to become invisible and appear as if they are not in-game at all.
Inspired by Star Trek's [cloaking device].
[cloaking device]: https://memory-alpha.fandom.com/wiki/Cloaking_device
## What is cloaking? ## What is cloaking?
@ -8,11 +11,10 @@ In this instance, cloaking is a way to go invisible and become undetectable by
most mods (unless they explicitly want to detect cloaked players, so they can most mods (unless they explicitly want to detect cloaked players, so they can
still send chat messages to them). still send chat messages to them).
## Why is cloaking so hacky, and where does it send the 'left the game' messages? ## Why is cloaking so hacky?
Cloaking sends no left the game messages, it leaves that up to the built-in left The aim of cloaking is to trick other mods into thinking the player is not
the game functions. The aim of cloaking is to trick other mods into thinking the in-game, and a lot of hacks are used to do this.
player is not in-game, and for this it must be hacky.
## Help, it crashes ## Help, it crashes
@ -21,24 +23,28 @@ running around, or by a bug in cloaking itself.
## How do I use cloaking? ## How do I use cloaking?
Cloaking adds a modding API and two chatcommands. Both of these require the Cloaking adds a modding API and some chatcommands. All of the chatcommands
`cloaking` privilege to execute, however you can uncloak yourself without any require the "cloaking" privilege to execute, with the exception of `/uncloak`
privileges. when used on yourself.
- `/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 - `/cloak_chat <message>`: Sends `<message>` to all online players with the
`cloaking` privilege. You can disable cloaked chat by setting `cloaking` privilege.
`cloaking.enable_cloaked_chat` to `false` in `minetest.conf`. - You can disable cloaked chat by adding
`cloaking.enable_cloaked_chat = false` to minetest.conf.
- `/shadow [victim]`: Attaches you to a player. If `victim` is not specified,
this command will detach you instead.
- Requires both the "cloaking" and "teleport" privileges.
- This command can only be used while cloaked.
- You can disable this by adding `cloaking.enable_shadow = false` to
minetest.conf.
## How do I download cloaking? ## How do I download cloaking?
You can either run You can either run
`git clone https://git.minetest.land/luk3yx/cloaking.git`, or download `git clone https://git.minetest.land/luk3yx/cloaking.git` or download this mod
a [zip](https://git.minetest.land/luk3yx/cloaking/archive/master.zip) or from [ContentDB](https://content.minetest.net/packages/luk3yx/cloaking).
[tar.gz](https://git.minetest.land/luk3yx/cloaking/archive/master.tar.gz)
file. You will need to rename the downloaded folder to `cloaking` (if it
doesn't already have that name) for it to work properly.
## How do I use the API? ## How do I use the API?
@ -50,8 +56,7 @@ Cloaking adds the following functions:
- `cloaking.get_connected_names()`: Gets a list of cloaked and uncloaked player - `cloaking.get_connected_names()`: Gets a list of cloaked and uncloaked player
names. names.
- `cloaking.is_cloaked(player)`: Checks if a player is cloaked. - `cloaking.is_cloaked(player)`: Checks if a player is cloaked.
- `cloaking.hide_player(player)`: Hides a player without cloaking them. If/when - `cloaking.hide_player(player)`: Hides a player without cloaking them.
minetest.hide_player() gets introduced, this will become an alias for that.
- `cloaking.unhide_player(player)`: Unhides a player previously hidden with - `cloaking.unhide_player(player)`: Unhides a player previously hidden with
`cloaking.hide_player()`. `cloaking.hide_player()`.
- `cloaking.chat`: Cloaked chat API, this is `nil` if cloaked chat is disabled. - `cloaking.chat`: Cloaked chat API, this is `nil` if cloaked chat is disabled.
@ -70,7 +75,7 @@ If you have made chatcommand work with players that aren't in-game, you can add
`_allow_while_cloaked = true` to the chatcommand definition. If you explicitly `_allow_while_cloaked = true` to the chatcommand definition. If you explicitly
don't want your chatcommand working with cloaked players, you can add 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 as a dependency, as
when cloaking is not loaded this parameter is simply ignored. when cloaking is not loaded this parameter is simply ignored.
## Backported bugfixes ## Backported bugfixes
@ -87,5 +92,3 @@ if it determines they are necessary for your server:
If you do not want this for whatever reason (although I do not recommend it), If you do not want this for whatever reason (although I do not recommend it),
you can disable these backports by adding `cloaking.backport_bugfixes = false` you can disable these backports by adding `cloaking.backport_bugfixes = false`
to your minetest.conf. to your minetest.conf.
[cloaking device]: https://memory-alpha.fandom.com/wiki/Cloaking_device

View File

@ -1,7 +1,7 @@
-- --
-- Minetest cloaking mod: chat3 fixes -- Minetest cloaking mod: chat3 fixes
-- --
-- © 2019 by luk3yx -- Copyright © 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

View File

@ -1,7 +1,7 @@
-- --
-- Minetest cloaking mod: chatcommands -- Minetest cloaking mod: chatcommands
-- --
-- © 2019 by luk3yx -- Copyright © 2018-2021 by luk3yx
-- --
minetest.register_privilege('cloaking', minetest.register_privilege('cloaking',
@ -12,21 +12,22 @@ minetest.register_chatcommand("cloak", {
description = "Cloak a player so they are not visible.", description = "Cloak a player so they are not visible.",
privs = {cloaking = true}, privs = {cloaking = true},
_allow_while_cloaked = true, _allow_while_cloaked = true,
func = function(player, victim) func = function(name, victim)
if not victim or victim == '' then if not victim or victim == '' then
victim = player victim = name
end end
local 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
if cloaking.is_cloaked(victim) then if cloaking.is_cloaked(victim) then
return false, victim .. " is already cloaked!" return false, victim .. " is already cloaked!"
end end
minetest.log('action', player .. ' cloaks ' .. victim .. '.') minetest.log('action', name .. ' cloaks ' .. victim .. '.')
cloaking.cloak(p) cloaking.cloak(p)
return true, "Cloaked!" return true, "Cloaked!"
end end
@ -36,16 +37,16 @@ minetest.register_chatcommand("uncloak", {
params = "[victim]", params = "[victim]",
description = "Uncloak a player so they are visible.", description = "Uncloak a player so they are visible.",
_allow_while_cloaked = true, _allow_while_cloaked = true,
func = function(player, victim) func = function(name, victim)
if not victim or victim == '' then if not victim or victim == '' then
victim = player victim = name
elseif not minetest.get_player_privs(player).cloaking then elseif not minetest.get_player_privs(name).cloaking then
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.') minetest.log('action', name .. ' 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
@ -54,14 +55,15 @@ minetest.register_chatcommand("uncloak", {
local 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
if not cloaking.is_cloaked(victim) then if not cloaking.is_cloaked(victim) then
return false, victim .. " is not cloaked!" return false, victim .. " is not cloaked!"
end end
minetest.log('action', player .. ' uncloaks ' .. victim .. '.') minetest.log('action', name .. ' uncloaks ' .. victim .. '.')
cloaking.uncloak(p) cloaking.uncloak(p)
return true, "Uncloaked!" return true, "Uncloaked!"
end end

View File

@ -1,7 +1,7 @@
-- --
-- Minetest player cloaking mod: "Cloaked chat" -- Minetest player cloaking mod: "Cloaked chat"
-- --
-- © 2019 by luk3yx -- Copyright © 2019 by luk3yx
-- --
cloaking.chat = {prefix = '-Cloaked-'} cloaking.chat = {prefix = '-Cloaked-'}

View File

@ -1,7 +1,7 @@
-- --
-- Minetest player cloaking mod: Core functions -- Minetest player cloaking mod: Core functions
-- --
-- © 2019 by luk3yx -- Copyright © 2018-2021 by luk3yx
-- --
cloaking = {} cloaking = {}
@ -76,11 +76,12 @@ end
-- Don't allow chat or chatcommands in all commands that don't have the -- Don't allow chat or chatcommands in all commands that don't have the
-- allow_while_cloaked parameter set. -- allow_while_cloaked parameter set.
local override_chatcommands = function() local function override_chatcommands()
for name, def in pairs(minetest.registered_chatcommands) do local chatcommands = minetest.registered_chatcommands
for cmd_name, def in pairs(chatcommands) do
if not def.allow_while_cloaked and not def._allow_while_cloaked then if not def.allow_while_cloaked and not def._allow_while_cloaked then
local real_cmd = def.func local real_cmd = def.func
minetest.chatcommands[name].func = function(name, param) chatcommands[cmd_name].func = function(name, param)
if cloaked_players[name] then if cloaked_players[name] then
local pass, r1, r2 local pass, r1, r2
if def._disallow_while_cloaked then if def._disallow_while_cloaked then
@ -166,10 +167,9 @@ end
-- "Hide" players -- "Hide" players
local hidden = {} local hidden = {}
function cloaking.hide_player(player, preserve_attrs) function cloaking.hide_player(player_or_name, preserve_attrs)
-- Sanity check -- Sanity check
local victim local player, victim = player_and_name(player_or_name, true)
local player, victim = player_and_name(player, true)
if not player then return end if not player then return end
-- Save existing attributes -- Save existing attributes
@ -202,9 +202,9 @@ minetest.register_on_leaveplayer(function(player)
end) end)
-- "Unhide" players -- "Unhide" players
function cloaking.unhide_player(player) function cloaking.unhide_player(player_or_name)
-- Sanity check -- Sanity check
local player, victim = player_and_name(player, true) local player, victim = player_and_name(player_or_name, true)
if not player or hidden[victim] == nil then return end if not player or hidden[victim] == nil then return end
-- Get the data -- Get the data
@ -236,11 +236,11 @@ function cloaking.unhide_player(player)
end end
-- The cloak and uncloak functions -- The cloak and uncloak functions
local use_areas = minetest.get_modpath('areas') and areas and areas.hud local use_areas = minetest.global_exists('areas') and areas.hud
function cloaking.cloak(player) function cloaking.cloak(player_or_name)
if not chatcommands_modified then override_chatcommands() end if not chatcommands_modified then override_chatcommands() end
local player, victim = player_and_name(player, true) local player, victim = player_and_name(player_or_name, true)
if not player then return end if not player then return end
cloaking.hide_player(player, false) cloaking.hide_player(player, false)
@ -275,8 +275,8 @@ function cloaking.cloak(player)
minetest.log('verbose', victim .. ' was cloaked.') minetest.log('verbose', victim .. ' was cloaked.')
end end
function cloaking.uncloak(player) function cloaking.uncloak(player_or_name)
local player, victim = player_and_name(player, false) local player, victim = player_and_name(player_or_name, false)
if not player then return end if not player then return end
cloaked_players[victim] = nil cloaked_players[victim] = nil
@ -296,15 +296,9 @@ function cloaking.uncloak(player)
end end
-- API functions -- API functions
function cloaking.auto_uncloak(player) cloaking.auto_uncloak = cloaking.uncloak
if type(player) ~= "string" then
player = player:get_player_name()
end
if cloaked_players[player] then
cloaking.uncloak(player)
end
end
-- Don't use delayed_uncloak outside of this mod.
function cloaking.delayed_uncloak(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
@ -319,8 +313,7 @@ end
-- Register cloaking.delayed_uncloak "manually" so that the profiler can't -- Register cloaking.delayed_uncloak "manually" so that the profiler can't
-- hijack it, preventing it from running. -- hijack it, preventing it from running.
minetest.registered_on_leaveplayers[#minetest.registered_on_leaveplayers + 1] table.insert(minetest.registered_on_leaveplayers, cloaking.delayed_uncloak)
= cloaking.delayed_uncloak
minetest.callback_origins[cloaking.delayed_uncloak] = { minetest.callback_origins[cloaking.delayed_uncloak] = {
mod = 'cloaking', mod = 'cloaking',
name = 'delayed_uncloak' name = 'delayed_uncloak'

View File

@ -15,25 +15,22 @@ 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'
local backport_bugfixes = 'cloaking.backport_bugfixes'
if minetest.settings and minetest.settings.get_bool then
cloaked_chat = minetest.settings:get_bool(cloaked_chat)
backport_bugfixes = minetest.settings:get_bool(backport_bugfixes)
else
cloaked_chat = minetest.setting_getbool(cloaked_chat)
backport_bugfixes = minetest.setting_getbool(backport_bugfixes)
end
-- Load cloaked chat if enabled -- Load cloaked chat if enabled
local cloaked_chat = minetest.settings:get_bool('cloaking.enable_cloaked_chat')
if cloaked_chat or cloaked_chat == nil then if cloaked_chat or cloaked_chat == nil then
dofile(path .. '/cloaked-chat.lua') dofile(path .. '/cloaked-chat.lua')
end end
-- Load /shadow if enabled
local shadow = minetest.settings:get_bool('cloaking.enable_shadow')
if shadow or shadow == nil then
dofile(path .. '/shadow.lua')
end
-- The following code is for backporting bugfixes, if the setting was disabled -- The following code is for backporting bugfixes, if the setting was disabled
-- simply return now. -- simply return now.
if backport_bugfixes ~= nil and not backport_bugfixes then local backport_fixes = minetest.settings:get_bool('cloaking.backport_bugfixes')
if backport_fixes ~= nil and not backport_fixes then
return return
end end

View File

@ -1,7 +1,7 @@
-- --
-- Minetest cloaking mod: IRC fixes -- Minetest cloaking mod: IRC fixes
-- --
-- © 2019 by luk3yx -- Copyright © 2019 by luk3yx
-- --
local irc_sendLocal = irc.sendLocal local irc_sendLocal = irc.sendLocal

View File

@ -2,5 +2,8 @@
# chat channel. # chat channel.
cloaking.enable_cloaked_chat (Cloaked chat) bool true cloaking.enable_cloaked_chat (Cloaked chat) bool true
# Enables /shadow.
cloaking.enable_shadow (Shadow command) bool true
# Backports certain bugfixes to older versions of Minetest. # Backports certain bugfixes to older versions of Minetest.
cloaking.backport_bugfixes (Backport MT bugfixes) bool true cloaking.backport_bugfixes (Backport MT bugfixes) bool true

42
shadow.lua Normal file
View File

@ -0,0 +1,42 @@
--
-- Minetest player cloaking mod
--
-- Copyright © 2021 by luk3yx
--
minetest.register_chatcommand('shadow', {
privs = {cloaking = true, teleport = true},
description = 'Attaches you to a player. If `victim` is not specified, ' ..
'this command will detach you instead.',
params = '[victim]',
func = function(name, param)
if not cloaking.is_cloaked(name) then
return false, 'You must be cloaked to use /shadow!'
elseif name == param then
return false, 'You cannot shadow yourself!'
end
local player = cloaking.get_player_by_name(name)
if param == '' then
player:set_detach()
return true, 'You are free to move normally.'
end
local victim = cloaking.get_player_by_name(param)
if not victim then
return false, ('Invalid player %q.'):format(param)
end
player:set_attach(victim, '', {x=0, y=0, z=0}, {x=0, y=0, z=0})
return true, ('You are now shadowing %q.'):format(param)
end
})
-- Detach on uncloak
minetest.register_on_joinplayer(function(player)
if not minetest.check_player_privs(player, "cloaking", "teleport") then
return
end
local parent = player:get_attach()
if minetest.is_player(parent) and parent:is_player() then
player:set_detach()
end
end)