98 lines
3.1 KiB
Lua
98 lines
3.1 KiB
Lua
-- LUALOCALS < ---------------------------------------------------------
|
|
local minetest, pairs, string, tonumber
|
|
= minetest, pairs, string, tonumber
|
|
local string_format
|
|
= string.format
|
|
-- 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 function now() return minetest.get_us_time() / 1000000 end
|
|
|
|
local times = {}
|
|
local actions = {}
|
|
|
|
minetest.register_chatcommand(modname, {
|
|
description = "Check player idle time and last action",
|
|
privs = {server = true},
|
|
func = function(_, param)
|
|
local time = times[param]
|
|
if not time then
|
|
return true, string_format("Player %q not found", param)
|
|
end
|
|
local active = (not minetest.check_player_privs(param, modname))
|
|
== (not invert)
|
|
return true, string_format(
|
|
"Player %q idle %0.2f/%s last action %q",
|
|
param,
|
|
now() - time,
|
|
active and string_format("%.2f", timeout) or "never",
|
|
actions[param] or "unknown")
|
|
end
|
|
})
|
|
|
|
local function bumpn(pname, action)
|
|
times[pname] = now()
|
|
actions[pname] = action
|
|
return pname
|
|
end
|
|
local function bump(player, action)
|
|
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, action)
|
|
end
|
|
|
|
minetest.register_on_joinplayer(function(player) return bump(player, "join") end)
|
|
minetest.register_on_placenode(function(_, _, player)
|
|
--do not return
|
|
bump(player, "placenode")
|
|
end)
|
|
minetest.register_on_dignode(function(_, _, player) return bump(player, "dignode") end)
|
|
minetest.register_on_punchnode(function(_, _, player) return bump(player, "punchnode") end)
|
|
minetest.register_on_chat_message(function(pname) bumpn(pname, "chat") end)
|
|
minetest.register_on_player_receive_fields(function(player) return bump(player, "formspec") end)
|
|
minetest.register_on_craft(function(_, player) bump(player, "craft") end)
|
|
minetest.register_on_player_inventory_action(function(player)
|
|
return bump(player, "inventory")
|
|
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] = look
|
|
|
|
if bits ~= oldbits then
|
|
return bumpn(pname, "control")
|
|
elseif not (oldlook and vector.distance(look, oldlook) < 0.001) then
|
|
return bumpn(pname, "lookdir")
|
|
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)
|