From cc95920bdd391b5968ffbec3f931d93fa05190ac Mon Sep 17 00:00:00 2001 From: vanx Date: Mon, 29 Dec 2025 01:52:31 +0300 Subject: [PATCH 1/3] omg omg --- Content.Client/Chat/UI/SpeechBubble.cs | 25 +++++++++++++++++++ .../Systems/Chat/ChatUIController.cs | 7 +++--- Content.Server/_White/TTS/TTSSystem.cs | 2 +- Content.Shared/Chat/SharedChatSystem.cs | 16 ++++++++++++ .../_White/CCVar/WhiteCVars.Chat.cs | 6 +++++ 5 files changed, 52 insertions(+), 4 deletions(-) diff --git a/Content.Client/Chat/UI/SpeechBubble.cs b/Content.Client/Chat/UI/SpeechBubble.cs index 66db93a8269..6dfd3bf56b3 100644 --- a/Content.Client/Chat/UI/SpeechBubble.cs +++ b/Content.Client/Chat/UI/SpeechBubble.cs @@ -52,6 +52,12 @@ public enum SpeechType : byte /// public const float SpeechMaxWidth = 256; + /// + /// White Dream; + /// Max amount of characters in a speech bubble + /// + public int SingleBubbleCharLimit => ConfigManager.GetCVar(WhiteCVars.SingleBubbleCharLimit); + private readonly EntityUid _senderEntity; private float _timeLeft = TotalTime; @@ -222,6 +228,21 @@ protected FormattedMessage ExtractAndFormatSpeechSubstring(ChatMessage message, return FormatSpeech(SharedChatSystem.GetStringInsideTag(message, tag), fontColor); } + public ChatMessage TruncateWrappedMessage(ChatMessage message, int maxLength) + { + var text = SharedChatSystem.GetStringInsideTag(message, "BubbleContent"); + + if (text.Length <= maxLength) + return message; + + text = text[..maxLength].TrimEnd(' ', '.', ',', ';', ':', '!', '?') + "..."; + + var newmsg = SharedChatSystem.SetStringInsideTag(message,"BubbleContent", text); + + message.WrappedMessage = newmsg; + + return message; + } } public sealed class TextSpeechBubble : SpeechBubble @@ -238,6 +259,8 @@ protected override Control BuildBubble(ChatMessage message, string speechStyleCl MaxWidth = SpeechMaxWidth, }; + message = TruncateWrappedMessage(message, SingleBubbleCharLimit); // White Dream + label.SetMessage(FormatSpeech(message.WrappedMessage, fontColor, "Bedstead")); // WWDP EDIT var panel = new PanelContainer @@ -268,6 +291,8 @@ protected override Control BuildBubble(ChatMessage message, string speechStyleCl MaxWidth = SpeechMaxWidth }; + message = TruncateWrappedMessage(message, SingleBubbleCharLimit); // White Dream + label.SetMessage(FormatSpeech(SharedChatSystem.GetStringInsideTag(message, "BubbleContent"), fontColor, "Bedstead")); // WWDP EDIT // LESS USELESS ONE LINER FUNCS PLS var unfanciedPanel = new PanelContainer diff --git a/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs b/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs index 6193ba339f0..ff660ecc1af 100644 --- a/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs +++ b/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs @@ -15,6 +15,7 @@ using Content.Client.UserInterface.Screens; using Content.Client.UserInterface.Systems.Chat.Widgets; using Content.Client.UserInterface.Systems.Gameplay; +using Content.Shared._White.CCVar; using Content.Shared.Administration; using Content.Shared.CCVar; using Content.Shared.Chat; @@ -107,7 +108,7 @@ public sealed class ChatUIController : UIController /// /// The max amount of chars allowed to fit in a single speech bubble. /// - private const int SingleBubbleCharLimit = 100; + private int SingleBubbleCharLimit => _config.GetCVar(WhiteCVars.SingleBubbleCharLimit); // White Dream moved to WhiteCvars /// /// Base queue delay each speech bubble has. @@ -117,12 +118,12 @@ public sealed class ChatUIController : UIController /// /// Factor multiplied by speech bubble char length to add to delay. /// - private const float BubbleDelayFactor = 0.8f / SingleBubbleCharLimit; + private const float BubbleDelayFactor = 0.8f / 100; // White Dream /// /// The max amount of speech bubbles over a single entity at once. /// - private const int SpeechBubbleCap = 4; + private int SpeechBubbleCap => _config.GetCVar(WhiteCVars.SpeechBubbleCap); // White Dream moved to WhiteCvars private LayoutContainer _speechBubbleRoot = default!; diff --git a/Content.Server/_White/TTS/TTSSystem.cs b/Content.Server/_White/TTS/TTSSystem.cs index 11a50c89cc5..4413fd46fc3 100644 --- a/Content.Server/_White/TTS/TTSSystem.cs +++ b/Content.Server/_White/TTS/TTSSystem.cs @@ -24,7 +24,7 @@ public sealed partial class TTSSystem : EntitySystem [Dependency] private readonly SharedTransformSystem _xforms = default!; [Dependency] private readonly LanguageSystem _language = default!; - private const int MaxMessageChars = 100 * 2; // same as SingleBubbleCharLimit * 2 + private int MaxMessageChars => _cfg.GetCVar(WhiteCVars.SingleBubbleCharLimit) * 2; // White dream moved to cvar private bool _isEnabled; public override void Initialize() diff --git a/Content.Shared/Chat/SharedChatSystem.cs b/Content.Shared/Chat/SharedChatSystem.cs index f0b09ba1b04..848fdc9e42c 100644 --- a/Content.Shared/Chat/SharedChatSystem.cs +++ b/Content.Shared/Chat/SharedChatSystem.cs @@ -359,6 +359,22 @@ public static string GetStringInsideTag(ChatMessage message, string tag) return rawmsg.Substring(tagStart, tagEnd - tagStart); } + // White Dream edit start + // Returns a message with a string inside tag removed and replaced + public static string SetStringInsideTag(ChatMessage message, string tag, string strInsert) + { + var rawmsg = message.WrappedMessage; + var tagStart = rawmsg.IndexOf($"[{tag}]"); + var tagEnd = rawmsg.IndexOf($"[/{tag}]"); + if (tagStart < 0 || tagEnd < 0) + return rawmsg; + tagStart += tag.Length + 2; + rawmsg = rawmsg.Remove(tagStart, tagEnd - tagStart); + rawmsg = rawmsg.Insert(tagStart, $"{strInsert}"); + return rawmsg; + } + // White Dream edit end + // WD EDIT START - Moved from ClatUIController /// /// Returns the chat name color for a mob diff --git a/Content.Shared/_White/CCVar/WhiteCVars.Chat.cs b/Content.Shared/_White/CCVar/WhiteCVars.Chat.cs index bf326afddca..521d59eb2ba 100644 --- a/Content.Shared/_White/CCVar/WhiteCVars.Chat.cs +++ b/Content.Shared/_White/CCVar/WhiteCVars.Chat.cs @@ -12,4 +12,10 @@ public sealed partial class WhiteCVars public static readonly CVarDef ColoredBubbleChat = CVarDef.Create("chat.colored_bubble", true, CVar.CLIENTONLY | CVar.ARCHIVE); + + public static readonly CVarDef SingleBubbleCharLimit = + CVarDef.Create("chat.bubble_character_limit", 43, CVar.SERVER | CVar.REPLICATED); + + public static readonly CVarDef SpeechBubbleCap = + CVarDef.Create("chat.bubble_max_count", 1, CVar.SERVER | CVar.REPLICATED); } From f636bc5e88c976b4fa0d9e5c5bfb28ab9d64461c Mon Sep 17 00:00:00 2001 From: vanx Date: Mon, 29 Dec 2025 02:23:45 +0300 Subject: [PATCH 2/3] robust cap --- .../UserInterface/Systems/Chat/ChatUIController.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs b/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs index ff660ecc1af..f2a46c1bca7 100644 --- a/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs +++ b/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs @@ -462,8 +462,10 @@ private void CreateSpeechBubble(EntityUid entity, SpeechBubbleData speechData) if (existing.Count > SpeechBubbleCap) { // Get the oldest to start fading fast. - var last = existing[0]; - last.FadeNow(); + // White Dream edit - Get all of the older ones + var lastBubbles = existing[..^SpeechBubbleCap]; + foreach (var last in lastBubbles) + last.FadeNow(); } } From ac2c10d9775186c5e95e917556cf74d0c49881ae Mon Sep 17 00:00:00 2001 From: vanx Date: Wed, 31 Dec 2025 15:27:10 +0300 Subject: [PATCH 3/3] client + validation --- Content.Client/Chat/UI/SpeechBubble.cs | 22 ++++++++++++--- .../Systems/Chat/ChatUIController.cs | 27 +++++++++++++++---- Content.Server/_White/TTS/TTSSystem.cs | 2 +- Content.Shared/Chat/SharedChatSystem.cs | 4 +-- .../_White/CCVar/WhiteCVars.Chat.cs | 4 +-- 5 files changed, 46 insertions(+), 13 deletions(-) diff --git a/Content.Client/Chat/UI/SpeechBubble.cs b/Content.Client/Chat/UI/SpeechBubble.cs index 6dfd3bf56b3..0f6fca6798c 100644 --- a/Content.Client/Chat/UI/SpeechBubble.cs +++ b/Content.Client/Chat/UI/SpeechBubble.cs @@ -56,7 +56,21 @@ public enum SpeechType : byte /// White Dream; /// Max amount of characters in a speech bubble /// - public int SingleBubbleCharLimit => ConfigManager.GetCVar(WhiteCVars.SingleBubbleCharLimit); + public int SingleBubbleCharLimit + { + get + { + var cvar = ConfigManager.GetCVar(WhiteCVars.SingleBubbleCharLimit); + + if (cvar <= 0) + { + Logger.Error("Local CVar chat.bubble_character_limit is set to 0 or lower"); + cvar = 1; + } + + return cvar; + } + } private readonly EntityUid _senderEntity; @@ -228,6 +242,7 @@ protected FormattedMessage ExtractAndFormatSpeechSubstring(ChatMessage message, return FormatSpeech(SharedChatSystem.GetStringInsideTag(message, tag), fontColor); } + // WWDP EDIT START public ChatMessage TruncateWrappedMessage(ChatMessage message, int maxLength) { var text = SharedChatSystem.GetStringInsideTag(message, "BubbleContent"); @@ -243,6 +258,7 @@ public ChatMessage TruncateWrappedMessage(ChatMessage message, int maxLength) return message; } + // WWDP EDIT END } public sealed class TextSpeechBubble : SpeechBubble @@ -259,7 +275,7 @@ protected override Control BuildBubble(ChatMessage message, string speechStyleCl MaxWidth = SpeechMaxWidth, }; - message = TruncateWrappedMessage(message, SingleBubbleCharLimit); // White Dream + message = TruncateWrappedMessage(message, SingleBubbleCharLimit); // WWDP edit label.SetMessage(FormatSpeech(message.WrappedMessage, fontColor, "Bedstead")); // WWDP EDIT @@ -291,7 +307,7 @@ protected override Control BuildBubble(ChatMessage message, string speechStyleCl MaxWidth = SpeechMaxWidth }; - message = TruncateWrappedMessage(message, SingleBubbleCharLimit); // White Dream + message = TruncateWrappedMessage(message, SingleBubbleCharLimit); // WWDP edit label.SetMessage(FormatSpeech(SharedChatSystem.GetStringInsideTag(message, "BubbleContent"), fontColor, "Bedstead")); // WWDP EDIT // LESS USELESS ONE LINER FUNCS PLS diff --git a/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs b/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs index f2a46c1bca7..182e9dd3bb9 100644 --- a/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs +++ b/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs @@ -108,7 +108,7 @@ public sealed class ChatUIController : UIController /// /// The max amount of chars allowed to fit in a single speech bubble. /// - private int SingleBubbleCharLimit => _config.GetCVar(WhiteCVars.SingleBubbleCharLimit); // White Dream moved to WhiteCvars + private int SingleBubbleCharLimit => _config.GetCVar(WhiteCVars.SingleBubbleCharLimit); // WWDP moved to WhiteCvars /// /// Base queue delay each speech bubble has. @@ -118,12 +118,28 @@ public sealed class ChatUIController : UIController /// /// Factor multiplied by speech bubble char length to add to delay. /// - private const float BubbleDelayFactor = 0.8f / 100; // White Dream + private const float BubbleDelayFactor = 0.8f / 100; // WWDP edit + // WWDP edit start /// /// The max amount of speech bubbles over a single entity at once. /// - private int SpeechBubbleCap => _config.GetCVar(WhiteCVars.SpeechBubbleCap); // White Dream moved to WhiteCvars + private int SpeechBubbleCap + { + get + { + var cvar = _config.GetCVar(WhiteCVars.SpeechBubbleCap); + + if (cvar <= 0) + { + Logger.Error("Local CVar chat.bubble_max_count is set to 0 or lower"); + cvar = 1; + } + + return cvar; + } + } + // WWDP edit end private LayoutContainer _speechBubbleRoot = default!; @@ -461,11 +477,12 @@ private void CreateSpeechBubble(EntityUid entity, SpeechBubbleData speechData) if (existing.Count > SpeechBubbleCap) { - // Get the oldest to start fading fast. - // White Dream edit - Get all of the older ones + // WWDP edit start + // Get all of the older ones var lastBubbles = existing[..^SpeechBubbleCap]; foreach (var last in lastBubbles) last.FadeNow(); + // WWDP edit end } } diff --git a/Content.Server/_White/TTS/TTSSystem.cs b/Content.Server/_White/TTS/TTSSystem.cs index 4413fd46fc3..dc8140bafef 100644 --- a/Content.Server/_White/TTS/TTSSystem.cs +++ b/Content.Server/_White/TTS/TTSSystem.cs @@ -24,7 +24,7 @@ public sealed partial class TTSSystem : EntitySystem [Dependency] private readonly SharedTransformSystem _xforms = default!; [Dependency] private readonly LanguageSystem _language = default!; - private int MaxMessageChars => _cfg.GetCVar(WhiteCVars.SingleBubbleCharLimit) * 2; // White dream moved to cvar + private int MaxMessageChars => _cfg.GetCVar(WhiteCVars.SingleBubbleCharLimit) * 2; private bool _isEnabled; public override void Initialize() diff --git a/Content.Shared/Chat/SharedChatSystem.cs b/Content.Shared/Chat/SharedChatSystem.cs index 848fdc9e42c..f72d582a35f 100644 --- a/Content.Shared/Chat/SharedChatSystem.cs +++ b/Content.Shared/Chat/SharedChatSystem.cs @@ -359,7 +359,7 @@ public static string GetStringInsideTag(ChatMessage message, string tag) return rawmsg.Substring(tagStart, tagEnd - tagStart); } - // White Dream edit start + // WWDP edit start // Returns a message with a string inside tag removed and replaced public static string SetStringInsideTag(ChatMessage message, string tag, string strInsert) { @@ -373,7 +373,7 @@ public static string SetStringInsideTag(ChatMessage message, string tag, string rawmsg = rawmsg.Insert(tagStart, $"{strInsert}"); return rawmsg; } - // White Dream edit end + // WWDP edit end // WD EDIT START - Moved from ClatUIController /// diff --git a/Content.Shared/_White/CCVar/WhiteCVars.Chat.cs b/Content.Shared/_White/CCVar/WhiteCVars.Chat.cs index 521d59eb2ba..264f9189e30 100644 --- a/Content.Shared/_White/CCVar/WhiteCVars.Chat.cs +++ b/Content.Shared/_White/CCVar/WhiteCVars.Chat.cs @@ -14,8 +14,8 @@ public sealed partial class WhiteCVars CVarDef.Create("chat.colored_bubble", true, CVar.CLIENTONLY | CVar.ARCHIVE); public static readonly CVarDef SingleBubbleCharLimit = - CVarDef.Create("chat.bubble_character_limit", 43, CVar.SERVER | CVar.REPLICATED); + CVarDef.Create("chat.bubble_character_limit", 43, CVar.CLIENT | CVar.ARCHIVE); public static readonly CVarDef SpeechBubbleCap = - CVarDef.Create("chat.bubble_max_count", 1, CVar.SERVER | CVar.REPLICATED); + CVarDef.Create("chat.bubble_max_count", 1, CVar.CLIENT | CVar.ARCHIVE); }