Merge remote-tracking branch 'upstream/master' into ed-21-06-2024-upstream-sync
# Conflicts: # Resources/Prototypes/Maps/europa.yml # Resources/Prototypes/Maps/train.yml
This commit is contained in:
@@ -1,84 +1,41 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using Content.Server.Players.RateLimiting;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Database;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Server.Chat.Managers;
|
||||
|
||||
internal sealed partial class ChatManager
|
||||
{
|
||||
private readonly Dictionary<ICommonSession, RateLimitDatum> _rateLimitData = new();
|
||||
private const string RateLimitKey = "Chat";
|
||||
|
||||
public bool HandleRateLimit(ICommonSession player)
|
||||
private void RegisterRateLimits()
|
||||
{
|
||||
ref var datum = ref CollectionsMarshal.GetValueRefOrAddDefault(_rateLimitData, player, out _);
|
||||
var time = _gameTiming.RealTime;
|
||||
if (datum.CountExpires < time)
|
||||
{
|
||||
// Period expired, reset it.
|
||||
var periodLength = _configurationManager.GetCVar(CCVars.ChatRateLimitPeriod);
|
||||
datum.CountExpires = time + TimeSpan.FromSeconds(periodLength);
|
||||
datum.Count = 0;
|
||||
datum.Announced = false;
|
||||
}
|
||||
|
||||
var maxCount = _configurationManager.GetCVar(CCVars.ChatRateLimitCount);
|
||||
datum.Count += 1;
|
||||
|
||||
if (datum.Count <= maxCount)
|
||||
return true;
|
||||
|
||||
// Breached rate limits, inform admins if configured.
|
||||
if (_configurationManager.GetCVar(CCVars.ChatRateLimitAnnounceAdmins))
|
||||
{
|
||||
if (datum.NextAdminAnnounce < time)
|
||||
_rateLimitManager.Register(RateLimitKey,
|
||||
new RateLimitRegistration
|
||||
{
|
||||
SendAdminAlert(Loc.GetString("chat-manager-rate-limit-admin-announcement", ("player", player.Name)));
|
||||
var delay = _configurationManager.GetCVar(CCVars.ChatRateLimitAnnounceAdminsDelay);
|
||||
datum.NextAdminAnnounce = time + TimeSpan.FromSeconds(delay);
|
||||
}
|
||||
}
|
||||
|
||||
if (!datum.Announced)
|
||||
{
|
||||
DispatchServerMessage(player, Loc.GetString("chat-manager-rate-limited"), suppressLog: true);
|
||||
_adminLogger.Add(LogType.ChatRateLimited, LogImpact.Medium, $"Player {player} breached chat rate limits");
|
||||
|
||||
datum.Announced = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
CVarLimitPeriodLength = CCVars.ChatRateLimitPeriod,
|
||||
CVarLimitCount = CCVars.ChatRateLimitCount,
|
||||
CVarAdminAnnounceDelay = CCVars.ChatRateLimitAnnounceAdminsDelay,
|
||||
PlayerLimitedAction = RateLimitPlayerLimited,
|
||||
AdminAnnounceAction = RateLimitAlertAdmins,
|
||||
AdminLogType = LogType.ChatRateLimited,
|
||||
});
|
||||
}
|
||||
|
||||
private void PlayerStatusChanged(object? sender, SessionStatusEventArgs e)
|
||||
private void RateLimitPlayerLimited(ICommonSession player)
|
||||
{
|
||||
if (e.NewStatus == SessionStatus.Disconnected)
|
||||
_rateLimitData.Remove(e.Session);
|
||||
DispatchServerMessage(player, Loc.GetString("chat-manager-rate-limited"), suppressLog: true);
|
||||
}
|
||||
|
||||
private struct RateLimitDatum
|
||||
private void RateLimitAlertAdmins(ICommonSession player)
|
||||
{
|
||||
/// <summary>
|
||||
/// Time stamp (relative to <see cref="IGameTiming.RealTime"/>) this rate limit period will expire at.
|
||||
/// </summary>
|
||||
public TimeSpan CountExpires;
|
||||
if (_configurationManager.GetCVar(CCVars.ChatRateLimitAnnounceAdmins))
|
||||
SendAdminAlert(Loc.GetString("chat-manager-rate-limit-admin-announcement", ("player", player.Name)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// How many messages have been sent in the current rate limit period.
|
||||
/// </summary>
|
||||
public int Count;
|
||||
|
||||
/// <summary>
|
||||
/// Have we announced to the player that they've been blocked in this rate limit period?
|
||||
/// </summary>
|
||||
public bool Announced;
|
||||
|
||||
/// <summary>
|
||||
/// Time stamp (relative to <see cref="IGameTiming.RealTime"/>) of the
|
||||
/// next time we can send an announcement to admins about rate limit breach.
|
||||
/// </summary>
|
||||
public TimeSpan NextAdminAnnounce;
|
||||
public RateLimitStatus HandleRateLimit(ICommonSession player)
|
||||
{
|
||||
return _rateLimitManager.CountAction(player, RateLimitKey);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,18 +5,17 @@ using Content.Server.Administration.Logs;
|
||||
using Content.Server.Administration.Managers;
|
||||
using Content.Server.Administration.Systems;
|
||||
using Content.Server.MoMMI;
|
||||
using Content.Server.Players.RateLimiting;
|
||||
using Content.Server.Preferences.Managers;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Chat;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Mind;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Replays;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server.Chat.Managers
|
||||
@@ -43,8 +42,7 @@ namespace Content.Server.Chat.Managers
|
||||
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
|
||||
[Dependency] private readonly INetConfigurationManager _netConfigManager = default!;
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly PlayerRateLimitManager _rateLimitManager = default!;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum length a player-sent message can be sent
|
||||
@@ -64,7 +62,7 @@ namespace Content.Server.Chat.Managers
|
||||
_configurationManager.OnValueChanged(CCVars.OocEnabled, OnOocEnabledChanged, true);
|
||||
_configurationManager.OnValueChanged(CCVars.AdminOocEnabled, OnAdminOocEnabledChanged, true);
|
||||
|
||||
_playerManager.PlayerStatusChanged += PlayerStatusChanged;
|
||||
RegisterRateLimits();
|
||||
}
|
||||
|
||||
private void OnOocEnabledChanged(bool val)
|
||||
@@ -206,7 +204,7 @@ namespace Content.Server.Chat.Managers
|
||||
/// <param name="type">The type of message.</param>
|
||||
public void TrySendOOCMessage(ICommonSession player, string message, OOCChatType type)
|
||||
{
|
||||
if (!HandleRateLimit(player))
|
||||
if (HandleRateLimit(player) != RateLimitStatus.Allowed)
|
||||
return;
|
||||
|
||||
// Check if message exceeds the character limit
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Server.Players;
|
||||
using Content.Server.Players.RateLimiting;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Chat;
|
||||
using Robust.Shared.Network;
|
||||
@@ -50,6 +52,6 @@ namespace Content.Server.Chat.Managers
|
||||
/// </summary>
|
||||
/// <param name="player">The player sending a chat message.</param>
|
||||
/// <returns>False if the player has violated rate limits and should be blocked from sending further messages.</returns>
|
||||
bool HandleRateLimit(ICommonSession player);
|
||||
RateLimitStatus HandleRateLimit(ICommonSession player);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using Content.Server.Administration.Managers;
|
||||
using Content.Server.Chat.Managers;
|
||||
using Content.Server.Examine;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.Players.RateLimiting;
|
||||
using Content.Server.Speech.Components;
|
||||
using Content.Server.Speech.EntitySystems;
|
||||
using Content.Server.Station.Components;
|
||||
@@ -183,7 +184,7 @@ public sealed partial class ChatSystem : SharedChatSystem
|
||||
return;
|
||||
}
|
||||
|
||||
if (player != null && !_chatManager.HandleRateLimit(player))
|
||||
if (player != null && _chatManager.HandleRateLimit(player) != RateLimitStatus.Allowed)
|
||||
return;
|
||||
|
||||
// Sus
|
||||
@@ -272,7 +273,7 @@ public sealed partial class ChatSystem : SharedChatSystem
|
||||
if (!CanSendInGame(message, shell, player))
|
||||
return;
|
||||
|
||||
if (player != null && !_chatManager.HandleRateLimit(player))
|
||||
if (player != null && _chatManager.HandleRateLimit(player) != RateLimitStatus.Allowed)
|
||||
return;
|
||||
|
||||
// It doesn't make any sense for a non-player to send in-game OOC messages, whereas non-players may be sending
|
||||
|
||||
Reference in New Issue
Block a user