906cf51cbb
- In some cases, players are not being kicked, even though their status clearly indicates they should be. Make sure the "should we kick them" logic in the status check command matches the logic in the thing that actually does the kick. - Clean up the way we handle event hooks to reduce the code mess. - Don't rely on the bump/bumpn functions returning pname; always return nil with them and determine pname at the outer layers and pass it in as necessary. This is how we should have fixed the earlier bug that caused players digging things not to get the node.
96 lines
2.8 KiB
Lua
96 lines
2.8 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
|
|
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
|
|
|
|
local function wrapon(event, idx, func)
|
|
minetest["register_on_" .. event](function(...)
|
|
return func(({...})[idx], event)
|
|
end)
|
|
end
|
|
wrapon("joinplayer", 1, bump)
|
|
wrapon("placenode", 3, bump)
|
|
wrapon("dignode", 3, bump)
|
|
wrapon("punchnode", 3, bump)
|
|
wrapon("chat_message", 1, bumpn)
|
|
wrapon("player_receive_fields", 1, bump)
|
|
wrapon("craft", 2, bump)
|
|
wrapon("player_inventory_action", 1, bump)
|
|
|
|
local looks = {}
|
|
local ctlbits = {}
|
|
local function checkplayer(player, pname)
|
|
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
|
|
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 = player:get_player_name()
|
|
checkplayer(player, pname)
|
|
if now() - times[pname] >= timeout then
|
|
minetest.kick_player(pname, reason)
|
|
end
|
|
end
|
|
end)
|