using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.InputSystem; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")] [assembly: AssemblyCompany("NiceChat")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.2.8.0")] [assembly: AssemblyInformationalVersion("1.2.8+4c75d1accc36435e7d9457468e2b00c4c86d6e92")] [assembly: AssemblyProduct("NiceChat")] [assembly: AssemblyTitle("NiceChat")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.2.7.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace NiceChat { public interface IServerVar : IDisposable { static List AllServerVars; void TryRegister(); static IServerVar() { AllServerVars = new List(); } } public class ServerVar : IServerVar, IDisposable where T : IEquatable { public delegate void ReadFromReader(FastBufferReader reader, out T1 value); private T value; private Action writeValue; private ReadFromReader readValue; public string Id { get; init; } public T Value { get { return value; } set { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsServer) { if (!EqualityComparer.Default.Equals(this.value, value)) { this.value = value; if (NetworkManager.Singleton.IsConnectedClient) { Plugin.log.LogDebug((object)$"[{Id}] Broadcasting new value \"{value}\" to all clients"); FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(128, (Allocator)2, -1); writeValue(val, value); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessageToAll(Id, val, (NetworkDelivery)3); } } } else { Plugin.log.LogWarning((object)("Client tried to set ServerVar \"" + Id + "\"")); } } } public ServerVar(string id, Action write, ReadFromReader read, T defaultValue = default(T)) { value = defaultValue; Id = (string.IsNullOrEmpty(id) ? "taffyko.NiceChat" : ("taffyko.NiceChat." + id)); writeValue = write; readValue = read; IServerVar.AllServerVars.Add(this); ((IServerVar)this).TryRegister(); Plugin.cleanupActions.Add(Dispose); } private void Handler(ulong senderClientId, FastBufferReader messagePayload) { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) if (senderClientId != NetworkManager.Singleton.LocalClientId) { if (NetworkManager.Singleton.IsServer) { FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(128, (Allocator)2, -1); writeValue(val, value); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage(Id, senderClientId, val, (NetworkDelivery)3); Plugin.log.LogDebug((object)$"[{Id}] Responded to request from {senderClientId} with value: \"{value}\""); } else { readValue(messagePayload, out value); Plugin.log.LogDebug((object)$"[{Id}] Received update from {senderClientId} with value: \"{value}\""); } } } private void OnClientConnectedCallback(ulong clientId) { if (clientId == NetworkManager.Singleton.LocalClientId) { ((IServerVar)this).TryRegister(); } } public void Dispose() { Plugin.log.LogDebug((object)("[" + Id + "] Disposed ServerVar")); if ((Object)(object)NetworkManager.Singleton != (Object)null) { NetworkManager.Singleton.OnClientConnectedCallback -= OnClientConnectedCallback; if (NetworkManager.Singleton.IsConnectedClient) { NetworkManager.Singleton.CustomMessagingManager.UnregisterNamedMessageHandler(Id); } } IServerVar.AllServerVars.Remove(this); } void IServerVar.TryRegister() { //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Expected O, but got Unknown //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Expected O, but got Unknown //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Expected O, but got Unknown //IL_0121: Unknown result type (might be due to invalid IL or missing references) Plugin.log.LogDebug((object)$"[{Id}] Attempting to register. NetworkManager: {(Object)(object)NetworkManager.Singleton != (Object)null}, Connected: {(Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsConnectedClient}"); if (!((Object)(object)NetworkManager.Singleton != (Object)null)) { return; } NetworkManager.Singleton.OnClientConnectedCallback += OnClientConnectedCallback; if (NetworkManager.Singleton.IsConnectedClient) { NetworkManager.Singleton.CustomMessagingManager.RegisterNamedMessageHandler(Id, new HandleNamedMessageDelegate(Handler)); NetworkManager.Singleton.CustomMessagingManager.RegisterNamedMessageHandler(Id, new HandleNamedMessageDelegate(Handler)); NetworkManager.Singleton.CustomMessagingManager.RegisterNamedMessageHandler(Id, new HandleNamedMessageDelegate(Handler)); Plugin.log.LogDebug((object)("[" + Id + "] Registered ServerVar")); if (!NetworkManager.Singleton.IsServer) { NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage(Id, 0uL, new FastBufferWriter(0, (Allocator)2, -1), (NetworkDelivery)3); Plugin.log.LogDebug((object)$"[{Id}] Sent request from {NetworkManager.Singleton.LocalClientId} to {0uL}"); } } } } [HarmonyPatch] internal class NetworkingPatches { [HarmonyPatch(typeof(StartOfRound), "Awake")] [HarmonyPostfix] private static void StartOfRound_Awake_Postfix() { foreach (IServerVar allServerVar in IServerVar.AllServerVars) { allServerVar.TryRegister(); } } } [BepInPlugin("taffyko.NiceChat", "NiceChat", "1.2.8")] public class Plugin : BaseUnityPlugin { private delegate bool ParseConfigValue(string input, out T output); public const string modGUID = "taffyko.NiceChat"; public const string modName = "NiceChat"; public const string modVersion = "1.2.8"; private readonly Harmony harmony = new Harmony("taffyko.NiceChat"); public static ManualLogSource log = null; internal static List cleanupActions = new List(); public static int MaxMessageHistory { get; private set; } public static float DefaultFontSize { get; private set; } public static bool EnlargeChatWindow { get; private set; } public static int CharacterLimit { get; private set; } public static float MessageRange { get; private set; } public static bool HearDeadPlayers { get; private set; } public static bool EnableTimestamps { get; private set; } public static bool TagMessageStatus { get; private set; } public static bool ShowScrollbar { get; private set; } public static float FadeOpacity { get; private set; } public static float FadeTimeAfterMessage { get; private set; } public static float FadeTimeAfterOwnMessage { get; private set; } public static float FadeTimeAfterUnfocused { get; private set; } public static bool GuiFadeFix { get; private set; } public static bool SpectatorChatHideOtherHudElements { get; private set; } public static Color InputTextColor { get; private set; } private void Awake() { ConfigInit(); log = Logger.CreateLogSource("NiceChat"); log.LogInfo((object)"Loading taffyko.NiceChat"); ServerVars.characterLimit = new ServerVar("characterLimit", delegate(FastBufferWriter writer, int v) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) ((FastBufferWriter)(ref writer)).WriteValueSafe(ref v, default(ForPrimitives)); }, delegate(FastBufferReader r, out int v) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) ((FastBufferReader)(ref r)).ReadValueSafe(ref v, default(ForPrimitives)); }, 49); ServerVars.hearDeadPlayers = new ServerVar("hearDeadPlayers", delegate(FastBufferWriter writer, bool v) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) ((FastBufferWriter)(ref writer)).WriteValueSafe(ref v, default(ForPrimitives)); }, delegate(FastBufferReader r, out bool v) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) ((FastBufferReader)(ref r)).ReadValueSafe(ref v, default(ForPrimitives)); }, defaultValue: false); ServerVars.messageRange = new ServerVar("messageRange", delegate(FastBufferWriter writer, float v) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) ((FastBufferWriter)(ref writer)).WriteValueSafe(ref v, default(ForPrimitives)); }, delegate(FastBufferReader r, out float v) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) ((FastBufferReader)(ref r)).ReadValueSafe(ref v, default(ForPrimitives)); }, 25f); ServerVars.modVersion = new ServerVar("", delegate(FastBufferWriter writer, string v) { ((FastBufferWriter)(ref writer)).WriteValueSafe(v, false); }, delegate(FastBufferReader r, out string v) { ((FastBufferReader)(ref r)).ReadValueSafe(ref v, false); }); harmony.PatchAll(Assembly.GetExecutingAssembly()); } private void OnDestroy() { } private void ConfigInit() { //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) ((BaseUnityPlugin)this).Config.Bind("README", "README", "", "All config values are text-based, as a workaround to make it possible for default values to change in future updates.\r\n\r\nSee https://github.com/taffyko/LCNiceChat/issues/3 for more information.\r\n\r\nIf you enter an invalid value, it will change back to \"default\" when the game starts."); Color vanillaValue = default(Color); ColorUtility.TryParseHtmlString("#585ed1d4", ref vanillaValue); ConfEntry("Chat", "MaxMessageHistory", 15, "Set the maximum number of messages in history before the oldest messages begin to disappear (NOTE: Long message histories can negatively impact performance)", int.TryParse, 4); ConfEntry("Chat", "DefaultFontSize", 11f, "Font size.", float.TryParse, 13f); ConfEntry("Chat", "EnlargeChatWindow", defaultValue: true, "Increases the size of the chat area.", bool.TryParse); ConfEntry("Chat", "CharacterLimit", 1000, "Maximum character limit for messages in your lobby.", int.TryParse, hostControlled: true); ConfEntry("Chat", "MessageRange", 25f, "Maximum distance from which messages between living players can be heard without a walkie-talkie.", float.TryParse, 25f, hostControlled: true); ConfEntry("Chat", "HearDeadPlayers", defaultValue: false, "When enabled, allows living players to hear messages from dead players.", bool.TryParse, hostControlled: true); ConfEntry("Chat", "EnableTimestamps", defaultValue: true, "Adds timestamps to messages whenever the clock is visible.", bool.TryParse); ConfEntry("Chat", "TagMessageStatus", defaultValue: false, "Adds tags like *WALKIE* and *DEAD* to messages in addition to the color-coding.", bool.TryParse); ConfEntry("Chat", "ShowScrollbar", defaultValue: true, "If false, the scrollbar is permanently hidden even when the chat input is focused.", bool.TryParse); ConfEntry("Chat", "InputTextColor", Color.white, "Default color of text in the input field", (ParseConfigValue)ColorUtility.TryParseHtmlString, vanillaValue, hostControlled: false); ConfEntry("Fade Behaviour", "FadeOpacity", 0f, "The opacity of the chat when it fades from inactivity. 0.0 makes the chat fade away completely.", float.TryParse, 0.2f); ConfEntry("Fade Behaviour", "FadeTimeAfterMessage", 4f, "The amount of seconds before the chat fades out after a message is sent by another player.", float.TryParse, 4f); ConfEntry("Fade Behaviour", "FadeTimeAfterOwnMessage", 2f, "The amount of seconds before the chat fades out after a message is sent by you.", float.TryParse, 2f); ConfEntry("Fade Behaviour", "FadeTimeAfterUnfocused", 1f, "The amount of seconds before the chat fades out after the chat input is unfocused.", float.TryParse, 1f); ConfEntry("Compatibility", "GuiFadeFix", defaultValue: true, "Workaround to prevent other UI elements (like the indicator from LethalLoudnessMeter) from also fading out when the chat fades", bool.TryParse); ConfEntry("Compatibility", "SpectatorChatHideOtherHudElements", defaultValue: true, "For spectator chat, ensures that only the chat window is shown, and that irrelevant HUD elements (inventory/etc.) are hidden.", bool.TryParse); } private static bool NoopParse(string input, out string output) { output = input; return true; } private void ConfEntry(string category, string name, T defaultValue, string description, ParseConfigValue tryParse, bool hostControlled = false) { ConfEntryInternal(category, name, defaultValue, description, tryParse, hostControlled); } private void ConfEntry(string category, string name, T defaultValue, string description, ParseConfigValue tryParse, T vanillaValue, bool hostControlled = false) { ConfEntryInternal(category, name, defaultValue, description, tryParse, hostControlled, ConfEntryToString(vanillaValue)); } private void ConfEntryInternal(string category, string name, T defaultValue, string description, ParseConfigValue tryParse, bool hostControlled = false, string? vanillaValueText = null) { PropertyInfo property = typeof(Plugin).GetProperty(name); string text = "[default: " + ConfEntryToString(defaultValue) + "]\n" + description; text += (hostControlled ? "\n(This setting is overridden by the lobby host)" : "\n(This setting's effect applies to you only)"); if (vanillaValueText != null) { text = text + "\n(The original value of this setting in the base-game is " + vanillaValueText + ")"; } ConfigEntry config = ((BaseUnityPlugin)this).Config.Bind(category, name, "default", text); if (string.IsNullOrEmpty(config.Value)) { config.Value = "default"; } T output; bool flag = tryParse(config.Value, out output) && config.Value != "default"; property.SetValue(null, (T)(flag ? ((object)output) : ((object)defaultValue))); if (!flag) { config.Value = "default"; } EventHandler loadConfig = delegate { T output2; bool flag2 = tryParse(config.Value, out output2) && config.Value != "default"; property.SetValue(null, (T)(flag2 ? ((object)output2) : ((object)defaultValue))); }; config.SettingChanged += loadConfig; cleanupActions.Add(delegate { config.SettingChanged -= loadConfig; property.SetValue(null, defaultValue); }); } private string ConfEntryToString(object? value) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) if (value == null) { return "null"; } Type type = value.GetType(); if (type == typeof(float)) { return $"{(float)value:0.0#####}"; } if (type == typeof(Color)) { return "#" + ColorUtility.ToHtmlStringRGBA((Color)value); } return value.ToString(); } } public static class ServerVars { public static ServerVar characterLimit; public static ServerVar hearDeadPlayers; public static ServerVar messageRange; public static ServerVar modVersion; } [HarmonyPatch] internal class Patches { public class CustomFields { public DateTime? connectTime; public bool networkReady; public InputAction? shiftAction; public InputAction? scrollAction; public TMP_Text? chatText; public TMP_InputField? chatTextField; public TextMeshProUGUI? chatTextFieldGui; public float previousChatTextHeight; public float previousScrollPosition; public RectTransform? hudBottomLeftCorner; public RectTransform? chatContainer; public RectTransform? chatTextBgRect; public RectTransform? chatTextFieldRect; public RectTransform? chatTextRect; public RectTransform? scrollContainerRect; public CanvasGroup? scrollbarCanvasGroup; public ScrollRect? scroll; public Scrollbar? scrollbar; public Action? restoreHiddenHudElementsAction; public List cleanupActions = new List(); } private record MessageContext(int senderId, bool walkie, bool senderDead); public static Dictionary fields = new Dictionary(); public static (HUDElement, float originalOpacity)[] hiddenElements = new(HUDElement, float)[0]; private static MethodInfo MethodInfo_GetChatMessageNameOpeningTag = typeof(Patches).GetMethod("GetChatMessageNameOpeningTag"); private static MethodInfo MethodInfo_GetChatMessageNameClosingTag = typeof(Patches).GetMethod("GetChatMessageNameClosingTag"); private static MethodInfo stringEqual = typeof(string).GetMethod("op_Equality", new Type[2] { typeof(string), typeof(string) }); private static MessageContext? messageContext = null; private static MethodInfo MethodInfo_Vector3_Distance = typeof(Vector3).GetMethod("Distance"); private static MethodInfo MethodInfo_CanHearPreflight = typeof(Patches).GetMethod("CanHearPreflight"); private static float timeAtLastCheck = 0f; private static MethodInfo getCharacterLimit = typeof(Patches).GetMethod("GetCharacterLimit"); private static FieldInfo FieldInfo_isPlayerDead = typeof(PlayerControllerB).GetField("isPlayerDead"); private static bool IsLocalPlayer(PlayerControllerB __instance) { return (Object)(object)__instance == (Object)(object)StartOfRound.Instance?.localPlayerController; } [HarmonyPatch(typeof(PlayerControllerB), "Awake")] [HarmonyPostfix] private static void Player_Awake(PlayerControllerB __instance) { reload(__instance); } [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPostfix] private static void Player_Update(PlayerControllerB __instance) { //IL_02c8: Unknown result type (might be due to invalid IL or missing references) //IL_0397: Unknown result type (might be due to invalid IL or missing references) //IL_03b1: Unknown result type (might be due to invalid IL or missing references) //IL_03cb: Unknown result type (might be due to invalid IL or missing references) //IL_03e5: Unknown result type (might be due to invalid IL or missing references) //IL_032d: Unknown result type (might be due to invalid IL or missing references) //IL_0347: Unknown result type (might be due to invalid IL or missing references) //IL_0361: Unknown result type (might be due to invalid IL or missing references) //IL_037b: Unknown result type (might be due to invalid IL or missing references) //IL_0834: Unknown result type (might be due to invalid IL or missing references) //IL_0839: Unknown result type (might be due to invalid IL or missing references) //IL_084f: Unknown result type (might be due to invalid IL or missing references) //IL_0854: Unknown result type (might be due to invalid IL or missing references) //IL_0869: Unknown result type (might be due to invalid IL or missing references) //IL_0873: Unknown result type (might be due to invalid IL or missing references) //IL_088e: Unknown result type (might be due to invalid IL or missing references) //IL_0898: Unknown result type (might be due to invalid IL or missing references) //IL_089d: Unknown result type (might be due to invalid IL or missing references) //IL_0438: Unknown result type (might be due to invalid IL or missing references) //IL_043d: Unknown result type (might be due to invalid IL or missing references) //IL_044a: Expected O, but got Unknown //IL_045d: Unknown result type (might be due to invalid IL or missing references) //IL_046d: Unknown result type (might be due to invalid IL or missing references) //IL_0487: Unknown result type (might be due to invalid IL or missing references) //IL_04a1: Unknown result type (might be due to invalid IL or missing references) //IL_04bd: Unknown result type (might be due to invalid IL or missing references) //IL_04c2: Unknown result type (might be due to invalid IL or missing references) //IL_04cd: Unknown result type (might be due to invalid IL or missing references) //IL_04d5: Unknown result type (might be due to invalid IL or missing references) //IL_04f4: Unknown result type (might be due to invalid IL or missing references) //IL_0503: Unknown result type (might be due to invalid IL or missing references) //IL_052d: Unknown result type (might be due to invalid IL or missing references) //IL_0539: Unknown result type (might be due to invalid IL or missing references) //IL_0545: Unknown result type (might be due to invalid IL or missing references) //IL_0551: Unknown result type (might be due to invalid IL or missing references) //IL_0599: Unknown result type (might be due to invalid IL or missing references) //IL_059e: Unknown result type (might be due to invalid IL or missing references) //IL_0646: Unknown result type (might be due to invalid IL or missing references) //IL_064b: Unknown result type (might be due to invalid IL or missing references) //IL_0658: Expected O, but got Unknown //IL_0688: Unknown result type (might be due to invalid IL or missing references) //IL_0694: Unknown result type (might be due to invalid IL or missing references) //IL_06aa: Unknown result type (might be due to invalid IL or missing references) //IL_06c0: Unknown result type (might be due to invalid IL or missing references) //IL_06f8: Unknown result type (might be due to invalid IL or missing references) //IL_0707: Unknown result type (might be due to invalid IL or missing references) //IL_072a: Unknown result type (might be due to invalid IL or missing references) //IL_0734: Unknown result type (might be due to invalid IL or missing references) //IL_0739: Unknown result type (might be due to invalid IL or missing references) //IL_0744: Unknown result type (might be due to invalid IL or missing references) //IL_0758: Unknown result type (might be due to invalid IL or missing references) //IL_0764: Unknown result type (might be due to invalid IL or missing references) //IL_078d: Unknown result type (might be due to invalid IL or missing references) //IL_079c: Unknown result type (might be due to invalid IL or missing references) //IL_07ac: Unknown result type (might be due to invalid IL or missing references) //IL_07ca: Unknown result type (might be due to invalid IL or missing references) //IL_08e1: Unknown result type (might be due to invalid IL or missing references) //IL_08fb: Unknown result type (might be due to invalid IL or missing references) //IL_0900: Unknown result type (might be due to invalid IL or missing references) //IL_096e: Unknown result type (might be due to invalid IL or missing references) //IL_0973: Unknown result type (might be due to invalid IL or missing references) //IL_09d2: Unknown result type (might be due to invalid IL or missing references) //IL_09a2: Unknown result type (might be due to invalid IL or missing references) //IL_0a06: Unknown result type (might be due to invalid IL or missing references) //IL_0a0b: Unknown result type (might be due to invalid IL or missing references) //IL_0a42: Unknown result type (might be due to invalid IL or missing references) //IL_0a47: Unknown result type (might be due to invalid IL or missing references) //IL_0abc: Unknown result type (might be due to invalid IL or missing references) //IL_0ac1: Unknown result type (might be due to invalid IL or missing references) //IL_0a6e: Unknown result type (might be due to invalid IL or missing references) //IL_0a73: Unknown result type (might be due to invalid IL or missing references) //IL_0a8f: Unknown result type (might be due to invalid IL or missing references) //IL_0a94: Unknown result type (might be due to invalid IL or missing references) reload(__instance); if (!IsLocalPlayer(__instance) || (Object)(object)HUDManager.Instance == (Object)null) { return; } CustomFields customFields = fields[__instance]; if (__instance.isPlayerDead) { HUDManager hud = HUDManager.Instance; if (hud.HUDContainer.GetComponent().alpha == 0f) { hud.HUDAnimator.SetTrigger("revealHud"); hud.ClearControlTips(); } if (Plugin.SpectatorChatHideOtherHudElements && customFields.restoreHiddenHudElementsAction == null) { HUDElement[] array = (HUDElement[])Traverse.Create((object)hud).Field("HUDElements").GetValue(); Transform bottomMiddle = hud.HUDContainer.transform.Find("BottomMiddle"); (HUDElement item, float)[] hudElementsAlphas = array.Select((HUDElement item) => (item: item, Mathf.Max(item.targetAlpha, item.canvasGroup.alpha))).ToArray(); customFields.restoreHiddenHudElementsAction = delegate { (HUDElement, float)[] array3 = hudElementsAlphas; for (int i = 0; i < array3.Length; i++) { var (val12, num7) = array3[i]; if (val12 != hud.Chat) { hud.PingHUDElement(val12, 0f, num7, num7); } } if ((Object)(object)bottomMiddle != (Object)null) { ((Component)bottomMiddle).gameObject.SetActive(true); } }; HUDElement[] array2 = array; foreach (HUDElement val in array2) { if (val != hud.Chat) { hud.PingHUDElement(val, 0f, 0f, 0f); } } if ((Object)(object)bottomMiddle != (Object)null) { ((Component)bottomMiddle).gameObject.SetActive(false); } } } if (customFields.restoreHiddenHudElementsAction != null && (!__instance.isPlayerDead || !Plugin.SpectatorChatHideOtherHudElements)) { customFields.restoreHiddenHudElementsAction(); customFields.restoreHiddenHudElementsAction = null; } if ((Object)(object)customFields.chatTextField != (Object)null) { customFields.chatTextField.characterLimit = ServerVars.characterLimit.Value; customFields.chatTextField.lineLimit = 0; if (customFields.shiftAction != null && customFields.shiftAction.IsPressed()) { customFields.chatTextField.lineType = (LineType)2; } else { customFields.chatTextField.lineType = (LineType)1; } } if ((Object)(object)customFields.chatText != (Object)null) { customFields.chatText.fontSize = Plugin.DefaultFontSize; if (customFields.chatText.text.Length > customFields.chatText.maxVisibleCharacters) { int num2 = customFields.chatText.maxVisibleCharacters / 10; while (customFields.chatText.text.Length > customFields.chatText.maxVisibleCharacters - num2) { customFields.chatText.text = customFields.chatText.text.Remove(0, HUDManager.Instance.ChatMessageHistory[0].Length); HUDManager.Instance.ChatMessageHistory.RemoveAt(0); } } } if ((Object)(object)customFields.chatTextFieldGui != (Object)null) { ((Graphic)customFields.chatTextFieldGui).color = Plugin.InputTextColor; } if (!((Object)(object)customFields.chatText != (Object)null) || !((Object)(object)customFields.chatTextRect != (Object)null) || !((Object)(object)customFields.chatTextBgRect != (Object)null) || !((Object)(object)customFields.chatTextFieldRect != (Object)null)) { return; } if (Plugin.EnlargeChatWindow) { customFields.chatTextBgRect.anchorMin = new Vector2(0.35f, 0.5f); customFields.chatTextBgRect.anchorMax = new Vector2(0.8f, 0.5f); customFields.chatTextFieldRect.anchorMin = new Vector2(0.3f, 0.5f); customFields.chatTextFieldRect.anchorMax = new Vector2(0.8f, 0.5f); } else { customFields.chatTextBgRect.anchorMin = new Vector2(0.5f, 0.5f); customFields.chatTextBgRect.anchorMax = new Vector2(0.5f, 0.5f); customFields.chatTextFieldRect.anchorMin = new Vector2(0.5f, 0.5f); customFields.chatTextFieldRect.anchorMax = new Vector2(0.5f, 0.5f); } Rect rect; if ((Object)(object)customFields.scrollContainerRect == (Object)null) { Transform obj = ((Transform)customFields.chatTextBgRect).parent.Find("ChatScrollContainer"); customFields.scrollContainerRect = ((obj != null) ? ((Component)obj).GetComponent() : null); if ((Object)(object)customFields.scrollContainerRect == (Object)null) { GameObject val2 = new GameObject { name = "ChatScrollContainer" }; customFields.scrollContainerRect = val2.AddComponent(); customFields.scrollContainerRect.anchorMin = Vector2.zero; customFields.scrollContainerRect.anchorMax = Vector2.one; customFields.scrollContainerRect.offsetMin = new Vector2(0f, 40f); customFields.scrollContainerRect.offsetMax = new Vector2(0f, -3f); ((Transform)customFields.scrollContainerRect).SetParent((Transform)(object)customFields.chatTextBgRect, false); GameObject val3 = new GameObject { name = "ScrollMask" }; RectTransform val4 = val3.AddComponent(); val3.AddComponent().sprite = Sprite.Create(Texture2D.whiteTexture, new Rect(0f, 0f, 1f, 1f), new Vector2(0f, 0f)); val3.AddComponent().showMaskGraphic = false; ((Transform)val4).SetParent((Transform)(object)customFields.scrollContainerRect, false); val4.anchorMin = Vector2.zero; val4.anchorMax = Vector2.one; val4.offsetMin = Vector2.zero; val4.offsetMax = Vector2.zero; ((Transform)customFields.chatTextRect).SetParent((Transform)(object)val4, false); LayoutElement val5 = default(LayoutElement); ((Component)customFields.chatText).gameObject.TryGetComponent(ref val5); Object.Destroy((Object)(object)val5); val5 = ((Component)customFields.chatText).gameObject.AddComponent(); LayoutElement obj2 = val5; rect = val4.rect; obj2.minHeight = ((Rect)(ref rect)).height; customFields.chatText.alignment = (TextAlignmentOptions)1025; ContentSizeFitter val6 = default(ContentSizeFitter); ((Component)customFields.chatText).gameObject.TryGetComponent(ref val6); Object.Destroy((Object)(object)val6); ContentSizeFitter obj3 = ((Component)customFields.chatText).gameObject.AddComponent(); obj3.verticalFit = (FitMode)2; obj3.horizontalFit = (FitMode)0; customFields.scroll = val2.AddComponent(); customFields.scroll.content = customFields.chatTextRect; customFields.scroll.viewport = val4; customFields.scroll.vertical = true; customFields.scroll.horizontal = false; _ = customFields.scroll; _ = 0f; GameObject val7 = new GameObject { name = "Scrollbar" }; customFields.scrollbarCanvasGroup = val7.AddComponent(); RectTransform val8 = val7.AddComponent(); ((Transform)val8).SetParent((Transform)(object)customFields.scrollContainerRect, false); val8.anchorMin = new Vector2(1f, 0f); val8.anchorMax = Vector2.one; val8.offsetMin = new Vector2(-7f, 0f); val8.offsetMax = new Vector2(-5f, -5f); customFields.scrollbar = val7.AddComponent(); Image obj4 = val7.AddComponent(); obj4.sprite = Sprite.Create(Texture2D.whiteTexture, new Rect(0f, 0f, 1f, 1f), new Vector2(0f, 0f)); ((Graphic)obj4).color = new Color(0.34509805f, 0.36862746f, 0.81960785f, 10f / 51f); GameObject val9 = new GameObject { name = "ScrollbarHandle" }; RectTransform val10 = val9.AddComponent(); ((Transform)val10).SetParent((Transform)(object)val8, false); val10.offsetMin = Vector2.zero; val10.offsetMax = Vector2.zero; Image obj5 = val9.AddComponent(); obj5.sprite = Sprite.Create(Texture2D.whiteTexture, new Rect(0f, 0f, 1f, 1f), new Vector2(0f, 0f)); ((Graphic)obj5).color = Color.white; ((Graphic)obj5).color = new Color(0.34509805f, 0.36862746f, 0.81960785f, 0.4392157f); customFields.scrollbar.handleRect = val10; customFields.scrollbar.direction = (Direction)2; customFields.scroll.verticalScrollbar = customFields.scrollbar; } } LayoutElement val11 = default(LayoutElement); ((Component)customFields.chatText).gameObject.TryGetComponent(ref val11); if ((Object)(object)val11 != (Object)null) { RectTransform component = ((Component)((Transform)customFields.chatTextRect).parent).GetComponent(); LayoutElement obj6 = val11; rect = component.rect; obj6.minHeight = ((Rect)(ref rect)).height; RectTransform? chatTextRect = customFields.chatTextRect; rect = component.rect; chatTextRect.sizeDelta = new Vector2(((Rect)(ref rect)).width - 12f, customFields.chatTextRect.sizeDelta.y); ((Transform)customFields.chatTextRect).localPosition = Vector2.op_Implicit(new Vector2(0f, ((Transform)customFields.chatTextRect).localPosition.y)); } if (!((Object)(object)customFields.chatTextField != (Object)null)) { return; } if (customFields.chatTextField.isFocused && customFields.scrollAction != null && (Object)(object)customFields.scroll != (Object)null) { float num3 = customFields.scrollAction.ReadValue().y / 120f; float num4 = num3; rect = customFields.chatTextRect.rect; num3 = num4 / ((Rect)(ref rect)).height; num3 *= 30f; _ = customFields.scroll.verticalNormalizedPosition + num3; } if (!((Object)(object)customFields.scroll != (Object)null) || !((Object)(object)customFields.scrollbar != (Object)null) || !((Object)(object)customFields.scrollbarCanvasGroup != (Object)null)) { return; } float preferredHeight = customFields.chatText.preferredHeight; rect = customFields.scrollContainerRect.rect; if (preferredHeight < ((Rect)(ref rect)).height) { ((Graphic)((Component)customFields.scrollbar.handleRect).GetComponent()).color = new Color(0f, 0f, 0f, 0f); } else { ((Graphic)((Component)customFields.scrollbar.handleRect).GetComponent()).color = new Color(0.34509805f, 0.36862746f, 0.81960785f, 0.4392157f); } if (customFields.chatTextField.isFocused) { HUDManager.Instance.Chat.targetAlpha = 1f; rect = customFields.chatTextRect.rect; if (((Rect)(ref rect)).height != customFields.previousChatTextHeight) { if (customFields.chatTextField.isFocused) { float verticalNormalizedPosition = customFields.scroll.verticalNormalizedPosition; rect = customFields.chatTextRect.rect; if (verticalNormalizedPosition >= 100f / ((Rect)(ref rect)).height) { float num5 = (1f - customFields.previousScrollPosition) * customFields.previousChatTextHeight; rect = customFields.chatTextRect.rect; float num6 = ((Rect)(ref rect)).height - num5; _ = customFields.scroll; rect = customFields.chatTextRect.rect; _ = num6 / ((Rect)(ref rect)).height; goto IL_0ab5; } } _ = customFields.scroll; _ = 0f; goto IL_0ab5; } } else { _ = customFields.scroll; _ = 0f; } goto IL_0ae1; IL_0ab5: rect = customFields.chatTextRect.rect; customFields.previousChatTextHeight = ((Rect)(ref rect)).height; goto IL_0ae1; IL_0ae1: customFields.scrollbarCanvasGroup.alpha = ((Plugin.ShowScrollbar && customFields.chatTextField.isFocused) ? 1f : 0f); customFields.previousScrollPosition = customFields.scroll.verticalNormalizedPosition; } [HarmonyPatch(typeof(PlayerControllerB), "OnDestroy")] [HarmonyPostfix] private static void OnDestroy(PlayerControllerB __instance) { if (IsLocalPlayer(__instance) && fields.ContainsKey(__instance)) { foreach (Action cleanupAction in fields[__instance].cleanupActions) { cleanupAction(); } } fields.Remove(__instance); } private static void reload(PlayerControllerB __instance) { //IL_02dd: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Unknown result type (might be due to invalid IL or missing references) //IL_037a: Unknown result type (might be due to invalid IL or missing references) //IL_037f: Unknown result type (might be due to invalid IL or missing references) //IL_0386: Unknown result type (might be due to invalid IL or missing references) //IL_03dc: Unknown result type (might be due to invalid IL or missing references) //IL_03e2: Expected O, but got Unknown CustomFields f; if (!fields.ContainsKey(__instance)) { fields[__instance] = new CustomFields(); f = fields[__instance]; f.cleanupActions.Add(delegate { if (f.restoreHiddenHudElementsAction != null) { f.restoreHiddenHudElementsAction(); } }); } else { f = fields[__instance]; } if (!IsLocalPlayer(__instance)) { return; } if ((Object)(object)f.hudBottomLeftCorner == (Object)null) { ref RectTransform? hudBottomLeftCorner = ref f.hudBottomLeftCorner; Transform obj = HUDManager.Instance.HUDContainer.transform.Find("BottomLeftCorner"); hudBottomLeftCorner = (RectTransform?)(object)((obj is RectTransform) ? obj : null); } if (((NetworkBehaviour)__instance).NetworkManager.IsConnectedClient && ((NetworkBehaviour)__instance).NetworkManager.IsServer) { ServerVars.characterLimit.Value = Plugin.CharacterLimit; ServerVars.modVersion.Value = "1.2.8"; ServerVars.hearDeadPlayers.Value = Plugin.HearDeadPlayers; ServerVars.messageRange.Value = Plugin.MessageRange; } if ((Object)(object)f.chatTextField == (Object)null) { f.chatTextField = HUDManager.Instance?.chatTextField; } if ((Object)(object)f.chatText == (Object)null) { f.chatText = (TMP_Text?)(object)HUDManager.Instance?.chatText; } if ((Object)(object)f.chatTextFieldRect == (Object)null && (Object)(object)f.chatTextField != (Object)null) { ((Component)f.chatTextField).TryGetComponent(ref f.chatTextFieldRect); } if ((Object)(object)f.chatTextFieldGui == (Object)null && (Object)(object)f.chatTextField != (Object)null) { CustomFields customFields = f; Transform obj2 = ((Component)f.chatTextField).transform.Find("Text Area/Text"); customFields.chatTextFieldGui = ((obj2 != null) ? ((Component)obj2).GetComponent() : null); } if ((Object)(object)f.chatTextRect == (Object)null && (Object)(object)f.chatText != (Object)null) { ((Component)f.chatText).TryGetComponent(ref f.chatTextRect); } if ((Object)(object)f.chatTextBgRect == (Object)null && (Object)(object)f.chatTextField != (Object)null) { Transform obj3 = ((Component)f.chatTextField).transform.parent.Find("Image"); if (obj3 != null) { ((Component)obj3).TryGetComponent(ref f.chatTextBgRect); } } if (f.shiftAction == null) { f.shiftAction = __instance.playerActions.FindAction("taffyko.NiceChat.Shift", false); if (f.shiftAction == null) { __instance.playerActions.Disable(); MovementActions movement = __instance.playerActions.Movement; f.shiftAction = InputActionSetupExtensions.AddAction(MovementActions.op_Implicit(movement), "taffyko.NiceChat.Shift", (InputActionType)1, ((InputControl)Keyboard.current.shiftKey).path, (string)null, (string)null, (string)null, (string)null); __instance.playerActions.Enable(); } InputAction? shiftAction = f.shiftAction; if (shiftAction != null) { shiftAction.Enable(); } } if (f.scrollAction == null) { f.scrollAction = __instance.playerActions.FindAction("taffyko.NiceChat.Scroll", false); if (f.scrollAction == null) { __instance.playerActions.Disable(); MovementActions movement2 = __instance.playerActions.Movement; f.scrollAction = InputActionSetupExtensions.AddAction(MovementActions.op_Implicit(movement2), "taffyko.NiceChat.Scroll", (InputActionType)0, ((InputControl)Mouse.current.scroll).path, (string)null, (string)null, (string)null, (string)null); __instance.playerActions.Enable(); } } if (Plugin.GuiFadeFix) { if ((Object)(object)f.chatContainer == (Object)null) { GameObject val = new GameObject("taffyko.NiceChat.ChatContainer"); f.chatContainer = val.AddComponent(); val.AddComponent(); ((Transform)f.chatContainer).SetParent((Transform)(object)f.hudBottomLeftCorner, false); } RectTransform? chatTextFieldRect = f.chatTextFieldRect; if ((Object)(object)((chatTextFieldRect != null) ? ((Transform)chatTextFieldRect).parent : null) != (Object)(object)f.chatContainer) { RectTransform? chatTextFieldRect2 = f.chatTextFieldRect; if (chatTextFieldRect2 != null) { ((Transform)chatTextFieldRect2).SetParent((Transform)(object)f.chatContainer); } RectTransform? chatTextBgRect = f.chatTextBgRect; if (chatTextBgRect != null) { ((Transform)chatTextBgRect).SetParent((Transform)(object)f.chatContainer); } HUDManager.Instance.Chat.canvasGroup = ((Component)f.chatContainer).GetComponent(); ((Component)f.hudBottomLeftCorner).GetComponent().alpha = 1f; } return; } RectTransform? chatTextFieldRect3 = f.chatTextFieldRect; if ((Object)(object)((chatTextFieldRect3 != null) ? ((Transform)chatTextFieldRect3).parent : null) != (Object)(object)f.hudBottomLeftCorner) { RectTransform? chatTextFieldRect4 = f.chatTextFieldRect; if (chatTextFieldRect4 != null) { ((Transform)chatTextFieldRect4).SetParent((Transform)(object)f.hudBottomLeftCorner); } RectTransform? chatTextBgRect2 = f.chatTextBgRect; if (chatTextBgRect2 != null) { ((Transform)chatTextBgRect2).SetParent((Transform)(object)f.hudBottomLeftCorner); } HUDManager.Instance.Chat.canvasGroup = ((Component)f.hudBottomLeftCorner).GetComponent(); } } [HarmonyPatch(typeof(HUDManager), "SubmitChat_performed")] [HarmonyPrefix] private static bool SubmitChat_performed_Prefix() { InputAction? shiftAction = fields[StartOfRound.Instance.localPlayerController].shiftAction; if (shiftAction == null) { return true; } return !shiftAction.IsPressed(); } [HarmonyPatch(typeof(HUDManager), "PingHUDElement")] [HarmonyPrefix] private static void PingHUDElementPrefix(HUDElement element, ref float delay, float startAlpha, ref float endAlpha) { if (element != null && element == HUDManager.Instance?.Chat) { endAlpha = Plugin.FadeOpacity; if (delay == 4f) { delay = Plugin.FadeTimeAfterMessage; } else if (delay == 2f) { delay = Plugin.FadeTimeAfterOwnMessage; } else if (delay == 1f) { delay = Plugin.FadeTimeAfterUnfocused; } } } public static string GetChatMessageNameOpeningTag() { string text = "#FF0000"; string text2 = ""; if (Plugin.EnableTimestamps && TimeOfDay.Instance.currentDayTimeStarted && (Object)(object)HUDManager.Instance?.clockNumber != (Object)null && ((((UIBehaviour)HUDManager.Instance.clockNumber).IsActive() && HUDManager.Instance.Clock.targetAlpha > 0f) || StartOfRound.Instance.localPlayerController.isPlayerDead)) { text2 = text2 + "[" + ((TMP_Text)HUDManager.Instance.clockNumber).text.Replace("\n", "") + "] "; } if (!(messageContext != null)) { goto IL_010c; } if (messageContext.senderDead) { text2 += ""; if (Plugin.TagMessageStatus) { text2 += "*DEAD* "; } } else { if (!messageContext.walkie) { goto IL_010c; } text2 += ""; if (Plugin.TagMessageStatus) { text2 += "*WALKIE* "; } } goto IL_011e; IL_011e: messageContext = null; return text2; IL_010c: text2 = text2 + ""; goto IL_011e; } public static string GetChatMessageNameClosingTag() { return ": "; } public static bool _HelperMessageSentByLocalPlayer(HUDManager instance, string chatMessage, int playerId) { _ = (int)Traverse.Create((object)instance).Field("__rpc_exec_stage").GetValue(); if (playerId >= 0 && playerId < StartOfRound.Instance.allPlayerScripts.Length && IsLocalPlayer(StartOfRound.Instance.allPlayerScripts[playerId])) { return true; } return false; } [HarmonyPatch(typeof(HUDManager), "AddPlayerChatMessageClientRpc")] [HarmonyTranspiler] private static IEnumerable transpiler_AddPlayerChatMessageClientRpc(IEnumerable instructions, ILGenerator generator) { yield return new CodeInstruction(OpCodes.Ldarg_0, (object)null); yield return new CodeInstruction(OpCodes.Ldarg_1, (object)null); yield return new CodeInstruction(OpCodes.Ldarg_2, (object)null); yield return new CodeInstruction(OpCodes.Call, (object)typeof(Patches).GetMethod("_HelperMessageSentByLocalPlayer")); Label label = generator.DefineLabel(); CodeInstruction nopInstruction = new CodeInstruction(OpCodes.Nop, (object)null); nopInstruction.labels.Add(label); CodeInstruction retInstruction = new CodeInstruction(OpCodes.Ret, (object)null); yield return new CodeInstruction(OpCodes.Brfalse, (object)label); yield return retInstruction; yield return nopInstruction; foreach (CodeInstruction instruction in instructions) { yield return instruction; } } private static bool PlayerCanHearMessage(int senderId, int recipientId, out MessageContext? messageContext) { //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) messageContext = null; if (senderId < 0) { return true; } if ((Object)(object)HUDManager.Instance == (Object)null) { return true; } if (HUDManager.Instance.playersManager.allPlayerScripts.Length <= senderId || HUDManager.Instance.playersManager.allPlayerScripts.Length <= recipientId) { return true; } PlayerControllerB val = HUDManager.Instance.playersManager.allPlayerScripts[senderId]; PlayerControllerB val2 = HUDManager.Instance.playersManager.allPlayerScripts[recipientId]; if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { return true; } bool flag = val.holdingWalkieTalkie && val2.holdingWalkieTalkie; messageContext = new MessageContext(senderId, flag, val.isPlayerDead); if (val2.isPlayerDead) { return true; } if (val.isPlayerDead) { if (ServerVars.hearDeadPlayers.Value || val2.isPlayerDead) { return true; } return false; } if (flag) { return true; } if (Vector3.Distance(((Component)val).transform.position, ((Component)val2).transform.position) <= ServerVars.messageRange.Value) { return true; } return false; } public static bool RecipientCanHear(int recipientId) { if (StartOfRound.Instance.localPlayerController.isPlayerDead) { return true; } MessageContext messageContext; return PlayerCanHearMessage((int)StartOfRound.Instance.localPlayerController.playerClientId, recipientId, out messageContext); } public static bool CanHearPreflight(int senderId) { MessageContext messageContext; bool num = PlayerCanHearMessage(senderId, (int)StartOfRound.Instance.localPlayerController.playerClientId, out messageContext); if (num) { Patches.messageContext = messageContext; } return num; } [HarmonyPatch(typeof(HUDManager), "AddPlayerChatMessageClientRpc")] [HarmonyTranspiler] private static IEnumerable transpiler_CanHearMessageOverride(IEnumerable instructions, ILGenerator generator) { bool deadCheckFound = false; bool distanceCheckFound = false; using IEnumerator e = instructions.GetEnumerator(); while (e.MoveNext()) { if (!deadCheckFound && e.Current.opcode == OpCodes.Ldfld && (FieldInfo)e.Current.operand == FieldInfo_isPlayerDead) { deadCheckFound = true; for (int i = 0; i < 5; i++) { yield return e.Current; e.MoveNext(); } yield return new CodeInstruction(OpCodes.Nop, (object)null); e.MoveNext(); } else if (!distanceCheckFound && e.Current.opcode == OpCodes.Call && (MethodInfo)e.Current.operand == MethodInfo_Vector3_Distance) { distanceCheckFound = true; yield return new CodeInstruction(OpCodes.Pop, (object)null); yield return new CodeInstruction(OpCodes.Pop, (object)null); for (int j = 0; j < 4; j++) { e.MoveNext(); } yield return new CodeInstruction(OpCodes.Ldarg_2, (object)null); yield return new CodeInstruction(OpCodes.Call, (object)MethodInfo_CanHearPreflight); } yield return e.Current; } } public static bool _ShouldSuppressDuplicateMessage(string message, string senderName) { float num = Time.fixedUnscaledTime - timeAtLastCheck; timeAtLastCheck = Time.fixedUnscaledTime; if (string.IsNullOrEmpty(senderName)) { return true; } if (num >= 0f && num < 0.1f) { return true; } return false; } public static int _GetMaxMessageCount() { return Plugin.MaxMessageHistory; } [HarmonyPatch(typeof(HUDManager), "AddChatMessage")] [HarmonyTranspiler] private static IEnumerable transpiler_AddChatMessage(IEnumerable instructions) { bool foundMaxMessageCount = false; bool foundPreviousMessageComparison = false; foreach (CodeInstruction instruction in instructions) { if (!foundMaxMessageCount && instruction.opcode == OpCodes.Ldc_I4_4) { yield return new CodeInstruction(OpCodes.Call, (object)typeof(Patches).GetMethod("_GetMaxMessageCount")); foundMaxMessageCount = true; continue; } if (!foundPreviousMessageComparison && instruction.opcode == OpCodes.Call && instruction.operand == stringEqual) { foundPreviousMessageComparison = true; yield return instruction; yield return new CodeInstruction(OpCodes.Ldarg_1, (object)null); yield return new CodeInstruction(OpCodes.Ldarg_2, (object)null); yield return new CodeInstruction(OpCodes.Call, (object)typeof(Patches).GetMethod("_ShouldSuppressDuplicateMessage")); yield return new CodeInstruction(OpCodes.And, (object)null); continue; } if (instruction.opcode == OpCodes.Ldstr) { switch ((string)instruction.operand) { case "": yield return new CodeInstruction(OpCodes.Call, (object)MethodInfo_GetChatMessageNameOpeningTag); continue; case ": '": yield return new CodeInstruction(OpCodes.Call, (object)MethodInfo_GetChatMessageNameClosingTag); continue; case "'": yield return new CodeInstruction(OpCodes.Ldstr, (object)""); continue; } } yield return instruction; } } public static int GetCharacterLimit() { return Plugin.CharacterLimit + 1; } [HarmonyPatch(typeof(HUDManager), "SubmitChat_performed")] [HarmonyPatch(typeof(HUDManager), "EnableChat_performed")] [HarmonyPatch(typeof(HUDManager), "AddPlayerChatMessageServerRpc")] [HarmonyTranspiler] private static IEnumerable transpiler_GeneralOverrides(IEnumerable instructions) { bool foundCharacterLimit = false; bool foundPlayerDeadCheck = false; foreach (CodeInstruction instruction in instructions) { if (!foundCharacterLimit && instruction.opcode == OpCodes.Ldc_I4_S) { if ((sbyte)instruction.operand == 50) { foundCharacterLimit = true; yield return new CodeInstruction(OpCodes.Call, (object)getCharacterLimit); continue; } } else if (!foundPlayerDeadCheck && instruction.opcode == OpCodes.Ldfld && (FieldInfo)instruction.operand == FieldInfo_isPlayerDead) { foundPlayerDeadCheck = true; yield return new CodeInstruction(OpCodes.Pop, (object)null); yield return new CodeInstruction(OpCodes.Ldc_I4_0, (object)null); continue; } yield return instruction; } } [HarmonyPatch(typeof(HUDManager), "SubmitChat_performed")] [HarmonyTranspiler] private static IEnumerable transpiler_SubmitChat_performed(IEnumerable instructions, ILGenerator generator) { bool distanceCheckFound = false; using IEnumerator e = instructions.GetEnumerator(); while (e.MoveNext()) { if (!distanceCheckFound && e.Current.opcode == OpCodes.Call && (MethodInfo)e.Current.operand == MethodInfo_Vector3_Distance) { distanceCheckFound = true; yield return new CodeInstruction(OpCodes.Pop, (object)null); yield return new CodeInstruction(OpCodes.Pop, (object)null); for (int i = 0; i < 12; i++) { e.MoveNext(); } yield return new CodeInstruction(OpCodes.Ldloc_0, (object)null); yield return new CodeInstruction(OpCodes.Call, (object)typeof(Patches).GetMethod("RecipientCanHear")); } yield return e.Current; } } [HarmonyPatch(typeof(HUDManager), "AddTextToChatOnServer")] [HarmonyPrefix] private static void AddTextToChatOnServer_Prefix(HUDManager __instance, int playerId) { if (playerId >= 0 && playerId < StartOfRound.Instance.allPlayerScripts.Length && IsLocalPlayer(StartOfRound.Instance.allPlayerScripts[playerId])) { CanHearPreflight(playerId); } } } public static class PluginInfo { public const string PLUGIN_GUID = "NiceChat"; public const string PLUGIN_NAME = "NiceChat"; public const string PLUGIN_VERSION = "1.2.8"; } } namespace System.Runtime.CompilerServices { internal static class IsExternalInit { } internal class RequiredMemberAttribute : Attribute { } internal class CompilerFeatureRequiredAttribute : Attribute { public CompilerFeatureRequiredAttribute(string name) { } } [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)] public sealed class SetsRequiredMembersAttribute : Attribute { } }