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