Aaron Suen 9e9cd6ca48 Ignore constantly-held controls too
Things like auto-forward or a taped down mining key also count
as "idle" for this system's purposes as well, to avoid players
trivially exploiting to avoid being kicked, or to prevent
false positives caused by stuck controls.
2022-10-04 18:38:17 -04:00

64 lines
2.3 KiB
Lua

-- LUALOCALS < ---------------------------------------------------------
local minetest, pairs, tonumber
= minetest, pairs, tonumber
-- LUALOCALS > ---------------------------------------------------------
local modname = minetest.get_current_modname()
local invert = minetest.settings:get_bool(modname .. "_invert")
local timeout = tonumber(minetest.settings:get(modname .. "_timeout")) or 600
local reason = minetest.settings:get(modname .. "_reason") or "idle timeout"
minetest.register_privilege(modname, {
description = (invert and "Kick" or "Do not kick") .. " this player when idle",
give_to_singleplayer = false,
give_to_admin = false
})
local times = {}
local function now() return minetest.get_us_time() / 1000000 end
local function bumpn(pname) times[pname] = now() return pname end
local function bump(player)
if not (player and player.get_player_name) then return end
local pname = player:get_player_name()
if not pname then return end
return bumpn(pname)
end
minetest.register_on_joinplayer(function(player) return bump(player) end)
minetest.register_on_placenode(function(_, _, player)
--do not return
bump(player)
end)
minetest.register_on_dignode(function(_, _, player) return bump(player) end)
minetest.register_on_punchnode(function(_, _, player) return bump(player) end)
minetest.register_on_chat_message(function(pname) bumpn(pname) end)
minetest.register_on_player_receive_fields(function(player) return bump(player) end)
minetest.register_on_craft(function(_, player) bump(player) end)
minetest.register_on_player_inventory_action(function(player) return bump(player) end)
local looks = {}
local ctlbits = {}
local function checkplayer(player)
local pname = player:get_player_name()
local bits = player:get_player_control_bits()
local oldbits = ctlbits[pname]
ctlbits[pname] = bits
local look = player:get_look_dir()
local oldlook = looks[pname]
looks[pname] = oldlook
if not (oldbits == bits and oldlook and vector.distance(look, oldlook) < 0.001)
then return bumpn(pname) end
return pname
end
minetest.register_globalstep(function()
for _, player in pairs(minetest.get_connected_players()) do
if (not minetest.check_player_privs(player, modname)) ~= (not invert) then return end
local pname = checkplayer(player)
if times[pname] < now() - timeout then
minetest.kick_player(pname, reason)
end
end
end)