Page 1 of 1

Disconnect player if inactive (and free a slot)

PostPosted: Mon Oct 13, 2014 16:50
by cacatoès
Hiya,

I haven't found any thread about this issue,

Each server has a defined number of slots for players. It happens they are all used up, sometimes by players who leave their computers running but who are not in front.

It would make sense to be able to set an inactivity period (like 1 hour), after which if no activity from the player it would gently disconnect (and free the slot). This period could be set by server admins and eventually disabled.

I'm unsure what would be the best way to track (in)activity since I don't know well the game mechanisms, but I guess you have ideas on this ;)

Regards,

Re: Disconnect player if inactive (and free a slot)

PostPosted: Mon Oct 13, 2014 19:14
by kaeza
Hello and welcome.

Something like this should work:

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
-- Interval between movement checks (in seconds).
local INTERVAL = 5

-- Minimum distance to move to register as not AFK (in blocks).
local MINDIST = 0.2

-- If player does not move within this time, kick player (in seconds).
local TIMEOUT = 300 -- 5 minutes

local time_afk = { }
local last_pos = { }

local function check_moved()
   for _, p in ipairs(minetest.get_connected_players()) do
      local plname = p:get_player_name()
      local pos = p:getpos()
      local kicked
      if last_pos[plname] then
         local d = vector.distance(last_pos[plname], pos)
         print("Player: "..plname..", Dist: "..d)
         if d < MINDIST then
            time_afk[plname] = (time_afk[plname] or 0) + INTERVAL
            if time_afk[plname] >= TIMEOUT then
               minetest.kick_player(plname,
                     "Inactive for "..TIMEOUT.." seconds.")
               kicked = true
            end
         else
            time_afk[plname] = 0
         end
      end
      if not kicked then
         last_pos[plname] = pos
      end
   end
   minetest.after(INTERVAL, check_moved)
end
minetest.after(INTERVAL, check_moved)

minetest.register_on_leaveplayer(function(player)
   local plname = player:get_player_name()
   time_afk[plname] = nil
   last_pos[plname] = nil
end)

Re: Disconnect player if inactive (and free a slot)

PostPosted: Mon Oct 13, 2014 20:15
by Gael de Sailly
I support.
+1

Re: Disconnect player if inactive (and free a slot)

PostPosted: Wed Oct 15, 2014 14:21
by CWz
i don't think the timeout time resets if the player starts moving

Re: Disconnect player if inactive (and free a slot)

PostPosted: Thu Oct 16, 2014 08:28
by kaeza
CWz wrote:i don't think the timeout time resets if the player starts moving

Thanks for spotting that. I corrected the snippet.

Re: Disconnect player if inactive (and free a slot)

PostPosted: Thu Oct 16, 2014 20:01
by cacatoès
Thanks for the code.

Are there chances for this to be merged into minetest ?

Re: Disconnect player if inactive (and free a slot)

PostPosted: Fri Oct 17, 2014 07:15
by Sol
keza, is there any particular advantage of using .after instead of globalstep?

Re: Disconnect player if inactive (and free a slot)

PostPosted: Fri Oct 17, 2014 22:44
by kaeza
Sol wrote:keza, is there any particular advantage of using .after instead of globalstep?

By using `after`, I avoid having to implement a timer to do it at some intervals. The `on_globalstep` callbacks run on every server step, which would be potentially slower and not really needed in this case.

EDIT: clarification.

Re: Disconnect player if inactive (and free a slot)

PostPosted: Fri Oct 17, 2014 22:46
by kaeza
cacatoès wrote:Thanks for the code.

Are there chances for this to be merged into minetest ?

I wouldn't bet on that, but feel free to submit a pull/feature request on Github.

EDIT: In case anyone has any problems, I release the code I posted as CC-0 (effectively "public domain").

Re: Disconnect player if inactive (and free a slot)

PostPosted: Sat Oct 18, 2014 05:36
by Sol
kaeza wrote:By using `after`, I avoid having to implement a timer to do it at some intervals. The `on_globalstep` callbacks run on every server step, which would be potentially slower and not really needed in this case.

Thanks for explanation!

Re: Disconnect player if inactive (and free a slot)

PostPosted: Mon Oct 20, 2014 15:55
by CWz
Now time for me to figure out to how add a "may afk" priv to that script

Re: Disconnect player if inactive (and free a slot)

PostPosted: Sun Oct 26, 2014 20:15
by cacatoès
Moreover I believe the code snippet above assumes "activity" is "to walk", while some other actions may as well be considered as "activity".
I would consider someone to be active if:
* Standing up without moving and have a chat with others, or playing with his/her inventory/crafting.

I am unsure a "may afk" priv would be useful. If this is a mean to allow admins of a server to stay as long as they want, I believe some private slots would be more appropriate to answer this need.
The logic with this auto-kick is: if you're automatically kicked, you still can reconnect as soon as you're back on your computer.

So if I sum up,
* Better define what "activity" is (i.e: not only walking)
* I also guess the inactivity period should be a variable in server config (minetest.conf), unless set to a sane default (30 minutes ?)

Unfortunately I can't code, so I may formalize a feature request if this topic makes sense.