diff --git a/Content.Server/Afk/AFKSystem.cs b/Content.Server/Afk/AFKSystem.cs index 0f2bc52112..0cfb1997e5 100644 --- a/Content.Server/Afk/AFKSystem.cs +++ b/Content.Server/Afk/AFKSystem.cs @@ -1,5 +1,6 @@ using System.Linq; using Content.Server.Afk.Events; +using Content.Server.Chat.Managers; using Content.Server.GameTicking; using Content.Shared.CCVar; using Robust.Server.Player; @@ -20,17 +21,20 @@ public sealed class AFKSystem : EntitySystem [Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly GameTicker _ticker = default!; + [Dependency] private readonly IChatManager _chatManager = default!; private float _checkDelay; + private float _kickDelay; private TimeSpan _checkTime; - private readonly HashSet _afkPlayers = new(); + private readonly Dictionary _afkPlayers = new(); public override void Initialize() { base.Initialize(); _playerManager.PlayerStatusChanged += OnPlayerChange; _configManager.OnValueChanged(CCVars.AfkTime, SetAfkDelay, true); + _configManager.OnValueChanged(CCVars.AfkKickTime, SetAfkKickDelay, true); } private void SetAfkDelay(float obj) @@ -38,6 +42,11 @@ public sealed class AFKSystem : EntitySystem _checkDelay = obj; } + private void SetAfkKickDelay(float obj) + { + _kickDelay = obj; + } + private void OnPlayerChange(object? sender, SessionStatusEventArgs e) { switch (e.NewStatus) @@ -54,6 +63,7 @@ public sealed class AFKSystem : EntitySystem _afkPlayers.Clear(); _playerManager.PlayerStatusChanged -= OnPlayerChange; _configManager.UnsubValueChanged(CCVars.AfkTime, SetAfkDelay); + _configManager.UnsubValueChanged(CCVars.AfkKickTime, SetAfkKickDelay); } public override void Update(float frameTime) @@ -78,18 +88,25 @@ public sealed class AFKSystem : EntitySystem var pSession = (IPlayerSession) session; var isAfk = _afkManager.IsAfk(pSession); - if (isAfk && _afkPlayers.Add(pSession)) + if (isAfk && _afkPlayers.TryAdd(pSession, _timing.CurTime)) { var ev = new AFKEvent(pSession); RaiseLocalEvent(ref ev); - continue; + + _chatManager.DispatchServerMessage(pSession, Loc.GetString("afk-system-kick-warning")); } if (!isAfk && _afkPlayers.Remove(pSession)) { var ev = new UnAFKEvent(pSession); RaiseLocalEvent(ref ev); - continue; + } + + if (isAfk && + _afkPlayers.TryGetValue(pSession, out var startAfkTime) && + _timing.CurTime - startAfkTime >= TimeSpan.FromSeconds(_kickDelay)) + { + pSession.ConnectedClient.Disconnect( Loc.GetString("afk-system-kick-reason")); } } } diff --git a/Content.Shared/CCVar/CCVars.cs b/Content.Shared/CCVar/CCVars.cs index 58c1198bc0..7000124fa8 100644 --- a/Content.Shared/CCVar/CCVars.cs +++ b/Content.Shared/CCVar/CCVars.cs @@ -1149,6 +1149,12 @@ namespace Content.Shared.CCVar public static readonly CVarDef AfkTime = CVarDef.Create("afk.time", 60f, CVar.SERVERONLY); + /// + /// How long seconds a client can go after being detected as AFK before being kicked. + /// + public static readonly CVarDef AfkKickTime = + CVarDef.Create("afk.kick_time", 600f, CVar.SERVERONLY); + /* * IC */ diff --git a/Resources/Locale/en-US/afk/afk.ftl b/Resources/Locale/en-US/afk/afk.ftl new file mode 100644 index 0000000000..6401ddba5c --- /dev/null +++ b/Resources/Locale/en-US/afk/afk.ftl @@ -0,0 +1,2 @@ +afk-system-kick-warning = You will be kicked for being AFK soon! +afk-system-kick-reason = You were kicked for being AFK!