Compare commits
5 Commits
305f1c54cb
...
6ee6cd0426
Author | SHA1 | Date |
---|---|---|
|
6ee6cd0426 | |
|
2154a39ad4 | |
|
6e454df37c | |
|
32f61e45b3 | |
|
bdd68b0e32 |
|
@ -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: ""
|
|
@ -0,0 +1,14 @@
|
|||
max_line_length = 80
|
||||
|
||||
globals = {
|
||||
'areas',
|
||||
'chat3',
|
||||
'cloaking',
|
||||
'minetest',
|
||||
'irc',
|
||||
}
|
||||
|
||||
read_globals = {
|
||||
string = {fields = {'split', 'trim'}},
|
||||
table = {fields = {'copy'}},
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
# 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
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
43
README.md
43
README.md
|
@ -1,6 +1,9 @@
|
|||
# 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?
|
||||
|
||||
|
@ -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
|
||||
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 game functions. The aim of cloaking is to trick other mods into thinking the
|
||||
player is not in-game, and for this it must be hacky.
|
||||
The aim of cloaking is to trick other mods into thinking the player is not
|
||||
in-game, and a lot of hacks are used to do this.
|
||||
|
||||
## Help, it crashes
|
||||
|
||||
|
@ -21,24 +23,28 @@ running around, or by a bug in cloaking itself.
|
|||
|
||||
## How do I use cloaking?
|
||||
|
||||
Cloaking adds a modding API and two chatcommands. Both of these require the
|
||||
`cloaking` privilege to execute, however you can uncloak yourself without any
|
||||
privileges.
|
||||
Cloaking adds a modding API and some chatcommands. All of the chatcommands
|
||||
require the "cloaking" privilege to execute, with the exception of `/uncloak`
|
||||
when used on yourself.
|
||||
|
||||
- `/cloak [victim]`: Cloaks yourself, alternatively an unsuspecting `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`.
|
||||
`cloaking` privilege.
|
||||
- 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?
|
||||
|
||||
You can either run
|
||||
`git clone https://git.minetest.land/luk3yx/cloaking.git`, or download
|
||||
a [zip](https://git.minetest.land/luk3yx/cloaking/archive/master.zip) or
|
||||
[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.
|
||||
`git clone https://git.minetest.land/luk3yx/cloaking.git` or download this mod
|
||||
from [ContentDB](https://content.minetest.net/packages/luk3yx/cloaking).
|
||||
|
||||
## 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
|
||||
names.
|
||||
- `cloaking.is_cloaked(player)`: Checks if a player is cloaked.
|
||||
- `cloaking.hide_player(player)`: Hides a player without cloaking them. If/when
|
||||
minetest.hide_player() gets introduced, this will become an alias for that.
|
||||
- `cloaking.hide_player(player)`: Hides a player without cloaking them.
|
||||
- `cloaking.unhide_player(player)`: Unhides a player previously hidden with
|
||||
`cloaking.hide_player()`.
|
||||
- `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
|
||||
don't want your chatcommand working with cloaked players, you can add
|
||||
`_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.
|
||||
|
||||
## 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),
|
||||
you can disable these backports by adding `cloaking.backport_bugfixes = false`
|
||||
to your minetest.conf.
|
||||
|
||||
[cloaking device]: https://memory-alpha.fandom.com/wiki/Cloaking_device
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
--
|
||||
-- Minetest cloaking mod: chat3 fixes
|
||||
--
|
||||
-- © 2019 by luk3yx
|
||||
-- Copyright © 2019 by luk3yx
|
||||
--
|
||||
|
||||
-- Override minetest.get_connected_players() so it lists cloaked players for
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
--
|
||||
-- Minetest cloaking mod: chatcommands
|
||||
--
|
||||
-- © 2019 by luk3yx
|
||||
-- Copyright © 2018-2021 by luk3yx
|
||||
--
|
||||
|
||||
minetest.register_privilege('cloaking',
|
||||
|
@ -12,21 +12,22 @@ minetest.register_chatcommand("cloak", {
|
|||
description = "Cloak a player so they are not visible.",
|
||||
privs = {cloaking = true},
|
||||
_allow_while_cloaked = true,
|
||||
func = function(player, victim)
|
||||
func = function(name, victim)
|
||||
if not victim or victim == '' then
|
||||
victim = player
|
||||
victim = name
|
||||
end
|
||||
|
||||
local p = cloaking.get_player_by_name(victim)
|
||||
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
|
||||
|
||||
if cloaking.is_cloaked(victim) then
|
||||
return false, victim .. " is already cloaked!"
|
||||
end
|
||||
|
||||
minetest.log('action', player .. ' cloaks ' .. victim .. '.')
|
||||
minetest.log('action', name .. ' cloaks ' .. victim .. '.')
|
||||
cloaking.cloak(p)
|
||||
return true, "Cloaked!"
|
||||
end
|
||||
|
@ -36,16 +37,16 @@ minetest.register_chatcommand("uncloak", {
|
|||
params = "[victim]",
|
||||
description = "Uncloak a player so they are visible.",
|
||||
_allow_while_cloaked = true,
|
||||
func = function(player, victim)
|
||||
func = function(name, victim)
|
||||
if not victim or victim == '' then
|
||||
victim = player
|
||||
elseif not minetest.get_player_privs(player).cloaking then
|
||||
victim = name
|
||||
elseif not minetest.get_player_privs(name).cloaking then
|
||||
return false, "You don't have permission to uncloak someone else."
|
||||
end
|
||||
|
||||
|
||||
if victim == '*' then
|
||||
minetest.log('action', player .. ' uncloaks everyone.')
|
||||
minetest.log('action', name .. ' uncloaks everyone.')
|
||||
for _, player in ipairs(cloaking.get_cloaked_players()) do
|
||||
cloaking.uncloak(player)
|
||||
end
|
||||
|
@ -54,14 +55,15 @@ minetest.register_chatcommand("uncloak", {
|
|||
|
||||
local p = cloaking.get_player_by_name(victim)
|
||||
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
|
||||
|
||||
if not cloaking.is_cloaked(victim) then
|
||||
return false, victim .. " is not cloaked!"
|
||||
end
|
||||
|
||||
minetest.log('action', player .. ' uncloaks ' .. victim .. '.')
|
||||
minetest.log('action', name .. ' uncloaks ' .. victim .. '.')
|
||||
cloaking.uncloak(p)
|
||||
return true, "Uncloaked!"
|
||||
end
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
--
|
||||
-- Minetest player cloaking mod: "Cloaked chat"
|
||||
--
|
||||
-- © 2019 by luk3yx
|
||||
-- Copyright © 2019 by luk3yx
|
||||
--
|
||||
|
||||
cloaking.chat = {prefix = '-Cloaked-'}
|
||||
|
|
115
core.lua
115
core.lua
|
@ -1,7 +1,7 @@
|
|||
--
|
||||
-- Minetest player cloaking mod: Core functions
|
||||
--
|
||||
-- © 2019 by luk3yx
|
||||
-- Copyright © 2018-2021 by luk3yx
|
||||
--
|
||||
|
||||
cloaking = {}
|
||||
|
@ -10,6 +10,7 @@ cloaking = {}
|
|||
-- can use them.
|
||||
cloaking.get_player_by_name = minetest.get_player_by_name
|
||||
cloaking.get_objects_inside_radius = minetest.get_objects_inside_radius
|
||||
cloaking.get_objects_in_area = minetest.get_objects_in_area
|
||||
cloaking.get_server_status = minetest.get_server_status
|
||||
|
||||
local cloaked_players = {}
|
||||
|
@ -24,16 +25,28 @@ function minetest.get_player_by_name(player)
|
|||
end
|
||||
end
|
||||
|
||||
function minetest.get_objects_inside_radius(pos, radius)
|
||||
local objs = {}
|
||||
for _, obj in ipairs(cloaking.get_objects_inside_radius(pos, radius)) do
|
||||
if not cloaked_players[obj:get_player_name()] then
|
||||
table.insert(objs, obj)
|
||||
local function remove_cloaked_players(list)
|
||||
for i = #list, 1, -1 do
|
||||
if cloaked_players[list[i]:get_player_name()] then
|
||||
table.remove(list, i)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function minetest.get_objects_inside_radius(pos, radius)
|
||||
local objs = cloaking.get_objects_inside_radius(pos, radius)
|
||||
remove_cloaked_players(objs)
|
||||
return objs
|
||||
end
|
||||
|
||||
if cloaking.get_objects_in_area then
|
||||
function minetest.get_objects_in_area(pos1, pos2)
|
||||
local objs = cloaking.get_objects_in_area(pos1, pos2)
|
||||
remove_cloaked_players(objs)
|
||||
return objs
|
||||
end
|
||||
end
|
||||
|
||||
local override_statusline = false
|
||||
if minetest.settings:get_bool('show_statusline_on_connect') ~= nil then
|
||||
override_statusline = true
|
||||
|
@ -46,16 +59,13 @@ function minetest.get_server_status(name, joined)
|
|||
|
||||
local status = cloaking.get_server_status(name, joined)
|
||||
if not status or status == "" then return status end
|
||||
local e = status:find('}', 1, true)
|
||||
if not e then return status end
|
||||
local motd = status:sub(e)
|
||||
status = status:sub(1, status:find('{', 1, true))
|
||||
local players = {}
|
||||
for _, player in ipairs(minetest.get_connected_players()) do
|
||||
table.insert(players, player:get_player_name())
|
||||
end
|
||||
players = table.concat(players, ', ')
|
||||
status = status .. players .. motd
|
||||
status = status:gsub('([,|] clients[:=][{ ])[^\n|}]*(}?)', function(p1, p2)
|
||||
local players = {}
|
||||
for _, player in ipairs(minetest.get_connected_players()) do
|
||||
table.insert(players, player:get_player_name())
|
||||
end
|
||||
return p1 .. table.concat(players, ', ') .. p2
|
||||
end, 1)
|
||||
return status
|
||||
end
|
||||
|
||||
|
@ -76,11 +86,13 @@ end
|
|||
|
||||
-- Don't allow chat or chatcommands in all commands that don't have the
|
||||
-- allow_while_cloaked parameter set.
|
||||
local override_chatcommands = function()
|
||||
for name, def in pairs(minetest.registered_chatcommands) do
|
||||
local delayed_uncloak
|
||||
local function override_chatcommands()
|
||||
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
|
||||
local real_cmd = def.func
|
||||
minetest.chatcommands[name].func = function(name, param)
|
||||
chatcommands[cmd_name].func = function(name, param)
|
||||
if cloaked_players[name] then
|
||||
local pass, r1, r2
|
||||
if def._disallow_while_cloaked then
|
||||
|
@ -106,7 +118,7 @@ local override_chatcommands = function()
|
|||
for _, func in ipairs(minetest.registered_on_leaveplayers) do
|
||||
c = c + 1
|
||||
local f = func
|
||||
if f ~= cloaking.delayed_uncloak then
|
||||
if f ~= delayed_uncloak then
|
||||
minetest.registered_on_leaveplayers[c] = function(p, t, cloaked)
|
||||
if cloaked ~= 'cloaking' and
|
||||
cloaked_players[p:get_player_name()] then
|
||||
|
@ -166,10 +178,9 @@ end
|
|||
|
||||
-- "Hide" players
|
||||
local hidden = {}
|
||||
function cloaking.hide_player(player, preserve_attrs)
|
||||
function cloaking.hide_player(player_or_name, preserve_attrs)
|
||||
-- Sanity check
|
||||
local victim
|
||||
local player, victim = player_and_name(player, true)
|
||||
local player, victim = player_and_name(player_or_name, true)
|
||||
if not player then return end
|
||||
|
||||
-- Save existing attributes
|
||||
|
@ -202,9 +213,9 @@ minetest.register_on_leaveplayer(function(player)
|
|||
end)
|
||||
|
||||
-- "Unhide" players
|
||||
function cloaking.unhide_player(player)
|
||||
function cloaking.unhide_player(player_or_name)
|
||||
-- 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
|
||||
|
||||
-- Get the data
|
||||
|
@ -236,11 +247,11 @@ function cloaking.unhide_player(player)
|
|||
end
|
||||
|
||||
-- The cloak and uncloak functions
|
||||
local use_areas = minetest.get_modpath('areas') and areas and areas.hud
|
||||
function cloaking.cloak(player)
|
||||
local use_areas = minetest.global_exists('areas') and areas.hud
|
||||
function cloaking.cloak(player_or_name)
|
||||
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
|
||||
|
||||
cloaking.hide_player(player, false)
|
||||
|
@ -251,7 +262,7 @@ function cloaking.cloak(player)
|
|||
end
|
||||
|
||||
for _, f in ipairs(minetest.registered_on_leaveplayers) do
|
||||
if f ~= cloaking.delayed_uncloak then
|
||||
if f ~= delayed_uncloak then
|
||||
f(player, false, 'cloaking')
|
||||
end
|
||||
end
|
||||
|
@ -275,8 +286,8 @@ function cloaking.cloak(player)
|
|||
minetest.log('verbose', victim .. ' was cloaked.')
|
||||
end
|
||||
|
||||
function cloaking.uncloak(player)
|
||||
local player, victim = player_and_name(player, false)
|
||||
function cloaking.uncloak(player_or_name)
|
||||
local player, victim = player_and_name(player_or_name, false)
|
||||
if not player then return end
|
||||
|
||||
cloaked_players[victim] = nil
|
||||
|
@ -296,21 +307,17 @@ function cloaking.uncloak(player)
|
|||
end
|
||||
|
||||
-- API functions
|
||||
function cloaking.auto_uncloak(player)
|
||||
if type(player) ~= "string" then
|
||||
player = player:get_player_name()
|
||||
end
|
||||
if cloaked_players[player] then
|
||||
cloaking.uncloak(player)
|
||||
end
|
||||
end
|
||||
cloaking.auto_uncloak = cloaking.uncloak
|
||||
|
||||
function cloaking.delayed_uncloak(player)
|
||||
-- This function removes the player from the cloaked players table on the next
|
||||
-- server step.
|
||||
-- Defined as a local above override_chatcommands().
|
||||
function delayed_uncloak(player)
|
||||
local victim = player:get_player_name()
|
||||
if cloaked_players[victim] then
|
||||
minetest.after(0.5, function()
|
||||
minetest.after(0, function()
|
||||
cloaked_players[victim] = nil
|
||||
if areas and areas.hud and areas.hud[victim] then
|
||||
if use_areas and areas.hud[victim] then
|
||||
areas.hud[victim] = nil
|
||||
end
|
||||
end)
|
||||
|
@ -319,9 +326,8 @@ end
|
|||
|
||||
-- Register cloaking.delayed_uncloak "manually" so that the profiler can't
|
||||
-- hijack it, preventing it from running.
|
||||
minetest.registered_on_leaveplayers[#minetest.registered_on_leaveplayers + 1]
|
||||
= cloaking.delayed_uncloak
|
||||
minetest.callback_origins[cloaking.delayed_uncloak] = {
|
||||
table.insert(minetest.registered_on_leaveplayers, delayed_uncloak)
|
||||
minetest.callback_origins[delayed_uncloak] = {
|
||||
mod = 'cloaking',
|
||||
name = 'delayed_uncloak'
|
||||
}
|
||||
|
@ -331,24 +337,25 @@ minetest.callback_origins[cloaking.delayed_uncloak] = {
|
|||
local get_connected_players = minetest.get_connected_players
|
||||
function minetest.get_connected_players()
|
||||
local res = get_connected_players()
|
||||
for i = #res, 1, -1 do
|
||||
if cloaked_players[res[i]:get_player_name()] then
|
||||
table.remove(res, i)
|
||||
end
|
||||
end
|
||||
remove_cloaked_players(res)
|
||||
return res
|
||||
end
|
||||
|
||||
-- There's currently no way to check if cloaked players will appear in the
|
||||
-- unmodified minetest.get_connected_players().
|
||||
function cloaking.get_connected_players()
|
||||
local a = minetest.get_connected_players()
|
||||
for player, cloaked in pairs(cloaked_players) do
|
||||
local players = minetest.get_connected_players()
|
||||
for name, cloaked in pairs(cloaked_players) do
|
||||
if cloaked then
|
||||
table.insert(a, cloaking.get_player_by_name(player))
|
||||
local player = cloaking.get_player_by_name(name)
|
||||
-- The player may be nil if they have just left but haven't been
|
||||
-- removed from the cloaked_players table yet.
|
||||
if player then
|
||||
players[#players + 1] = player
|
||||
end
|
||||
end
|
||||
end
|
||||
return a
|
||||
return players
|
||||
end
|
||||
|
||||
function cloaking.get_cloaked_players()
|
||||
|
|
21
init.lua
21
init.lua
|
@ -15,25 +15,22 @@ if minetest.get_modpath('irc') then
|
|||
dofile(path .. '/irc.lua')
|
||||
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
|
||||
local cloaked_chat = minetest.settings:get_bool('cloaking.enable_cloaked_chat')
|
||||
if cloaked_chat or cloaked_chat == nil then
|
||||
dofile(path .. '/cloaked-chat.lua')
|
||||
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
|
||||
-- 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
|
||||
end
|
||||
|
||||
|
|
2
irc.lua
2
irc.lua
|
@ -1,7 +1,7 @@
|
|||
--
|
||||
-- Minetest cloaking mod: IRC fixes
|
||||
--
|
||||
-- © 2019 by luk3yx
|
||||
-- Copyright © 2019 by luk3yx
|
||||
--
|
||||
|
||||
local irc_sendLocal = irc.sendLocal
|
||||
|
|
1
mod.conf
1
mod.conf
|
@ -1,3 +1,4 @@
|
|||
name = cloaking
|
||||
title = Cloaking
|
||||
description = Allows admins to become invisible to both mods and other players.
|
||||
optional_depends = areas,chat3,irc
|
||||
|
|
|
@ -2,5 +2,8 @@
|
|||
# chat channel.
|
||||
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.
|
||||
cloaking.backport_bugfixes (Backport MT bugfixes) bool true
|
||||
|
|
|
@ -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)
|
Loading…
Reference in New Issue