AFKSystem.cs 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. using Content.Server.Afk.Events;
  2. using Content.Server.GameTicking;
  3. using Content.Shared.CCVar;
  4. using Robust.Server.Player;
  5. using Robust.Shared.Configuration;
  6. using Robust.Shared.Enums;
  7. using Robust.Shared.Input;
  8. using Robust.Shared.Player;
  9. using Robust.Shared.Timing;
  10. namespace Content.Server.Afk;
  11. /// <summary>
  12. /// Actively checks for AFK players regularly and issues an event whenever they go afk.
  13. /// </summary>
  14. public sealed class AFKSystem : EntitySystem
  15. {
  16. [Dependency] private readonly IAfkManager _afkManager = default!;
  17. [Dependency] private readonly IConfigurationManager _configManager = default!;
  18. [Dependency] private readonly IPlayerManager _playerManager = default!;
  19. [Dependency] private readonly IGameTiming _timing = default!;
  20. [Dependency] private readonly GameTicker _ticker = default!;
  21. private float _checkDelay;
  22. private TimeSpan _checkTime;
  23. private readonly HashSet<ICommonSession> _afkPlayers = new();
  24. public override void Initialize()
  25. {
  26. base.Initialize();
  27. _playerManager.PlayerStatusChanged += OnPlayerChange;
  28. Subs.CVar(_configManager, CCVars.AfkTime, SetAfkDelay, true);
  29. SubscribeNetworkEvent<FullInputCmdMessage>(HandleInputCmd);
  30. }
  31. private void HandleInputCmd(FullInputCmdMessage msg, EntitySessionEventArgs args)
  32. {
  33. _afkManager.PlayerDidAction(args.SenderSession);
  34. }
  35. private void SetAfkDelay(float obj)
  36. {
  37. _checkDelay = obj;
  38. }
  39. private void OnPlayerChange(object? sender, SessionStatusEventArgs e)
  40. {
  41. switch (e.NewStatus)
  42. {
  43. case SessionStatus.Disconnected:
  44. _afkPlayers.Remove(e.Session);
  45. break;
  46. }
  47. }
  48. public override void Shutdown()
  49. {
  50. base.Shutdown();
  51. _afkPlayers.Clear();
  52. _playerManager.PlayerStatusChanged -= OnPlayerChange;
  53. }
  54. public override void Update(float frameTime)
  55. {
  56. base.Update(frameTime);
  57. if (_ticker.RunLevel != GameRunLevel.InRound)
  58. {
  59. _afkPlayers.Clear();
  60. _checkTime = TimeSpan.Zero;
  61. return;
  62. }
  63. // TODO: Should also listen to the input events for more accurate timings.
  64. if (_timing.CurTime < _checkTime)
  65. return;
  66. _checkTime = _timing.CurTime + TimeSpan.FromSeconds(_checkDelay);
  67. foreach (var pSession in Filter.GetAllPlayers())
  68. {
  69. if (pSession.Status != SessionStatus.InGame) continue;
  70. var isAfk = _afkManager.IsAfk(pSession);
  71. if (isAfk && _afkPlayers.Add(pSession))
  72. {
  73. var ev = new AFKEvent(pSession);
  74. RaiseLocalEvent(ref ev);
  75. continue;
  76. }
  77. if (!isAfk && _afkPlayers.Remove(pSession))
  78. {
  79. var ev = new UnAFKEvent(pSession);
  80. RaiseLocalEvent(ref ev);
  81. }
  82. }
  83. }
  84. }