AfkManager.cs 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. using Content.Server.Administration.Managers;
  2. using Content.Shared.CCVar;
  3. using JetBrains.Annotations;
  4. using Robust.Server.Player;
  5. using Robust.Shared.Configuration;
  6. using Robust.Shared.Console;
  7. using Robust.Shared.Enums;
  8. using Robust.Shared.Player;
  9. using Robust.Shared.Timing;
  10. namespace Content.Server.Afk
  11. {
  12. /// <summary>
  13. /// Tracks AFK (away from keyboard) status for players.
  14. /// </summary>
  15. /// <seealso cref="CCVars.AfkTime"/>
  16. public interface IAfkManager
  17. {
  18. /// <summary>
  19. /// Check whether this player is currently AFK.
  20. /// </summary>
  21. /// <param name="player">The player to check.</param>
  22. /// <returns>True if the player is AFK, false otherwise.</returns>
  23. bool IsAfk(ICommonSession player);
  24. /// <summary>
  25. /// Resets AFK status for the player as if they just did an action and are definitely not AFK.
  26. /// </summary>
  27. /// <param name="player">The player to set AFK status for.</param>
  28. void PlayerDidAction(ICommonSession player);
  29. void Initialize();
  30. }
  31. [UsedImplicitly]
  32. public sealed class AfkManager : IAfkManager
  33. {
  34. [Dependency] private readonly IPlayerManager _playerManager = default!;
  35. [Dependency] private readonly IGameTiming _gameTiming = default!;
  36. [Dependency] private readonly IConfigurationManager _cfg = default!;
  37. [Dependency] private readonly IConsoleHost _consoleHost = default!;
  38. [Dependency] private readonly IAdminManager _adminManager = default!;
  39. private readonly Dictionary<ICommonSession, TimeSpan> _lastActionTimes = new();
  40. public void Initialize()
  41. {
  42. // Connecting, console commands and input commands all reset AFK status.
  43. _playerManager.PlayerStatusChanged += PlayerStatusChanged;
  44. _consoleHost.AnyCommandExecuted += ConsoleHostOnAnyCommandExecuted;
  45. }
  46. public void PlayerDidAction(ICommonSession player)
  47. {
  48. if (player.Status == SessionStatus.Disconnected)
  49. // Make sure we don't re-add to the dictionary if the player is disconnected now.
  50. return;
  51. _lastActionTimes[player] = _gameTiming.RealTime;
  52. }
  53. public bool IsAfk(ICommonSession player)
  54. {
  55. if (!_lastActionTimes.TryGetValue(player, out var time))
  56. {
  57. // Some weird edge case like disconnected clients. Just say true I guess.
  58. return true;
  59. }
  60. var timeOut = _adminManager.IsAdmin(player)
  61. ? TimeSpan.FromSeconds(_cfg.GetCVar(CCVars.AdminAfkTime))
  62. : TimeSpan.FromSeconds(_cfg.GetCVar(CCVars.AfkTime));
  63. return _gameTiming.RealTime - time > timeOut;
  64. }
  65. private void PlayerStatusChanged(object? sender, SessionStatusEventArgs e)
  66. {
  67. if (e.NewStatus == SessionStatus.Disconnected)
  68. {
  69. _lastActionTimes.Remove(e.Session);
  70. return;
  71. }
  72. PlayerDidAction(e.Session);
  73. }
  74. private void ConsoleHostOnAnyCommandExecuted(IConsoleShell shell, string commandname, string argstr, string[] args)
  75. {
  76. if (shell.Player is { } player)
  77. PlayerDidAction(player);
  78. }
  79. }
  80. }