init.lua 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. afk_removal = afk_removal or {}
  2. afk_removal.players = afk_removal.players or {}
  3. afk_removal.modpath = minetest.get_modpath("afk_removal")
  4. afk_removal.steptime = 5
  5. afk_removal.timeout = 60 * 30
  6. afk_removal.warntime = 60 * 29
  7. afk_removal.disable_kick = minetest.is_singleplayer()
  8. -- Public API function.
  9. -- This should be called from any mod that wishes to reset the kick timeout for a player.
  10. -- For example, a chat mod may call this when a player chats.
  11. afk_removal.reset_timeout = function(name)
  12. -- localize
  13. local players = afk_removal.players
  14. -- Ensure an entry exists for this name.
  15. local data = players[name]
  16. if not data then
  17. players[name] = {time=0, pos={x=0, y=0, z=0}}
  18. data = players[name]
  19. end
  20. data.time = 0
  21. data.afk = nil
  22. end
  23. function afk_removal.on_joinplayer(player)
  24. local name = player:get_player_name()
  25. afk_removal.players[name] = {time=0, pos=player:get_pos()}
  26. end
  27. function afk_removal.on_leaveplayer(player, timedout)
  28. local pname = player:get_player_name()
  29. afk_removal.players[pname] = nil
  30. end
  31. -- API function to query whether a player is currently AFK.
  32. -- Note that this only has meaning for registered players.
  33. -- Unregistered players are kicked, so you generally won't encounter those.
  34. function afk_removal.is_afk(pname)
  35. local p = afk_removal.players
  36. local o = p[pname]
  37. if o then
  38. if o.afk then
  39. return true
  40. end
  41. end
  42. return false
  43. end
  44. -- Returns the number of seconds since player's last action.
  45. -- Returns -1 if player data is not available (wrong player name?).
  46. function afk_removal.seconds_since_action(pname)
  47. local p = afk_removal.players
  48. local o = p[pname]
  49. if o then
  50. return o.time
  51. end
  52. return -1
  53. end
  54. afk_removal.update = function()
  55. local allplayers = minetest.get_connected_players()
  56. for k, player in ipairs(allplayers) do
  57. local name = player:get_player_name()
  58. local target = afk_removal.players[name]
  59. local pos = vector.round(player:getpos())
  60. local dist = vector.distance(pos, target.pos)
  61. local nokick = false
  62. if afk_removal.disable_kick or minetest.check_player_privs(name, {canafk=true}) then
  63. nokick = true
  64. end
  65. if dist > 0.5 then
  66. target.pos = pos
  67. target.time = 0
  68. target.afk = nil
  69. else
  70. -- Increase time since AFK started.
  71. local time = target.time
  72. time = time + afk_removal.steptime
  73. target.time = time
  74. if not nokick and time >= afk_removal.warntime then
  75. -- Only ignore players who are registered and NOT dead.
  76. if player:get_hp() > 0 and passport.player_registered(name) then
  77. -- If player is registered and NOT dead, don't send message.
  78. nokick = true
  79. else
  80. local remain = afk_removal.timeout - time
  81. minetest.chat_send_player(name, "# Server: You will be kicked for inactivity in " .. math.floor(remain) .. " seconds.")
  82. easyvend.sound_error(name)
  83. end
  84. end
  85. end
  86. -- Kick players who have done nothing for too long.
  87. if target.time >= afk_removal.timeout then
  88. if nokick then
  89. -- If player is registered and NOT dead, then just mark them as AFK.
  90. -- If player is registered but dead, they'll be kicked anyway.
  91. target.afk = true
  92. else
  93. minetest.kick_player(name, "Kicked for inactivity.")
  94. local dname = rename.gpn(name)
  95. minetest.chat_send_all("# Server: <" .. dname .. "> was kicked for being AFK too long.")
  96. end
  97. end
  98. end
  99. end
  100. local timer = 0
  101. local delay = afk_removal.steptime
  102. function afk_removal.globalstep(dtime)
  103. timer = timer + dtime
  104. if timer < delay then return end
  105. timer = 0
  106. afk_removal.update()
  107. end
  108. function afk_removal.on_craft(itemstack, player, old_craft_grid, craft_inv)
  109. if not player then return end
  110. if not player:is_player() then return end
  111. -- Ensure this player has an entry in the table.
  112. local name = player:get_player_name()
  113. if not afk_removal.players[name] then
  114. afk_removal.players[name] = {time=0, pos={x=0, y=0, z=0}}
  115. end
  116. afk_removal.players[name].time = 0
  117. end
  118. local function toggle_status(name)
  119. if not afk_removal.players[name] then
  120. return
  121. end
  122. if afk_removal.players[name].afk then
  123. afk_removal.players[name].afk = nil
  124. minetest.chat_send_player(name, "# Server: You're no longer AFK.")
  125. else
  126. afk_removal.players[name].afk = true
  127. minetest.chat_send_player(name, "# Server: You've gone AFK!")
  128. end
  129. end
  130. function afk_removal.do_afk(name, param)
  131. if param ~= "" then
  132. local pname = rename.grn(param)
  133. if afk_removal.is_afk(pname) then
  134. minetest.chat_send_player(name, "# Server: <" .. rename.gpn(pname) .. "> is AFK!")
  135. else
  136. if minetest.get_player_by_name(pname) then
  137. local time = afk_removal.seconds_since_action(pname)
  138. if time < 60 then
  139. minetest.chat_send_player(name, "# Server: <" .. rename.gpn(pname) .. "> is active.")
  140. elseif time < 60*2 then
  141. minetest.chat_send_player(name, "# Server: <" .. rename.gpn(pname) .. "> might be AFK.")
  142. else
  143. minetest.chat_send_player(name, "# Server: <" .. rename.gpn(pname) .. "> is probably AFK.")
  144. end
  145. else
  146. minetest.chat_send_player(name, "# Server: <" .. param .. "> is not online.")
  147. end
  148. end
  149. else
  150. minetest.after(0, toggle_status, name)
  151. end
  152. end
  153. if not afk_removal.registered then
  154. -- Crafting resets the player's AFK timeout.
  155. minetest.register_on_craft(function(...)
  156. return afk_removal.on_craft(...)
  157. end)
  158. minetest.register_globalstep(function(...)
  159. return afk_removal.globalstep(...)
  160. end)
  161. minetest.register_privilege("canafk", {
  162. description = "Player can remain AFK without being kicked.",
  163. give_to_singleplayer = false,
  164. })
  165. minetest.register_on_joinplayer(function(...)
  166. return afk_removal.on_joinplayer(...)
  167. end)
  168. minetest.register_on_leaveplayer(function(...)
  169. return afk_removal.on_leaveplayer(...)
  170. end)
  171. minetest.register_chatcommand("afk", {
  172. params = "[name]",
  173. description = "Query whether another player is AFK, or toggle your own AFK status.",
  174. privs = {interact=true},
  175. func = function(...)
  176. afk_removal.do_afk(...)
  177. return true
  178. end,
  179. })
  180. local c = "afk_removal:core"
  181. local f = afk_removal.modpath .. "/init.lua"
  182. reload.register_file(c, f, false)
  183. afk_removal.registered = true
  184. end