Auke Kok 80cbd6d34a Add license headers to all lua files.
Some of these are copies from the respective origins from mtg,
to make sure we have headers everywhere listing the proper code.

I've relicensed spectator_mode from WT*PL to LGPL-2.1. No other
licenses were changed.
2018-06-21 22:56:48 -07:00

137 lines
3.5 KiB
Lua

--[[
spectator mode - originally by kilbith.
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., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
]]--
local original_pos = {}
local watching = {}
minetest.register_privilege("watch", "Player can watch other players")
local function toggle_hud_flags(player, bool)
local flags = player:hud_get_flags()
local new_hud_flags = {}
for flag in pairs(flags) do
new_hud_flags[flag] = bool
end
player:hud_set_flags(new_hud_flags)
end
local function unwatching(name)
local watcher = minetest.get_player_by_name(name)
local privs = minetest.get_player_privs(name)
if watcher and watching[name] then
watcher:set_detach()
watching[name] = nil
watcher:set_eye_offset(vector.new(), vector.new())
watcher:set_nametag_attributes({color = {a = 255, r = 255, g = 255, b = 255}})
toggle_hud_flags(watcher, true)
watcher:set_properties({
visual_size = {x = 1, y = 1},
makes_footstep_sound = true,
collisionbox = {-0.3, -1, -0.3, 0.3, 1, 0.3}
})
if not privs.interact and privs.watch == true then
privs.interact = true
minetest.set_player_privs(name, privs)
end
local pos = original_pos[watcher]
if pos then
-- setpos seems to be very unreliable
-- this workaround helps though
minetest.after(0.1, function()
watcher:setpos(pos)
end)
original_pos[watcher] = nil
end
end
end
minetest.register_chatcommand("watch", {
params = "<to_name>",
description = "watch a given player",
privs = {watch = true},
func = function(name, param)
local watcher = minetest.get_player_by_name(name)
local target = minetest.get_player_by_name(param)
local privs = minetest.get_player_privs(name)
if target and watcher ~= target then
if watching[name] then
unwatching(param)
else
original_pos[watcher] = watcher:getpos()
end
watching[name] = target
watcher:set_attach(target, "", vector.new(0, -5, -20), vector.new())
watcher:set_eye_offset(vector.new(0, -5, -20), vector.new())
watcher:set_nametag_attributes({color = {a = 0}})
toggle_hud_flags(watcher, true)
watcher:set_properties({
visual_size = {x = 0, y = 0},
makes_footstep_sound = false,
collisionbox = {0}
})
privs.interact = nil
minetest.set_player_privs(name, privs)
return true, "Watching '" .. param .. "' at "..
minetest.pos_to_string(vector.round(target:getpos()))
end
return false, "Invalid parameter ('" .. param .. "')."
end
})
minetest.register_chatcommand("unwatch", {
description = "unwatch a player",
privs = {watch=true},
func = function(name, param)
unwatching(name)
end
})
minetest.register_on_leaveplayer(function(player)
local name = player:get_player_name()
-- if watched target disconnects, stop spectator mode for the watcher
for k, v in pairs(watching) do
if name == v then
unwatching(k)
end
end
if watching[name] then
unwatching(name)
end
end)