Files
tbd-station-14/Content.Server/Afk/AFKSystem.cs
Pieter-Jan Briers 68ce53ae17 Random spontaneous cleanup PR (#25131)
* Use new Subs.CVar helper

Removes manual config OnValueChanged calls, removes need to remember to manually unsubscribe.

This both reduces boilerplate and fixes many issues where subscriptions weren't removed on entity system shutdown.

* Fix a bunch of warnings

* More warning fixes

* Use new DateTime serializer to get rid of ISerializationHooks in changelog code.

* Get rid of some more ISerializationHooks for enums

* And a little more

* Apply suggestions from code review

Co-authored-by: 0x6273 <0x40@keemail.me>

---------

Co-authored-by: 0x6273 <0x40@keemail.me>
2024-02-13 16:48:39 -05:00

102 lines
2.9 KiB
C#

using Content.Server.Afk.Events;
using Content.Server.GameTicking;
using Content.Shared.CCVar;
using Robust.Server.Player;
using Robust.Shared.Configuration;
using Robust.Shared.Enums;
using Robust.Shared.Input;
using Robust.Shared.Player;
using Robust.Shared.Timing;
namespace Content.Server.Afk;
/// <summary>
/// Actively checks for AFK players regularly and issues an event whenever they go afk.
/// </summary>
public sealed class AFKSystem : EntitySystem
{
[Dependency] private readonly IAfkManager _afkManager = default!;
[Dependency] private readonly IConfigurationManager _configManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly GameTicker _ticker = default!;
private float _checkDelay;
private TimeSpan _checkTime;
private readonly HashSet<ICommonSession> _afkPlayers = new();
public override void Initialize()
{
base.Initialize();
_playerManager.PlayerStatusChanged += OnPlayerChange;
Subs.CVar(_configManager, CCVars.AfkTime, SetAfkDelay, true);
SubscribeNetworkEvent<FullInputCmdMessage>(HandleInputCmd);
}
private void HandleInputCmd(FullInputCmdMessage msg, EntitySessionEventArgs args)
{
_afkManager.PlayerDidAction(args.SenderSession);
}
private void SetAfkDelay(float obj)
{
_checkDelay = obj;
}
private void OnPlayerChange(object? sender, SessionStatusEventArgs e)
{
switch (e.NewStatus)
{
case SessionStatus.Disconnected:
_afkPlayers.Remove(e.Session);
break;
}
}
public override void Shutdown()
{
base.Shutdown();
_afkPlayers.Clear();
_playerManager.PlayerStatusChanged -= OnPlayerChange;
}
public override void Update(float frameTime)
{
base.Update(frameTime);
if (_ticker.RunLevel != GameRunLevel.InRound)
{
_afkPlayers.Clear();
_checkTime = TimeSpan.Zero;
return;
}
// TODO: Should also listen to the input events for more accurate timings.
if (_timing.CurTime < _checkTime)
return;
_checkTime = _timing.CurTime + TimeSpan.FromSeconds(_checkDelay);
foreach (var pSession in Filter.GetAllPlayers())
{
if (pSession.Status != SessionStatus.InGame) continue;
var isAfk = _afkManager.IsAfk(pSession);
if (isAfk && _afkPlayers.Add(pSession))
{
var ev = new AFKEvent(pSession);
RaiseLocalEvent(ref ev);
continue;
}
if (!isAfk && _afkPlayers.Remove(pSession))
{
var ev = new UnAFKEvent(pSession);
RaiseLocalEvent(ref ev);
}
}
}
}