From 6af331c9ff8be54c3e53c67a4ecf1ec387a94234 Mon Sep 17 00:00:00 2001 From: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com> Date: Wed, 23 Nov 2022 00:52:19 +1300 Subject: [PATCH] Remove StoredChatMessage (#12623) --- Content.Client/Chat/StoredChatMessage.cs | 51 ---------- .../Systems/Chat/ChatUIController.cs | 20 ++-- .../Systems/Chat/Widgets/ChatBox.xaml.cs | 6 +- Content.Server/Chat/Managers/ChatManager.cs | 78 +++++++-------- Content.Server/Chat/Managers/IChatManager.cs | 11 ++- Content.Server/Chat/Systems/ChatSystem.cs | 56 ++++++----- Content.Server/GameTicking/GameTicker.cs | 5 +- .../GameTicking/Rules/ZombieRuleSystem.cs | 1 + .../Radio/EntitySystems/RadioDeviceSystem.cs | 2 +- .../Radio/EntitySystems/RadioSystem.cs | 19 ++-- Content.Shared/Chat/MsgChatMessage.cs | 94 +++++++------------ 11 files changed, 131 insertions(+), 212 deletions(-) delete mode 100644 Content.Client/Chat/StoredChatMessage.cs diff --git a/Content.Client/Chat/StoredChatMessage.cs b/Content.Client/Chat/StoredChatMessage.cs deleted file mode 100644 index 1d8d9c61f4..0000000000 --- a/Content.Client/Chat/StoredChatMessage.cs +++ /dev/null @@ -1,51 +0,0 @@ -using Content.Shared.Chat; -using Robust.Shared.Log; -using Robust.Shared.Maths; - -namespace Content.Client.Chat -{ - public sealed class StoredChatMessage - { - // TODO Make me reflected with respect to MsgChatMessage - - /// - /// Client's own copies of chat messages used in filtering locally - /// - - /// - /// Actual Message contents, i.e. words - /// - public string Message { get; set; } - - /// - /// Message channel, used for filtering - /// - public ChatChannel Channel { get; set; } - - /// - /// Modified message with some wrapping text. E.g. 'Joe says: "HELP!"' - /// - public string WrappedMessage { get; set; } - - /// - /// The override color of the message - /// - public Color MessageColorOverride { get; set; } - - /// - /// Whether the user has read this message at least once. - /// - public bool Read { get; set; } - - /// - /// Constructor to copy a net message into stored client variety - /// - public StoredChatMessage(MsgChatMessage netMsg) - { - Message = netMsg.Message; - Channel = netMsg.Channel; - WrappedMessage = netMsg.WrappedMessage; - MessageColorOverride = netMsg.MessageColorOverride; - } - } -} diff --git a/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs b/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs index fbc674bcf7..585a55e063 100644 --- a/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs +++ b/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs @@ -109,6 +109,7 @@ public sealed class ChatUIController : UIController = new(); private readonly HashSet _chats = new(); + public IReadOnlySet Chats => _chats; /// /// The max amount of characters an entity can send in one message @@ -121,7 +122,7 @@ public sealed class ChatUIController : UIController /// private readonly Dictionary _unreadMessages = new(); - public readonly List History = new(); + public readonly List History = new(); // Maintains which channels a client should be able to filter (for showing in the chatbox) // and select (for attempting to send on). @@ -142,7 +143,7 @@ public sealed class ChatUIController : UIController public event Action? FilterableChannelsChanged; public event Action? SelectableChannelsChanged; public event Action? UnreadMessageCountsUpdated; - public event Action? MessageAdded; + public event Action? MessageAdded; public override void Initialize() { @@ -285,7 +286,7 @@ public sealed class ChatUIController : UIController UpdateChannelPermissions(); } - private void AddSpeechBubble(MsgChatMessage msg, SpeechBubble.SpeechType speechType) + private void AddSpeechBubble(ChatMessage msg, SpeechBubble.SpeechType speechType) { if (!_entities.EntityExists(msg.SenderEntity)) { @@ -635,18 +636,19 @@ public sealed class ChatUIController : UIController box.ChatInput.Input.ReleaseKeyboardFocus(); } - private void OnChatMessage(MsgChatMessage msg) + private void OnChatMessage(MsgChatMessage message) => ProcessChatMessage(message.Message); + + public void ProcessChatMessage(ChatMessage msg) { // Log all incoming chat to repopulate when filter is un-toggled if (!msg.HideChat) { - var storedMessage = new StoredChatMessage(msg); - History.Add(storedMessage); - MessageAdded?.Invoke(storedMessage); + History.Add(msg); + MessageAdded?.Invoke(msg); - if (!storedMessage.Read) + if (!msg.Read) { - _sawmill.Debug($"Message filtered: {storedMessage.Channel}: {storedMessage.Message}"); + _sawmill.Debug($"Message filtered: {msg.Channel}: {msg.Message}"); if (!_unreadMessages.TryGetValue(msg.Channel, out var count)) count = 0; diff --git a/Content.Client/UserInterface/Systems/Chat/Widgets/ChatBox.xaml.cs b/Content.Client/UserInterface/Systems/Chat/Widgets/ChatBox.xaml.cs index a67740503e..663cb3dd0a 100644 --- a/Content.Client/UserInterface/Systems/Chat/Widgets/ChatBox.xaml.cs +++ b/Content.Client/UserInterface/Systems/Chat/Widgets/ChatBox.xaml.cs @@ -44,7 +44,7 @@ public partial class ChatBox : UIWidget _controller.SendMessage(this, SelectedChannel); } - private void OnMessageAdded(StoredChatMessage msg) + private void OnMessageAdded(ChatMessage msg) { Logger.DebugS("chat", $"{msg.Channel}: {msg.Message}"); if (!ChatInput.FilterButton.ChatFilterPopup.IsActive(msg.Channel)) @@ -54,8 +54,8 @@ public partial class ChatBox : UIWidget msg.Read = true; - var color = msg.MessageColorOverride != Color.Transparent - ? msg.MessageColorOverride + var color = msg.MessageColorOverride != null + ? msg.MessageColorOverride.Value : msg.Channel.TextColor(); AddLine(msg.WrappedMessage, color); diff --git a/Content.Server/Chat/Managers/ChatManager.cs b/Content.Server/Chat/Managers/ChatManager.cs index e32542a5d6..e9f16334fa 100644 --- a/Content.Server/Chat/Managers/ChatManager.cs +++ b/Content.Server/Chat/Managers/ChatManager.cs @@ -13,6 +13,7 @@ using Robust.Shared.Configuration; using Robust.Shared.Map; using Robust.Shared.Network; using Robust.Shared.Player; +using Robust.Shared.Replays; using Robust.Shared.Utility; namespace Content.Server.Chat.Managers @@ -30,15 +31,13 @@ namespace Content.Server.Chat.Managers { "revolutionary", "#aa00ff" } }; + [Dependency] private readonly IReplayRecordingManager _replay = default!; [Dependency] private readonly IServerNetManager _netManager = default!; [Dependency] private readonly IMoMMILink _mommiLink = default!; [Dependency] private readonly IAdminManager _adminManager = default!; [Dependency] private readonly IAdminLogManager _adminLogger = default!; [Dependency] private readonly IServerPreferencesManager _preferencesManager = default!; [Dependency] private readonly IConfigurationManager _configurationManager = default!; - [Dependency] private readonly IEntityManager _entityManager = default!; - - private StationSystem _stationSystem = default!; /// /// The maximum length a player-sent message can be sent @@ -50,7 +49,6 @@ namespace Content.Server.Chat.Managers public void Initialize() { - _stationSystem = _entityManager.EntitySysManager.GetEntitySystem(); _netManager.RegisterNetMessage(); _configurationManager.OnValueChanged(CCVars.OocEnabled, OnOocEnabledChanged, true); @@ -78,7 +76,7 @@ namespace Content.Server.Chat.Managers public void DispatchServerAnnouncement(string message, Color? colorOverride = null) { var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", FormattedMessage.EscapeText(message))); - ChatMessageToAll(ChatChannel.Server, message, wrappedMessage, colorOverride); + ChatMessageToAll(ChatChannel.Server, message, wrappedMessage, EntityUid.Invalid, hideChat: false, recordReplay: true, colorOverride: colorOverride); Logger.InfoS("SERVER", message); _adminLogger.Add(LogType.Chat, LogImpact.Low, $"Server announcement: {message}"); @@ -99,7 +97,7 @@ namespace Content.Server.Chat.Managers var wrappedMessage = Loc.GetString("chat-manager-send-admin-announcement-wrap-message", ("adminChannelName", Loc.GetString("chat-manager-admin-channel-name")), ("message", FormattedMessage.EscapeText(message))); - ChatMessageToMany(ChatChannel.Admin, message, wrappedMessage, default, false, clients); + ChatMessageToMany(ChatChannel.Admin, message, wrappedMessage, default, false, true, clients); _adminLogger.Add(LogType.Chat, LogImpact.Low, $"Admin announcement from {message}: {message}"); } @@ -110,7 +108,7 @@ namespace Content.Server.Chat.Managers return; } var wrappedMessage = Loc.GetString("chat-manager-send-hook-ooc-wrap-message", ("senderName", sender), ("message", FormattedMessage.EscapeText(message))); - ChatMessageToAll(ChatChannel.OOC, message, wrappedMessage); + ChatMessageToAll(ChatChannel.OOC, message, wrappedMessage, source: EntityUid.Invalid, hideChat: false, recordReplay: true); _adminLogger.Add(LogType.Chat, LogImpact.Low, $"Hook OOC from {sender}: {message}"); } @@ -176,7 +174,7 @@ namespace Content.Server.Chat.Managers } //TODO: player.Name color, this will need to change the structure of the MsgChatMessage - ChatMessageToAll(ChatChannel.OOC, message, wrappedMessage, colorOverride); + ChatMessageToAll(ChatChannel.OOC, message, wrappedMessage, EntityUid.Invalid, hideChat: false, recordReplay: true, colorOverride); _mommiLink.SendOOCMessage(player.Name, message); _adminLogger.Add(LogType.Chat, LogImpact.Low, $"OOC from {player:Player}: {message}"); } @@ -193,7 +191,7 @@ namespace Content.Server.Chat.Managers var wrappedMessage = Loc.GetString("chat-manager-send-admin-chat-wrap-message", ("adminChannelName", Loc.GetString("chat-manager-admin-channel-name")), ("playerName", player.Name), ("message", FormattedMessage.EscapeText(message))); - ChatMessageToMany(ChatChannel.Admin, message, wrappedMessage, default, false, clients.ToList()); + ChatMessageToMany(ChatChannel.Admin, message, wrappedMessage, default, false, true, clients.ToList()); _adminLogger.Add(LogType.Chat, $"Admin chat from {player:Player}: {message}"); } @@ -202,40 +200,32 @@ namespace Content.Server.Chat.Managers #region Utility - public void ChatMessageToOne(ChatChannel channel, string message, string wrappedMessage, EntityUid source, bool hideChat, INetChannel client, Color? colorOverride = null) + public void ChatMessageToOne(ChatChannel channel, string message, string wrappedMessage, EntityUid source, bool hideChat, INetChannel client, Color? colorOverride = null, bool recordReplay = false) { - var msg = new MsgChatMessage(); - msg.Channel = channel; - msg.Message = message; - msg.WrappedMessage = wrappedMessage; - msg.SenderEntity = source; - msg.HideChat = hideChat; - if (colorOverride != null) - { - msg.MessageColorOverride = colorOverride.Value; - } - _netManager.ServerSendMessage(msg, client); + var msg = new ChatMessage(channel, message, wrappedMessage, source, hideChat, colorOverride); + _netManager.ServerSendMessage(new MsgChatMessage() { Message = msg }, client); + + if (recordReplay) + _replay.QueueReplayMessage(msg); } - public void ChatMessageToMany(ChatChannel channel, string message, string wrappedMessage, EntityUid source, bool hideChat, IEnumerable clients, Color? colorOverride = null) + public void ChatMessageToMany(ChatChannel channel, string message, string wrappedMessage, EntityUid source, bool hideChat, bool recordReplay, IEnumerable clients, Color? colorOverride = null) + => ChatMessageToMany(channel, message, wrappedMessage, source, hideChat, recordReplay, clients.ToList(), colorOverride); + + public void ChatMessageToMany(ChatChannel channel, string message, string wrappedMessage, EntityUid source, bool hideChat, bool recordReplay, List clients, Color? colorOverride = null) { - var msg = new MsgChatMessage(); - msg.Channel = channel; - msg.Message = message; - msg.WrappedMessage = wrappedMessage; - msg.SenderEntity = source; - msg.HideChat = hideChat; - if (colorOverride != null) - { - msg.MessageColorOverride = colorOverride.Value; - } - _netManager.ServerSendToMany(msg, clients.ToList()); + var msg = new ChatMessage(channel, message, wrappedMessage, source, hideChat, colorOverride); + _netManager.ServerSendToMany(new MsgChatMessage() { Message = msg }, clients); + + if (recordReplay) + _replay.QueueReplayMessage(msg); } public void ChatMessageToManyFiltered(Filter filter, ChatChannel channel, string message, string wrappedMessage, EntityUid source, - bool hideChat, Color? colorOverride = null) + bool hideChat, bool recordReplay, Color? colorOverride = null) { - if (!filter.Recipients.Any()) return; + if (!recordReplay && !filter.Recipients.Any()) + return; var clients = new List(); foreach (var recipient in filter.Recipients) @@ -243,20 +233,16 @@ namespace Content.Server.Chat.Managers clients.Add(recipient.ConnectedClient); } - ChatMessageToMany(channel, message, wrappedMessage, source, hideChat, clients, colorOverride); + ChatMessageToMany(channel, message, wrappedMessage, source, hideChat, recordReplay, clients, colorOverride); } - public void ChatMessageToAll(ChatChannel channel, string message, string wrappedMessage, Color? colorOverride = null) + public void ChatMessageToAll(ChatChannel channel, string message, string wrappedMessage, EntityUid source, bool hideChat, bool recordReplay, Color? colorOverride = null) { - var msg = new MsgChatMessage(); - msg.Channel = channel; - msg.Message = message; - msg.WrappedMessage = wrappedMessage; - if (colorOverride != null) - { - msg.MessageColorOverride = colorOverride.Value; - } - _netManager.ServerSendToAll(msg); + var msg = new ChatMessage(channel, message, wrappedMessage, source, hideChat, colorOverride); + _netManager.ServerSendToAll(new MsgChatMessage() { Message = msg }); + + if (recordReplay) + _replay.QueueReplayMessage(msg); } public bool MessageCharacterLimit(IPlayerSession? player, string message) diff --git a/Content.Server/Chat/Managers/IChatManager.cs b/Content.Server/Chat/Managers/IChatManager.cs index a38005cebd..cbf5814c36 100644 --- a/Content.Server/Chat/Managers/IChatManager.cs +++ b/Content.Server/Chat/Managers/IChatManager.cs @@ -24,11 +24,14 @@ namespace Content.Server.Chat.Managers void SendAdminAnnouncement(string message); void ChatMessageToOne(ChatChannel channel, string message, string wrappedMessage, EntityUid source, bool hideChat, - INetChannel client, Color? colorOverride = null); - void ChatMessageToMany(ChatChannel channel, string message, string wrappedMessage, EntityUid source, bool hideChat, + INetChannel client, Color? colorOverride = null, bool recordReplay = false); + + void ChatMessageToMany(ChatChannel channel, string message, string wrappedMessage, EntityUid source, bool hideChat, bool recordReplay, IEnumerable clients, Color? colorOverride = null); - void ChatMessageToManyFiltered(Filter filter, ChatChannel channel, string message, string wrappedMessage, EntityUid source, bool hideChat, Color? colorOverride); - void ChatMessageToAll(ChatChannel channel, string message, string wrappedMessage, Color? colorOverride = null); + + void ChatMessageToManyFiltered(Filter filter, ChatChannel channel, string message, string wrappedMessage, EntityUid source, bool hideChat, bool recordReplay, Color? colorOverride); + + void ChatMessageToAll(ChatChannel channel, string message, string wrappedMessage, EntityUid source, bool hideChat, bool recordReplay, Color? colorOverride = null); bool MessageCharacterLimit(IPlayerSession player, string message); } diff --git a/Content.Server/Chat/Systems/ChatSystem.cs b/Content.Server/Chat/Systems/ChatSystem.cs index 843b0fc011..499784fe3b 100644 --- a/Content.Server/Chat/Systems/ChatSystem.cs +++ b/Content.Server/Chat/Systems/ChatSystem.cs @@ -1,24 +1,22 @@ using System.Linq; using System.Text; -using System.Text.RegularExpressions; using Content.Server.Administration.Logs; using Content.Server.Administration.Managers; using Content.Server.Chat.Managers; using Content.Server.GameTicking; using Content.Server.Ghost.Components; -using Content.Server.Mind.Components; +using Content.Server.MobState; using Content.Server.Players; using Content.Server.Popups; -using Content.Server.Radio.EntitySystems; using Content.Server.Station.Components; using Content.Server.Station.Systems; -using Content.Server.MobState; using Content.Shared.ActionBlocker; using Content.Shared.CCVar; using Content.Shared.Chat; using Content.Shared.Database; using Content.Shared.IdentityManagement; using Content.Shared.Inventory; +using Content.Shared.Radio; using Robust.Server.GameObjects; using Robust.Server.Player; using Robust.Shared.Audio; @@ -29,9 +27,8 @@ using Robust.Shared.Player; using Robust.Shared.Players; using Robust.Shared.Prototypes; using Robust.Shared.Random; +using Robust.Shared.Replays; using Robust.Shared.Utility; -using Content.Server.Speech.EntitySystems; -using Content.Shared.Radio; namespace Content.Server.Chat.Systems; @@ -41,6 +38,7 @@ namespace Content.Server.Chat.Systems; /// public sealed partial class ChatSystem : SharedChatSystem { + [Dependency] private readonly IReplayRecordingManager _replay = default!; [Dependency] private readonly IConfigurationManager _configurationManager = default!; [Dependency] private readonly IChatManager _chatManager = default!; [Dependency] private readonly IChatSanitizationManager _sanitizer = default!; @@ -119,7 +117,7 @@ public sealed partial class ChatSystem : SharedChatSystem /// The player doing the speaking /// The name to use for the speaking entity. Usually this should just be modified via . If this is set, the event will not get raised. public void TrySendInGameICMessage(EntityUid source, string message, InGameICChatType desiredType, bool hideChat, bool hideGlobalGhostChat = false, - IConsoleShell? shell = null, IPlayerSession? player = null, string? nameOverride = null) + IConsoleShell? shell = null, IPlayerSession? player = null, string? nameOverride = null, bool checkRadioPrefix = true) { if (HasComp(source)) { @@ -157,7 +155,7 @@ public sealed partial class ChatSystem : SharedChatSystem switch (desiredType) { case InGameICChatType.Speak: - SendEntitySpeak(source, message, hideChat, hideGlobalGhostChat, nameOverride); + SendEntitySpeak(source, message, hideChat, hideGlobalGhostChat, nameOverride, checkRadioPrefix); break; case InGameICChatType.Whisper: SendEntityWhisper(source, message, hideChat, hideGlobalGhostChat, null, nameOverride); @@ -211,7 +209,7 @@ public sealed partial class ChatSystem : SharedChatSystem bool playSound = true, SoundSpecifier? announcementSound = null, Color? colorOverride = null) { var wrappedMessage = Loc.GetString("chat-manager-sender-announcement-wrap-message", ("sender", sender), ("message", FormattedMessage.EscapeText(message))); - _chatManager.ChatMessageToAll(ChatChannel.Radio, message, wrappedMessage, colorOverride); + _chatManager.ChatMessageToAll(ChatChannel.Radio, message, wrappedMessage, default, false, true, colorOverride); if (playSound) { SoundSystem.Play(announcementSound?.GetSound() ?? DefaultAnnouncementSound, Filter.Broadcast(), AudioParams.Default.WithVolume(-2f)); @@ -243,7 +241,7 @@ public sealed partial class ChatSystem : SharedChatSystem var filter = _stationSystem.GetInStation(stationDataComp); - _chatManager.ChatMessageToManyFiltered(filter, ChatChannel.Radio, message, wrappedMessage, source, false, colorOverride); + _chatManager.ChatMessageToManyFiltered(filter, ChatChannel.Radio, message, wrappedMessage, source, false, true, colorOverride); if (playDefaultSound) { @@ -257,12 +255,18 @@ public sealed partial class ChatSystem : SharedChatSystem #region Private API - private void SendEntitySpeak(EntityUid source, string originalMessage, bool hideChat, bool hideGlobalGhostChat, string? nameOverride) + private void SendEntitySpeak(EntityUid source, string originalMessage, bool hideChat, bool hideGlobalGhostChat, string? nameOverride, bool checkRadioPrefix) { if (!_actionBlocker.CanSpeak(source)) return; - var (message, channel) = GetRadioPrefix(source, originalMessage); + RadioChannelPrototype? channel = null; + string message; + + if (checkRadioPrefix) + (message, channel) = GetRadioPrefix(source, originalMessage); + else + message = originalMessage; if (channel != null) { @@ -331,6 +335,15 @@ public sealed partial class ChatSystem : SharedChatSystem } name = FormattedMessage.EscapeText(name); + + var wrappedMessage = Loc.GetString("chat-manager-entity-whisper-wrap-message", + ("entityName", name), ("message", FormattedMessage.EscapeText(message))); + + + var wrappedobfuscatedMessage = Loc.GetString("chat-manager-entity-whisper-wrap-message", + ("entityName", name), ("message", FormattedMessage.EscapeText(obfuscatedMessage))); + + foreach (var (session, data) in GetRecipients(source, VoiceRange)) { if (session.AttachedEntity is not { Valid: true } playerEntity) @@ -340,22 +353,13 @@ public sealed partial class ChatSystem : SharedChatSystem continue; // Won't get logged to chat, and ghosts are too far away to see the pop-up, so we just won't send it to them. if (data.Range <= WhisperRange) - { - var wrappedMessage = Loc.GetString("chat-manager-entity-whisper-wrap-message", - ("entityName", name), ("message", FormattedMessage.EscapeText(message))); - _chatManager.ChatMessageToOne(ChatChannel.Whisper, message, wrappedMessage, source, data.HideChatOverride ?? hideChat, session.ConnectedClient); - } else - { - var wrappedMessage = Loc.GetString("chat-manager-entity-whisper-wrap-message", - ("entityName", name), ("message", FormattedMessage.EscapeText(obfuscatedMessage))); - - _chatManager.ChatMessageToOne(ChatChannel.Whisper, obfuscatedMessage, wrappedMessage, source, data.HideChatOverride ?? hideChat, - session.ConnectedClient); - } + _chatManager.ChatMessageToOne(ChatChannel.Whisper, obfuscatedMessage, wrappedobfuscatedMessage, source, data.HideChatOverride ?? hideChat, session.ConnectedClient); } + _replay.QueueReplayMessage(new ChatMessage(ChatChannel.Whisper, message, wrappedMessage, source, hideChat)); + var ev = new EntitySpokeEvent(source, message, channel, obfuscatedMessage); RaiseLocalEvent(source, ev, true); @@ -421,7 +425,7 @@ public sealed partial class ChatSystem : SharedChatSystem _adminLogger.Add(LogType.Chat, LogImpact.Low, $"Dead chat from {player:Player}: {message}"); } - _chatManager.ChatMessageToMany(ChatChannel.Dead, message, wrappedMessage, source, hideChat, clients.ToList()); + _chatManager.ChatMessageToMany(ChatChannel.Dead, message, wrappedMessage, source, hideChat, false, clients.ToList()); } #endregion @@ -438,6 +442,8 @@ public sealed partial class ChatSystem : SharedChatSystem var entHideChat = data.HideChatOverride ?? (hideChat || hideGlobalGhostChat && data.Observer && data.Range < 0); _chatManager.ChatMessageToOne(channel, message, wrappedMessage, source, entHideChat, session.ConnectedClient); } + + _replay.QueueReplayMessage(new ChatMessage(channel, message, wrappedMessage, source, hideChat)); } /// diff --git a/Content.Server/GameTicking/GameTicker.cs b/Content.Server/GameTicking/GameTicker.cs index ec21e456ef..89e2d3c504 100644 --- a/Content.Server/GameTicking/GameTicker.cs +++ b/Content.Server/GameTicking/GameTicker.cs @@ -85,10 +85,7 @@ namespace Content.Server.GameTicking private void SendServerMessage(string message) { - var msg = new MsgChatMessage(); - msg.Channel = ChatChannel.Server; - msg.Message = message; - IoCManager.Resolve().ServerSendToAll(msg); + _chatManager.ChatMessageToAll(ChatChannel.Server, message, "", default, false, true); } public override void Update(float frameTime) diff --git a/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs b/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs index e587810a12..fc45058211 100644 --- a/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs @@ -306,6 +306,7 @@ public sealed class ZombieRuleSystem : GameRuleSystem _initialInfectedNames.Add(inCharacterName, mind.Session.Name); // I went all the way to ChatManager.cs and all i got was this lousy T-shirt + // You got a free T-shirt!?!? _chatManager.ChatMessageToOne(Shared.Chat.ChatChannel.Server, message, wrappedMessage, default, false, mind.Session.ConnectedClient, Color.Plum); } diff --git a/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs b/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs index 0afb003fdb..8d192c4de0 100644 --- a/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs +++ b/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs @@ -143,6 +143,6 @@ public sealed class RadioDeviceSystem : EntitySystem ("originalName", nameEv.Name)); var hideGlobalGhostChat = true; // log to chat so people can identity the speaker/source, but avoid clogging ghost chat if there are many radios - _chat.TrySendInGameICMessage(uid, args.Message, InGameICChatType.Speak, false, nameOverride: name, hideGlobalGhostChat:hideGlobalGhostChat); + _chat.TrySendInGameICMessage(uid, args.Message, InGameICChatType.Speak, false, nameOverride: name, hideGlobalGhostChat:hideGlobalGhostChat, checkRadioPrefix: false); } } diff --git a/Content.Server/Radio/EntitySystems/RadioSystem.cs b/Content.Server/Radio/EntitySystems/RadioSystem.cs index a5dd5a2f2b..27c39c168d 100644 --- a/Content.Server/Radio/EntitySystems/RadioSystem.cs +++ b/Content.Server/Radio/EntitySystems/RadioSystem.cs @@ -1,22 +1,23 @@ using Content.Server.Chat.Systems; using Content.Server.Radio.Components; -using Content.Server.Speech; using Content.Server.VoiceMask; using Content.Shared.Chat; using Content.Shared.IdentityManagement; using Content.Shared.Radio; using Robust.Server.GameObjects; using Robust.Shared.Network; +using Robust.Shared.Replays; using Robust.Shared.Utility; namespace Content.Server.Radio.EntitySystems; /// -/// This system handles radio speakers and microphones (which together form a hand-held radio). +/// This system handles intrinsic radios and the general process of converting radio messages into chat messages. /// public sealed class RadioSystem : EntitySystem { [Dependency] private readonly INetManager _netMan = default!; + [Dependency] private readonly IReplayRecordingManager _replay = default!; // set used to prevent radio feedback loops. private readonly HashSet _messages = new(); @@ -56,13 +57,12 @@ public sealed class RadioSystem : EntitySystem name = FormattedMessage.EscapeText(name); // most radios are relayed to chat, so lets parse the chat message beforehand - var chatMsg = new MsgChatMessage - { - Channel = ChatChannel.Radio, - Message = message, - //Square brackets are added here to avoid issues with escaping - WrappedMessage = Loc.GetString("chat-radio-message-wrap", ("color", channel.Color), ("channel", $"\\[{channel.LocalizedName}\\]"), ("name", name), ("message", FormattedMessage.EscapeText(message))) - }; + var chat = new ChatMessage( + ChatChannel.Radio, + message, + Loc.GetString("chat-radio-message-wrap", ("color", channel.Color), ("channel", $"\\[{channel.LocalizedName}\\]"), ("name", name), ("message", FormattedMessage.EscapeText(message))), + EntityUid.Invalid); + var chatMsg = new MsgChatMessage { Message = chat }; var ev = new RadioReceiveEvent(message, source, channel, chatMsg); var attemptEv = new RadioReceiveAttemptEvent(message, source, channel); @@ -84,6 +84,7 @@ public sealed class RadioSystem : EntitySystem RaiseLocalEvent(radio.Owner, ev); } + _replay.QueueReplayMessage(chat); _messages.Remove(message); } } diff --git a/Content.Shared/Chat/MsgChatMessage.cs b/Content.Shared/Chat/MsgChatMessage.cs index 980d5578dd..4497ef8f7f 100644 --- a/Content.Shared/Chat/MsgChatMessage.cs +++ b/Content.Shared/Chat/MsgChatMessage.cs @@ -2,9 +2,35 @@ using JetBrains.Annotations; using Lidgren.Network; using Robust.Shared.Network; using Robust.Shared.Serialization; +using Robust.Shared.Utility; +using System.IO; namespace Content.Shared.Chat { + [Serializable, NetSerializable] + public sealed class ChatMessage + { + public ChatChannel Channel; + public string Message; + public string WrappedMessage; + public EntityUid SenderEntity; + public bool HideChat; + public Color? MessageColorOverride; + + [NonSerialized] + public bool Read; + + public ChatMessage(ChatChannel channel, string message, string wrappedMessage, EntityUid source, bool hideChat = false, Color? colorOverride = null) + { + Channel = channel; + Message = message; + WrappedMessage = wrappedMessage; + SenderEntity = source; + HideChat = hideChat; + MessageColorOverride = colorOverride; + } + } + /// /// Sent from server to client to notify the client about a new chat message. /// @@ -13,73 +39,21 @@ namespace Content.Shared.Chat { public override MsgGroups MsgGroup => MsgGroups.Command; - /// - /// The channel the message is on. This can also change whether certain params are used. - /// - public ChatChannel Channel { get; set; } - - /// - /// The actual message contents. - /// - public string Message { get; set; } = string.Empty; - - /// - /// Modified message with some wrapping text. E.g. 'Joe says: "HELP!"' - /// - public string WrappedMessage { get; set; } = string.Empty; - - /// - /// The sending entity. - /// Only applies to , and . - /// - public EntityUid SenderEntity { get; set; } - - /// - /// The override color of the message - /// - public Color MessageColorOverride { get; set; } = Color.Transparent; - - public bool HideChat { get; set; } - + public ChatMessage Message = default!; public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer serializer) { - Channel = (ChatChannel) buffer.ReadInt16(); - Message = buffer.ReadString(); - WrappedMessage = buffer.ReadString(); - - switch (Channel) - { - case ChatChannel.Local: - case ChatChannel.Whisper: - case ChatChannel.Dead: - case ChatChannel.Admin: - case ChatChannel.Emotes: - SenderEntity = buffer.ReadEntityUid(); - break; - } - MessageColorOverride = buffer.ReadColor(); - HideChat = buffer.ReadBoolean(); + var length = buffer.ReadVariableInt32(); + using var stream = buffer.ReadAlignedMemory(length); + serializer.DeserializeDirect(stream, out Message); } public override void WriteToBuffer(NetOutgoingMessage buffer, IRobustSerializer serializer) { - buffer.Write((short)Channel); - buffer.Write(Message); - buffer.Write(WrappedMessage); - - switch (Channel) - { - case ChatChannel.Local: - case ChatChannel.Whisper: - case ChatChannel.Dead: - case ChatChannel.Admin: - case ChatChannel.Emotes: - buffer.Write(SenderEntity); - break; - } - buffer.Write(MessageColorOverride); - buffer.Write(HideChat); + var stream = new MemoryStream(); + serializer.SerializeDirect(stream, Message); + buffer.WriteVariableInt32((int) stream.Length); + buffer.Write(stream.AsSpan()); } } }