icyessentials/ess/player.lua

223 lines
6.0 KiB
Lua

local player_cache = {}
-- AFK
local afk_check = minetest.settings:get_bool("ess_afk_check", true)
local afk_max_time = tonumber(minetest.settings:get("ess_afk_time")) or 300
local afk_warn_time = tonumber(minetest.settings:get("ess_afk_warn_time")) or 20
local afk_check_interval = tonumber(minetest.settings:get("ess_afk_check_interval")) or 1
local afk_warn_msg = minetest.settings:get("ess_afk_warn_msg")
if not afk_warn_msg then
afk_warn_msg = "Warning, you have %d seconds to move or be kicked"
end
-- Disable AFK check in singleplayer, doesn't really make sense to have it
if minetest.is_singleplayer() then
ess_afk_check = false
end
-- Player
local save_death = minetest.settings:get_bool("ess_save_death", false)
local newplayer = minetest.settings:get("ess_new_player")
if not newplayer then
newplayer = "%s has joined the server for the first time! Welcome!"
end
-- Commands
local function cmd_god(name, params, splitparams)
local target = name
if splitparams[1] then
target = splitparams[1]
end
local player = minetest.get_player_by_name(target)
if not player then
return false, "No such player."
end
local grps = player:get_armor_groups()
local status = not player_cache[target].god
if grps["immortal"] == 1 then
status = false
end
player_cache[target].god = status
local msg = "God mode enabled."
local grp = 1
if not status then
grp = 0
msg = "God mode disabled."
end
grps["immortal"] = grp
player:set_armor_groups(grps)
if target ~= name then
minetest.chat_send_player(target, msg)
end
ess.set_player_meta(target, "god", status)
return true, msg
end
local commands = {
["god"] = {
description = "Toggle invincibility mode.",
aliases = {"godmode", "invincible"},
privs = true,
params = "[<playername>]",
func = cmd_god
},
["whois"] = {
description = "Get network information of player",
params = "[<playername>]",
privs = true,
func = function(name, param)
if param == "" then
param = name
end
if not player_cache[param] then
return false, string.format("Player %s was not found!", param)
end
local player_info = minetest.get_player_information(param)
minetest.chat_send_player(name, string.format("[%s] IP address: %s", param, player_info["address"]))
minetest.chat_send_player(name, string.format("[%s] average round trip time: %d ms", param, player_info["avg_rtt"] * 1000))
minetest.chat_send_player(name, string.format("[%s] connected for: %d seconds", param, player_info["connection_uptime"]))
return true
end
},
["heal"] = {
description = "Heal player",
params = "[<playername>]",
privs = {
["ess.player.heal"] = true,
["ess.player.heal.other"] = true,
},
func = function(name, param)
if param == "" then
param = name
elseif param ~= "" and param ~= name and not ess.priv_match(name, "ess.player.heal.other") then
return ess.reject_permission()
end
local p = minetest.get_player_by_name(param)
if not p then
return false, string.format("Player %s was not found!", param)
end
p:set_hp(20)
return true, string.format("Successfully healed %s.", param)
end
}
}
ess.autoregister(commands, "player")
-- AFK kick immunity privilege
minetest.register_privilege("ess.player.afk", {
description = "AFK kick immunity",
give_to_singleplayer = false,
give_to_admin = true,
})
if afk_check then
local check_timer = 0
minetest.register_globalstep(function(dtime)
check_timer = check_timer + dtime
if check_timer > afk_check_interval then
check_timer = 0
-- Loop through all connected players
for _,player in ipairs(minetest.get_connected_players()) do
local player_name = player:get_player_name()
-- Only continue if the player has an entry in the player cache
-- Check for afk players
if player_cache[player_name] and not ess.priv_match(player_name, "ess.player.afk") then
local kicked = false
-- Kick player if he/she has been inactive for longer than afk_max_time seconds
if player_cache[player_name].active + afk_max_time < minetest.get_gametime() then
minetest.kick_player(player_name, "Kicked for inactivity")
kicked = true
end
-- Warn player if he/she has less than afk_warn_time seconds to move or be kicked
if not kicked and afk_warn_time > 0 and player_cache[player_name].active +
afk_max_time - afk_warn_time < minetest.get_gametime() then
local seconds = tostring(player_cache[player_name].active + afk_max_time - minetest.get_gametime())
minetest.chat_send_player(player_name, string.format(afk_warn_msg, seconds))
end
-- Check if this player is doing an action
if not kicked then
for _,keyPressed in pairs(player:get_player_control()) do
if keyPressed then
player_cache[player_name].active = minetest.get_gametime()
end
end
end
end
end
end
end)
end
-- New player message
if newplayer ~= "" then
minetest.register_on_newplayer(function (player)
local player_name = player:get_player_name()
minetest.chat_send_all(string.format(newplayer, player_name))
end)
end
-- Join
minetest.register_on_joinplayer(function (player)
local player_name = player:get_player_name()
player_cache[player_name] = {
active = minetest.get_gametime(),
god = ess.get_player_meta(player_name, "god") == true,
}
-- Ensure god mode persistance
local grps = player:get_armor_groups()
if grps["immortal"] ~= 1 and player_cache[player_name].god then
if not ess.priv_match(player_name, "ess.player.god") then
player_cache[player_name].god = false
ess.set_player_meta(player_name, "god", false)
return
end
grps["immortal"] = 1
player:set_armor_groups(grps)
end
end)
-- Leave
minetest.register_on_leaveplayer(function(player)
local player_name = player:get_player_name()
player_cache[player_name] = nil
end)
-- Save death point for use with /back
if save_death then
minetest.register_on_dieplayer(function(player)
local player_name = player:get_player_name()
if player_cache[player_name] and player_cache[player_name].god then
return
end
ess.save_player_pos(player)
end)
end