diff --git a/Content.Client/Communications/UI/CommunicationsConsoleBoundUserInterface.cs b/Content.Client/Communications/UI/CommunicationsConsoleBoundUserInterface.cs index dc7448aab1..07492b310f 100644 --- a/Content.Client/Communications/UI/CommunicationsConsoleBoundUserInterface.cs +++ b/Content.Client/Communications/UI/CommunicationsConsoleBoundUserInterface.cs @@ -1,5 +1,7 @@ -using Content.Shared.Communications; -using Robust.Client.GameObjects; +using Content.Shared.CCVar; +using Content.Shared.Chat; +using Content.Shared.Communications; +using Robust.Shared.Configuration; using Robust.Shared.Timing; namespace Content.Client.Communications.UI @@ -7,6 +9,7 @@ namespace Content.Client.Communications.UI public sealed class CommunicationsConsoleBoundUserInterface : BoundUserInterface { [Dependency] private readonly IGameTiming _gameTiming = default!; + [Dependency] private readonly IConfigurationManager _cfg = default!; [ViewVariables] private CommunicationsConsoleMenu? _menu; @@ -63,22 +66,9 @@ namespace Content.Client.Communications.UI public void AnnounceButtonPressed(string message) { - var msg = (message.Length <= 256 ? message.Trim() : $"{message.Trim().Substring(0, 256)}...").ToCharArray(); - - // No more than 2 newlines, other replaced to spaces - var newlines = 0; - for (var i = 0; i < msg.Length; i++) - { - if (msg[i] != '\n') - continue; - - if (newlines >= 2) - msg[i] = ' '; - - newlines++; - } - - SendMessage(new CommunicationsConsoleAnnounceMessage(new string(msg))); + var maxLength = _cfg.GetCVar(CCVars.ChatMaxAnnouncementLength); + var msg = SharedChatSystem.SanitizeAnnouncement(message, maxLength); + SendMessage(new CommunicationsConsoleAnnounceMessage(msg)); } public void CallShuttle() diff --git a/Content.Client/Communications/UI/CommunicationsConsoleMenu.xaml.cs b/Content.Client/Communications/UI/CommunicationsConsoleMenu.xaml.cs index 8ab444f9ba..37fcdd5e29 100644 --- a/Content.Client/Communications/UI/CommunicationsConsoleMenu.xaml.cs +++ b/Content.Client/Communications/UI/CommunicationsConsoleMenu.xaml.cs @@ -23,7 +23,7 @@ namespace Content.Client.Communications.UI var loc = IoCManager.Resolve(); MessageInput.Placeholder = new Rope.Leaf(loc.GetString("comms-console-menu-announcement-placeholder")); - AnnounceButton.OnPressed += (_) => Owner.AnnounceButtonPressed(Rope.Collapse(MessageInput.TextRope).Trim()); + AnnounceButton.OnPressed += (_) => Owner.AnnounceButtonPressed(Rope.Collapse(MessageInput.TextRope)); AnnounceButton.Disabled = !owner.CanAnnounce; AlertLevelButton.OnItemSelected += args => diff --git a/Content.Client/NukeOps/WarDeclaratorBoundUserInterface.cs b/Content.Client/NukeOps/WarDeclaratorBoundUserInterface.cs index 7394e27043..20103a9743 100644 --- a/Content.Client/NukeOps/WarDeclaratorBoundUserInterface.cs +++ b/Content.Client/NukeOps/WarDeclaratorBoundUserInterface.cs @@ -1,13 +1,16 @@ -using Content.Shared.NukeOps; +using Content.Shared.CCVar; +using Content.Shared.Chat; +using Content.Shared.NukeOps; using JetBrains.Annotations; -using Robust.Client.GameObjects; -using Robust.Shared.Timing; +using Robust.Shared.Configuration; namespace Content.Client.NukeOps; [UsedImplicitly] public sealed class WarDeclaratorBoundUserInterface : BoundUserInterface { + [Dependency] private readonly IConfigurationManager _cfg = default!; + [ViewVariables] private WarDeclaratorWindow? _window; @@ -44,6 +47,8 @@ public sealed class WarDeclaratorBoundUserInterface : BoundUserInterface private void OnWarDeclaratorActivated(string message) { - SendMessage(new WarDeclaratorActivateMessage(message)); + var maxLength = _cfg.GetCVar(CCVars.ChatMaxAnnouncementLength); + var msg = SharedChatSystem.SanitizeAnnouncement(message, maxLength); + SendMessage(new WarDeclaratorActivateMessage(msg)); } } diff --git a/Content.Client/NukeOps/WarDeclaratorWindow.xaml.cs b/Content.Client/NukeOps/WarDeclaratorWindow.xaml.cs index 8fb10b8215..104e776daa 100644 --- a/Content.Client/NukeOps/WarDeclaratorWindow.xaml.cs +++ b/Content.Client/NukeOps/WarDeclaratorWindow.xaml.cs @@ -2,7 +2,6 @@ using Content.Shared.NukeOps; using Robust.Client.AutoGenerated; using Robust.Client.Graphics; -using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.XAML; using Robust.Shared.Timing; @@ -27,7 +26,7 @@ public sealed partial class WarDeclaratorWindow : DefaultWindow _gameTiming = IoCManager.Resolve(); - WarButton.OnPressed += ActivateWarDeclarator; + WarButton.OnPressed += (_) => OnActivated?.Invoke(Rope.Collapse(MessageEdit.TextRope)); var loc = IoCManager.Resolve(); MessageEdit.Placeholder = new Rope.Leaf(loc.GetString("war-declarator-message-placeholder")); @@ -129,10 +128,4 @@ public sealed partial class WarDeclaratorWindow : DefaultWindow return; } } - - private void ActivateWarDeclarator(BaseButton.ButtonEventArgs obj) - { - var message = Rope.Collapse(MessageEdit.TextRope); - OnActivated?.Invoke(message); - } } diff --git a/Content.Server/Communications/CommunicationsConsoleSystem.cs b/Content.Server/Communications/CommunicationsConsoleSystem.cs index ea27450956..6a4cd23ba1 100644 --- a/Content.Server/Communications/CommunicationsConsoleSystem.cs +++ b/Content.Server/Communications/CommunicationsConsoleSystem.cs @@ -11,6 +11,7 @@ using Content.Server.Station.Systems; using Content.Shared.Access.Components; using Content.Shared.Access.Systems; using Content.Shared.CCVar; +using Content.Shared.Chat; using Content.Shared.Communications; using Content.Shared.Database; using Content.Shared.Emag.Components; @@ -35,8 +36,6 @@ namespace Content.Server.Communications [Dependency] private readonly IConfigurationManager _cfg = default!; [Dependency] private readonly IAdminLogManager _adminLogger = default!; - private const int MaxMessageLength = 256; - private const int MaxMessageNewlines = 2; private const float UIUpdateInterval = 5.0f; public override void Initialize() @@ -231,22 +230,8 @@ namespace Content.Server.Communications private void OnAnnounceMessage(EntityUid uid, CommunicationsConsoleComponent comp, CommunicationsConsoleAnnounceMessage message) { - var msgWords = message.Message.Trim(); - var msgChars = (msgWords.Length <= MaxMessageLength ? msgWords : $"{msgWords[0..MaxMessageLength]}...").ToCharArray(); - - var newlines = 0; - for (var i = 0; i < msgChars.Length; i++) - { - if (msgChars[i] != '\n') - continue; - - if (newlines >= MaxMessageNewlines) - msgChars[i] = ' '; - - newlines++; - } - - var msg = new string(msgChars); + var maxLength = _cfg.GetCVar(CCVars.ChatMaxAnnouncementLength); + var msg = SharedChatSystem.SanitizeAnnouncement(message.Message, maxLength); var author = Loc.GetString("comms-console-announcement-unknown-sender"); if (message.Session.AttachedEntity is { Valid: true } mob) { diff --git a/Content.Server/NukeOps/WarDeclaratorComponent.cs b/Content.Server/NukeOps/WarDeclaratorComponent.cs index 15279ee13c..ef6a3db5af 100644 --- a/Content.Server/NukeOps/WarDeclaratorComponent.cs +++ b/Content.Server/NukeOps/WarDeclaratorComponent.cs @@ -22,10 +22,6 @@ public sealed partial class WarDeclaratorComponent : Component [DataField] public bool AllowEditingMessage = true; - [ViewVariables(VVAccess.ReadWrite)] - [DataField] - public int MaxMessageLength = 512; - /// /// War declarement text color /// diff --git a/Content.Server/NukeOps/WarDeclaratorSystem.cs b/Content.Server/NukeOps/WarDeclaratorSystem.cs index dcf6c28d43..328990738e 100644 --- a/Content.Server/NukeOps/WarDeclaratorSystem.cs +++ b/Content.Server/NukeOps/WarDeclaratorSystem.cs @@ -3,9 +3,12 @@ using Content.Server.GameTicking.Rules; using Content.Server.GameTicking.Rules.Components; using Content.Server.Popups; using Content.Server.UserInterface; +using Content.Shared.CCVar; +using Content.Shared.Chat; using Content.Shared.Database; using Content.Shared.NukeOps; using Robust.Server.GameObjects; +using Robust.Shared.Configuration; namespace Content.Server.NukeOps; @@ -18,6 +21,7 @@ public sealed class WarDeclaratorSystem : EntitySystem [Dependency] private readonly IAdminLogManager _adminLogger = default!; [Dependency] private readonly NukeopsRuleSystem _nukeopsRuleSystem = default!; [Dependency] private readonly PopupSystem _popupSystem = default!; + [Dependency] private readonly IConfigurationManager _cfg = default!; public override void Initialize() { @@ -52,22 +56,8 @@ public sealed class WarDeclaratorSystem : EntitySystem return; } - var text = (args.Message.Length <= component.MaxMessageLength ? args.Message.Trim() : $"{args.Message.Trim().Substring(0, 256)}...").ToCharArray(); - - // No more than 2 newlines, other replaced to spaces - var newlines = 0; - for (var i = 0; i < text.Length; i++) - { - if (text[i] != '\n') - continue; - - if (newlines >= 2) - text[i] = ' '; - - newlines++; - } - - string message = new string(text); + var maxLength = _cfg.GetCVar(CCVars.ChatMaxAnnouncementLength); + var message = SharedChatSystem.SanitizeAnnouncement(args.Message, maxLength); if (component.AllowEditingMessage && message != string.Empty) { component.Message = message; diff --git a/Content.Shared/CCVar/CCVars.cs b/Content.Shared/CCVar/CCVars.cs index a3b875feef..f0b6c2f923 100644 --- a/Content.Shared/CCVar/CCVars.cs +++ b/Content.Shared/CCVar/CCVars.cs @@ -1598,6 +1598,9 @@ namespace Content.Shared.CCVar public static readonly CVarDef ChatMaxMessageLength = CVarDef.Create("chat.max_message_length", 1000, CVar.SERVER | CVar.REPLICATED); + public static readonly CVarDef ChatMaxAnnouncementLength = + CVarDef.Create("chat.max_announcement_length", 256, CVar.SERVER | CVar.REPLICATED); + public static readonly CVarDef ChatSanitizerEnabled = CVarDef.Create("chat.chat_sanitizer_enabled", true, CVar.SERVERONLY); diff --git a/Content.Shared/Chat/SharedChatSystem.cs b/Content.Shared/Chat/SharedChatSystem.cs index 69918f8098..931bfb37fc 100644 --- a/Content.Shared/Chat/SharedChatSystem.cs +++ b/Content.Shared/Chat/SharedChatSystem.cs @@ -184,4 +184,34 @@ public abstract class SharedChatSystem : EntitySystem return message; } + + public static string SanitizeAnnouncement(string message, int maxLength = 0, int maxNewlines = 2) + { + var trimmed = message.Trim(); + if (maxLength > 0 && trimmed.Length > maxLength) + { + trimmed = $"{message[..maxLength]}..."; + } + + // No more than max newlines, other replaced to spaces + if (maxNewlines > 0) + { + var chars = trimmed.ToCharArray(); + var newlines = 0; + for (var i = 0; i < chars.Length; i++) + { + if (chars[i] != '\n') + continue; + + if (newlines >= maxNewlines) + chars[i] = ' '; + + newlines++; + } + + return new string(chars); + } + + return trimmed; + } }