diff --git a/Content.Client/Chat/ChatBox.cs b/Content.Client/Chat/ChatBox.cs index eb37c86703..dbe24f1d76 100644 --- a/Content.Client/Chat/ChatBox.cs +++ b/Content.Client/Chat/ChatBox.cs @@ -35,6 +35,8 @@ namespace Content.Client.Chat public bool ReleaseFocusOnEnter { get; set; } = true; + public bool ClearOnEnter { get; set; } = true; + public ChatBox() { /*MarginLeft = -475.0f; @@ -166,12 +168,18 @@ namespace Content.Client.Chat private void Input_OnTextEntered(LineEdit.LineEditEventArgs args) { + // We set it there to true so it's set to false by TextSubmitted.Invoke if necessary + ClearOnEnter = true; + if (!string.IsNullOrWhiteSpace(args.Text)) { TextSubmitted?.Invoke(this, args.Text); } - Input.Clear(); + if (ClearOnEnter) + { + Input.Clear(); + } if (ReleaseFocusOnEnter) { diff --git a/Content.Client/Chat/ChatManager.cs b/Content.Client/Chat/ChatManager.cs index 21be7769ae..61dbdc28f1 100644 --- a/Content.Client/Chat/ChatManager.cs +++ b/Content.Client/Chat/ChatManager.cs @@ -1,17 +1,21 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using Content.Client.Interfaces.Chat; using Content.Shared.Chat; using Robust.Client.Console; using Robust.Client.Interfaces.Graphics.ClientEye; using Robust.Client.Interfaces.UserInterface; +using Robust.Client.Player; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; using Robust.Shared.GameObjects; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.Network; using Robust.Shared.IoC; +using Robust.Shared.Localization; using Robust.Shared.Log; using Robust.Shared.Maths; +using Robust.Shared.Network; using Robust.Shared.Timing; using Robust.Shared.Utility; @@ -45,6 +49,11 @@ namespace Content.Client.Chat /// private const int SpeechBubbleCap = 4; + /// + /// The max amount of characters an entity can send in one message + /// + private int _maxMessageLength = 1000; + private const char ConCmdSlash = '/'; private const char OOCAlias = '['; private const char MeAlias = '@'; @@ -89,11 +98,15 @@ namespace Content.Client.Chat public void Initialize() { _netManager.RegisterNetMessage(MsgChatMessage.NAME, _onChatMessage); + _netManager.RegisterNetMessage(ChatMaxMsgLengthMessage.NAME, _onMaxLengthReceived); _speechBubbleRoot = new LayoutContainer(); LayoutContainer.SetAnchorPreset(_speechBubbleRoot, LayoutContainer.LayoutPreset.Wide); _userInterfaceManager.StateRoot.AddChild(_speechBubbleRoot); _speechBubbleRoot.SetPositionFirst(); + + // When connexion is achieved, request the max chat message length + _netManager.Connected += new EventHandler(RequestMaxLength); } public void FrameUpdate(FrameEventArgs delta) @@ -213,6 +226,15 @@ namespace Content.Client.Chat if (string.IsNullOrWhiteSpace(text)) return; + // Check if message is longer than the character limit + if (text.Length > _maxMessageLength) + { + string locWarning = Loc.GetString("Your message exceeds {0} character limit", _maxMessageLength); + _currentChatBox?.AddLine(locWarning, ChatChannel.Server, Color.Orange); + _currentChatBox.ClearOnEnter = false; // The text shouldn't be cleared if it hasn't been sent + return; + } + switch (text[0]) { case ConCmdSlash: @@ -345,6 +367,17 @@ namespace Content.Client.Chat } } + private void _onMaxLengthReceived(ChatMaxMsgLengthMessage msg) + { + _maxMessageLength = msg.MaxMessageLength; + } + + private void RequestMaxLength(object sender, NetChannelArgs args) + { + ChatMaxMsgLengthMessage msg = _netManager.CreateNetMessage(); + _netManager.ClientSendMessage(msg); + } + private void AddSpeechBubble(MsgChatMessage msg, SpeechBubble.SpeechType speechType) { if (!_entityManager.TryGetEntity(msg.SenderEntity, out var entity)) diff --git a/Content.Server/Chat/ChatManager.cs b/Content.Server/Chat/ChatManager.cs index 1a035fbb5c..a6e0296b04 100644 --- a/Content.Server/Chat/ChatManager.cs +++ b/Content.Server/Chat/ChatManager.cs @@ -5,7 +5,9 @@ using Content.Server.Interfaces; using Content.Server.Interfaces.Chat; using Content.Shared.Chat; using Content.Shared.GameObjects.EntitySystems; +using NFluidsynth; using Robust.Server.Console; +using Robust.Server.Interfaces.GameObjects; using Robust.Server.Interfaces.Player; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.Network; @@ -19,8 +21,18 @@ namespace Content.Server.Chat /// internal sealed class ChatManager : IChatManager { + /// + /// The maximum length a player-sent message can be sent + /// + public int MaxMessageLength = 1000; + private const int VoiceRange = 7; // how far voice goes in world units + /// + /// The message displayed to the player when it exceeds the chat character limit + /// + private const string MaxLengthExceededMessage = "Your message exceeded {0} character limit"; + #pragma warning disable 649 [Dependency] private readonly IEntitySystemManager _entitySystemManager; [Dependency] private readonly IServerNetManager _netManager; @@ -33,6 +45,12 @@ namespace Content.Server.Chat public void Initialize() { _netManager.RegisterNetMessage(MsgChatMessage.NAME); + _netManager.RegisterNetMessage(ChatMaxMsgLengthMessage.NAME, _onMaxLengthRequest); + + // Tell all the connected players the chat's character limit + var msg = _netManager.CreateNetMessage(); + msg.MaxMessageLength = MaxMessageLength; + _netManager.ServerSendToAll(msg); } public void DispatchServerAnnouncement(string message) @@ -69,6 +87,17 @@ namespace Content.Server.Chat return; } + // Get entity's PlayerSession + IPlayerSession playerSession = source.GetComponent().playerSession; + + // Check if message exceeds the character limit if the sender is a player + if (playerSession != null) + if (message.Length > MaxMessageLength) + { + DispatchServerMessage(playerSession, Loc.GetString(MaxLengthExceededMessage, MaxMessageLength)); + return; + } + var pos = source.Transform.GridPosition; var clients = _playerManager.GetPlayersInRange(pos, VoiceRange).Select(p => p.ConnectedClient); @@ -90,6 +119,17 @@ namespace Content.Server.Chat return; } + // Check if entity is a player + IPlayerSession playerSession = source.GetComponent().playerSession; + + // Check if message exceeds the character limit + if (playerSession != null) + if (action.Length > MaxMessageLength) + { + DispatchServerMessage(playerSession, Loc.GetString(MaxLengthExceededMessage, MaxMessageLength)); + return; + } + var pos = source.Transform.GridPosition; var clients = _playerManager.GetPlayersInRange(pos, VoiceRange).Select(p => p.ConnectedClient); @@ -103,6 +143,13 @@ namespace Content.Server.Chat public void SendOOC(IPlayerSession player, string message) { + // Check if message exceeds the character limi + if (message.Length > MaxMessageLength) + { + DispatchServerMessage(player, Loc.GetString(MaxLengthExceededMessage, MaxMessageLength)); + return; + } + var msg = _netManager.CreateNetMessage(); msg.Channel = ChatChannel.OOC; msg.Message = message; @@ -114,6 +161,13 @@ namespace Content.Server.Chat public void SendDeadChat(IPlayerSession player, string message) { + // Check if message exceeds the character limit + if (message.Length > MaxMessageLength) + { + DispatchServerMessage(player, Loc.GetString(MaxLengthExceededMessage, MaxMessageLength)); + return; + } + var clients = _playerManager.GetPlayersBy(x => x.AttachedEntity != null && x.AttachedEntity.HasComponent()).Select(p => p.ConnectedClient);; var msg = _netManager.CreateNetMessage(); @@ -126,7 +180,14 @@ namespace Content.Server.Chat public void SendAdminChat(IPlayerSession player, string message) { - if(!_conGroupController.CanCommand(player, "asay")) + // Check if message exceeds the character limit + if (message.Length > MaxMessageLength) + { + DispatchServerMessage(player, Loc.GetString(MaxLengthExceededMessage, MaxMessageLength)); + return; + } + + if (!_conGroupController.CanCommand(player, "asay")) { SendOOC(player, message); return; @@ -149,5 +210,12 @@ namespace Content.Server.Chat msg.MessageWrap = $"OOC: (D){sender}: {{0}}"; _netManager.ServerSendToAll(msg); } + + private void _onMaxLengthRequest(ChatMaxMsgLengthMessage msg) + { + var response = _netManager.CreateNetMessage(); + response.MaxMessageLength = MaxMessageLength; + _netManager.ServerSendMessage(response, msg.MsgChannel); + } } } diff --git a/Content.Shared/Chat/ChatMaxMsgLengthMessage.cs b/Content.Shared/Chat/ChatMaxMsgLengthMessage.cs new file mode 100644 index 0000000000..6e183ebca6 --- /dev/null +++ b/Content.Shared/Chat/ChatMaxMsgLengthMessage.cs @@ -0,0 +1,39 @@ +using Lidgren.Network; +using Robust.Shared.Interfaces.Network; +using Robust.Shared.Network; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Content.Shared.Chat +{ + /// + /// This message is sent by the server to let clients know what is the chat's character limit for this server. + /// It is first sent by the client as a request + /// + public sealed class ChatMaxMsgLengthMessage : NetMessage + { + #region REQUIRED + + public const MsgGroups GROUP = MsgGroups.Command; + public const string NAME = nameof(ChatMaxMsgLengthMessage); + public ChatMaxMsgLengthMessage(INetChannel channel) : base(NAME, GROUP) { } + + #endregion + + /// + /// The max length a player-sent message can get + /// + public int MaxMessageLength { get; set; } + + public override void ReadFromBuffer(NetIncomingMessage buffer) + { + MaxMessageLength = buffer.ReadInt32(); + } + + public override void WriteToBuffer(NetOutgoingMessage buffer) + { + buffer.Write(MaxMessageLength); + } + } +}