diff --git a/ess/player.lua b/ess/player.lua index e69de29..427be57 100644 --- a/ess/player.lua +++ b/ess/player.lua @@ -0,0 +1,206 @@ + +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 + +-- Debug + +local globalstepskip = minetest.settings:get_bool("ess_skip_globalstep", false) + +-- Commands + +local function cmd_god(name, params, splitparams) + local target = name + if splitparams[1] then + target = splitparams[1] + end + + if not player_cache[target] then + return false, "No such player." + end + + local status = not player_cache[target].god + player_cache[target].god = status + + local msg = "God mode enabled." + if not status then + msg = "God mode disabled." + end + + if target ~= name then + minetest.chat_send_player(target, msg) + end + + ess.set_player_meta(target, "god", status) + + return true, msg +end + +local commands = { + ["whois"] = { + description = "Get network information of player", + params = "[]", + 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 = "[]", + 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 + } +} + +-- AFK kick immunity privilege +minetest.register_privilege("ess.player.afk", { + description = "AFK kick immunity", + give_to_singleplayer = false, + give_to_admin = true, +}) + +if not globalstepskip then + commands["god"] = { + description = "Toggle invincibility mode.", + aliases = {"godmode", "invincible"}, + privs = true, + params = "[]", + func = cmd_god + } + + local check_timer = 0 + minetest.register_globalstep(function(dtime) + -- 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 + if player_cache[player_name] then + -- Check for afk players + if afk_check and not ess.priv_match(player_name, "ess.player.afk") then + check_timer = check_timer + dtime + if check_timer > afk_check_interval then + check_timer = 0 + + -- 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") + end + + -- Warn player if he/she has less than afk_warn_time seconds to move or be kicked + if 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 + end + + -- Check if this player is doing an action + for _,keyPressed in pairs(player:get_player_control()) do + if keyPressed then + player_cache[player_name].active = minetest.get_gametime() + end + end + end + + -- Check if player has godmode turned on + if player_cache[player_name].god == true then + player:set_hp(20) + player:set_breath(11) + end + end + end + end) +end + +ess.autoregister(commands, "player") + +-- 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, + } +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 diff --git a/ess/settingtypes.txt b/ess/settingtypes.txt index 7c546ba..3d83efb 100644 --- a/ess/settingtypes.txt +++ b/ess/settingtypes.txt @@ -1,6 +1,35 @@ +[Teleport] + +# /tpa request timeout in seconds +ess_tpa_timeout (tpask request timeout in seconds) int 120 + +# Seconds to wait before teleporting +ess_teleport_delay (Teleportation delays) int 0 + +[Players] # Save death position so that the player can return to it via /back ess_save_death (Save death position) bool false -# /tpa request timeout in seconds -ess_tpa_timeout (tpask request timeout in seconds) int 120 +# AFK kicking +ess_afk_check (Check for AFK players) bool true + +# AFK kick timer interval +ess_afk_check_interval (AFK kick timer interval) int 1 + +# Maximum AFK time before kicking +ess_afk_time (Max AFK time in seconds) int 300 + +# Warn AFKing players +ess_afk_warn_time (AFK warning time before kicking in seconds) int 20 + +# AFK warn message +ess_afk_warn_msg (AFK warning) string "Warning, you have %d seconds to move or be kicked" + +# Broadcast new players +ess_new_player (Broadcast new players) string "%s has joined the server for the first time! Welcome!" + +[Debug] + +# For debug purposes. If you're having unexplainable lag, try setting this to true. Breaks AFK timers and god mode. +ess_skip_globalstep (Skip GlobalStep) bool false diff --git a/ess/teleport.lua b/ess/teleport.lua index 9ff320b..e069c81 100644 --- a/ess/teleport.lua +++ b/ess/teleport.lua @@ -1,5 +1,4 @@ -local ess_save_death = minetest.settings:get_bool("ess_save_death", false) local ess_tpa_timeout = tonumber(minetest.settings:get("ess_tpa_timeout")) or 120 local tpask = { @@ -195,10 +194,3 @@ local commands = { } ess.autoregister(commands, "teleport") - --- Save death point for use with /back -if ess_save_death then - minetest.register_on_dieplayer(function(player) - ess.save_player_pos(player) - end) -end