diff --git a/src/Patches/Gameplay/UI/Chat/ChatPatch.cs b/src/Patches/Gameplay/UI/Chat/ChatPatch.cs
index 3ed599b..0670f90 100644
--- a/src/Patches/Gameplay/UI/Chat/ChatPatch.cs
+++ b/src/Patches/Gameplay/UI/Chat/ChatPatch.cs
@@ -19,6 +19,9 @@ internal static class ChatPatch
internal const string COMMAND_POSTFIX_ID = "IsCommand";
+ ///
+ /// Removes all chat bubbles from the chat.
+ ///
internal static void ClearChat()
{
if (!HudManager.InstanceExists)
@@ -28,6 +31,9 @@ internal static class ChatPatch
HudManager.Instance.Chat.chatBubblePool.ReclaimAll();
}
+ ///
+ /// Removes all player chat bubbles from the chat, excluding command bubbles.
+ ///
internal static void ClearPlayerChats()
{
if (!HudManager.InstanceExists)
@@ -46,6 +52,75 @@ internal static class ChatPatch
HudManager.Instance.Chat.AlignAllBubbles();
}
+ ///
+ /// Contains cached information about censored chat bubbles, keyed by the associated chat bubble instance.
+ ///
+ private static readonly Dictionary _censoredChatBubbleInfo = [];
+
+ ///
+ /// Censors all active player chat bubbles by anonymizing player information and obscuring chat text.
+ ///
+ internal static void CensorPlayerChats()
+ {
+ if (!HudManager.InstanceExists)
+ return;
+
+ UncensorPlayerChats();
+
+ foreach (var obj in HudManager.Instance.Chat.chatBubblePool.activeChildren.ToArray())
+ {
+ var chatBubble = obj.GetComponent();
+ if (chatBubble != null)
+ {
+ if (_censoredChatBubbleInfo.ContainsKey(chatBubble)) continue;
+ if (chatBubble.NameText.text.EndsWith(COMMAND_POSTFIX_ID)) continue;
+
+ _censoredChatBubbleInfo[chatBubble] = (chatBubble.PoolIndex, chatBubble.playerInfo, chatBubble.NameText.text, chatBubble.TextArea.text);
+
+ // Anonymize player info and obscure chat text
+ chatBubble.playerInfo = null;
+ chatBubble.NameText.SetText("???".ToColor(Color.white));
+ chatBubble.TextArea.SetText(new string('*', chatBubble.TextArea.text.Length).ToColor(Color.white));
+ chatBubble.Player.ResetCosmetics();
+ chatBubble.Player.SetBodyColor(15);
+ chatBubble.ColorBlindName.SetText(string.Empty);
+ }
+ }
+
+ HudManager.Instance.Chat.AlignAllBubbles();
+ }
+
+ ///
+ /// Restores all previously censored player chat bubbles to display their original, uncensored content in the chat
+ /// UI.
+ ///
+ internal static void UncensorPlayerChats()
+ {
+ if (!HudManager.InstanceExists)
+ return;
+
+ foreach (var (chatBubble, (index, info, name, msg)) in _censoredChatBubbleInfo)
+ {
+ if (chatBubble == null) continue;
+
+ // Ensure the chat bubble matches the cached pool index before restoring
+ if (index != chatBubble.PoolIndex) continue;
+
+ // Restore original player info and chat text
+ chatBubble.playerInfo = info;
+ chatBubble.NameText.SetText(name);
+ chatBubble.TextArea.SetText(msg);
+ chatBubble.Player.UpdateFromPlayerData(chatBubble.playerInfo, PlayerOutfitType.Default, PlayerMaterial.MaskType.ScrollingUI, false);
+ chatBubble.AlignChildren();
+ }
+
+ _censoredChatBubbleInfo.Clear();
+ HudManager.Instance.Chat.AlignAllBubbles();
+ }
+
+ ///
+ /// Removes all command related chat bubbles from the chat, preserving player chat bubbles.
+ ///
internal static void ClearCommands()
{
if (!HudManager.InstanceExists)
diff --git a/src/Patches/Gameplay/UI/MeetingHudPatch.cs b/src/Patches/Gameplay/UI/MeetingHudPatch.cs
index f81f12b..01d5f34 100644
--- a/src/Patches/Gameplay/UI/MeetingHudPatch.cs
+++ b/src/Patches/Gameplay/UI/MeetingHudPatch.cs
@@ -17,6 +17,11 @@ internal static class MeetingHudPatch
[HarmonyPostfix]
private static void MeetingHud_Start_Postfix(MeetingHud __instance)
{
+ if (BAUConfigs.ChatInGameplay.Value && PlayerControl.LocalPlayer.IsAlive())
+ {
+ ChatPatch.UncensorPlayerChats();
+ }
+
if (__instance == null || __instance.playerStates == null)
return;
@@ -91,9 +96,9 @@ internal static class MeetingHudPatch
Logger_.LogHeader("Meeting Has Ended");
// Clear chat when meeting ends if gameplay chat is enabled
- if (BAUConfigs.ChatInGameplay.Value && !GameState.IsFreePlay && PlayerControl.LocalPlayer.IsAlive())
+ if (BAUConfigs.ChatInGameplay.Value && PlayerControl.LocalPlayer.IsAlive())
{
- ChatPatch.ClearPlayerChats();
+ ChatPatch.CensorPlayerChats();
}
}
}
\ No newline at end of file