Decompiled source of NiceChat v1.2.7

BepInEx/plugins/NiceChat.dll

Decompiled a month ago
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.7.0")]
[assembly: AssemblyInformationalVersion("1.2.7+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]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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<IServerVar> AllServerVars;

		void TryRegister();

		static IServerVar()
		{
			AllServerVars = new List<IServerVar>();
		}
	}
	public class ServerVar<T> : IServerVar, IDisposable where T : IEquatable<T>
	{
		public delegate void ReadFromReader<T1>(FastBufferReader reader, out T1 value);

		private T value;

		private Action<FastBufferWriter, T> writeValue;

		private ReadFromReader<T> 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<T>.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<FastBufferWriter, T> write, ReadFromReader<T> 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.7")]
	public class Plugin : BaseUnityPlugin
	{
		private delegate bool ParseConfigValue<T>(string input, out T output);

		public const string modGUID = "taffyko.NiceChat";

		public const string modName = "NiceChat";

		public const string modVersion = "1.2.7";

		private readonly Harmony harmony = new Harmony("taffyko.NiceChat");

		public static ManualLogSource log = null;

		internal static List<Action> cleanupActions = new List<Action>();

		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<int>("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<int>(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<int>(ref v, default(ForPrimitives));
			}, 49);
			ServerVars.hearDeadPlayers = new ServerVar<bool>("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<bool>(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<bool>(ref v, default(ForPrimitives));
			}, defaultValue: false);
			ServerVars.messageRange = new ServerVar<float>("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<float>(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<float>(ref v, default(ForPrimitives));
			}, 25f);
			ServerVars.modVersion = new ServerVar<string>("", 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<string>("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<Color>)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<T>(string category, string name, T defaultValue, string description, ParseConfigValue<T> tryParse, bool hostControlled = false)
		{
			ConfEntryInternal(category, name, defaultValue, description, tryParse, hostControlled);
		}

		private void ConfEntry<T>(string category, string name, T defaultValue, string description, ParseConfigValue<T> tryParse, T vanillaValue, bool hostControlled = false)
		{
			ConfEntryInternal(category, name, defaultValue, description, tryParse, hostControlled, ConfEntryToString(vanillaValue));
		}

		private void ConfEntryInternal<T>(string category, string name, T defaultValue, string description, ParseConfigValue<T> tryParse, bool hostControlled = false, string? vanillaValueText = null)
		{
			ParseConfigValue<T> tryParse2 = tryParse;
			T defaultValue2 = defaultValue;
			PropertyInfo property = typeof(Plugin).GetProperty(name);
			string text = "[default: " + ConfEntryToString(defaultValue2) + "]\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<string> config = ((BaseUnityPlugin)this).Config.Bind<string>(category, name, "default", text);
			if (string.IsNullOrEmpty(config.Value))
			{
				config.Value = "default";
			}
			T output;
			bool flag = tryParse2(config.Value, out output) && config.Value != "default";
			property.SetValue(null, flag ? output : defaultValue2);
			if (!flag)
			{
				config.Value = "default";
			}
			EventHandler loadConfig = delegate
			{
				T output2;
				bool flag2 = tryParse2(config.Value, out output2) && config.Value != "default";
				property.SetValue(null, flag2 ? output2 : defaultValue2);
			};
			config.SettingChanged += loadConfig;
			cleanupActions.Add(delegate
			{
				config.SettingChanged -= loadConfig;
				property.SetValue(null, defaultValue2);
			});
		}

		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<int> characterLimit;

		public static ServerVar<bool> hearDeadPlayers;

		public static ServerVar<float> messageRange;

		public static ServerVar<string> 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<Action> cleanupActions = new List<Action>();
		}

		private record MessageContext(int senderId, bool walkie, bool senderDead);

		public static Dictionary<PlayerControllerB, CustomFields> fields = new Dictionary<PlayerControllerB, CustomFields>();

		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<CanvasGroup>().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, Mathf.Max(item.targetAlpha, item.canvasGroup.alpha))).ToArray();
					customFields.restoreHiddenHudElementsAction = delegate
					{
						(HUDElement, float)[] array3 = hudElementsAlphas;
						for (int j = 0; j < array3.Length; j++)
						{
							var (val12, num6) = array3[j];
							if (val12 != hud.Chat)
							{
								hud.PingHUDElement(val12, 0f, num6, num6);
							}
						}
						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 num = customFields.chatText.maxVisibleCharacters / 10;
					while (customFields.chatText.text.Length > customFields.chatText.maxVisibleCharacters - num)
					{
						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<RectTransform>() : null);
				if ((Object)(object)customFields.scrollContainerRect == (Object)null)
				{
					GameObject val2 = new GameObject
					{
						name = "ChatScrollContainer"
					};
					customFields.scrollContainerRect = val2.AddComponent<RectTransform>();
					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<RectTransform>();
					val3.AddComponent<Image>().sprite = Sprite.Create(Texture2D.whiteTexture, new Rect(0f, 0f, 1f, 1f), new Vector2(0f, 0f));
					val3.AddComponent<Mask>().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<LayoutElement>(ref val5);
					Object.Destroy((Object)(object)val5);
					val5 = ((Component)customFields.chatText).gameObject.AddComponent<LayoutElement>();
					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<ContentSizeFitter>(ref val6);
					Object.Destroy((Object)(object)val6);
					ContentSizeFitter obj3 = ((Component)customFields.chatText).gameObject.AddComponent<ContentSizeFitter>();
					obj3.verticalFit = (FitMode)2;
					obj3.horizontalFit = (FitMode)0;
					customFields.scroll = val2.AddComponent<ScrollRect>();
					customFields.scroll.content = customFields.chatTextRect;
					customFields.scroll.viewport = val4;
					customFields.scroll.vertical = true;
					customFields.scroll.horizontal = false;
					customFields.scroll.verticalNormalizedPosition = 0f;
					GameObject val7 = new GameObject
					{
						name = "Scrollbar"
					};
					customFields.scrollbarCanvasGroup = val7.AddComponent<CanvasGroup>();
					RectTransform val8 = val7.AddComponent<RectTransform>();
					((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<Scrollbar>();
					Image obj4 = val7.AddComponent<Image>();
					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<RectTransform>();
					((Transform)val10).SetParent((Transform)(object)val8, false);
					val10.offsetMin = Vector2.zero;
					val10.offsetMax = Vector2.zero;
					Image obj5 = val9.AddComponent<Image>();
					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<LayoutElement>(ref val11);
			if ((Object)(object)val11 != (Object)null)
			{
				RectTransform component = ((Component)((Transform)customFields.chatTextRect).parent).GetComponent<RectTransform>();
				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 num2 = customFields.scrollAction.ReadValue<Vector2>().y / 120f;
				float num3 = num2;
				rect = customFields.chatTextRect.rect;
				num2 = num3 / ((Rect)(ref rect)).height;
				num2 *= 30f;
				ScrollRect? scroll = customFields.scroll;
				scroll.verticalNormalizedPosition += num2;
			}
			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<Image>()).color = new Color(0f, 0f, 0f, 0f);
			}
			else
			{
				((Graphic)((Component)customFields.scrollbar.handleRect).GetComponent<Image>()).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 num4 = (1f - customFields.previousScrollPosition) * customFields.previousChatTextHeight;
							rect = customFields.chatTextRect.rect;
							float num5 = ((Rect)(ref rect)).height - num4;
							ScrollRect? scroll2 = customFields.scroll;
							rect = customFields.chatTextRect.rect;
							scroll2.verticalNormalizedPosition = num5 / ((Rect)(ref rect)).height;
							goto IL_0ab5;
						}
					}
					customFields.scroll.verticalNormalizedPosition = 0f;
					goto IL_0ab5;
				}
			}
			else
			{
				customFields.scroll.verticalNormalizedPosition = 0f;
			}
			goto IL_0ae1;
			IL_0ae1:
			customFields.scrollbarCanvasGroup.alpha = ((Plugin.ShowScrollbar && customFields.chatTextField.isFocused) ? 1f : 0f);
			customFields.previousScrollPosition = customFields.scroll.verticalNormalizedPosition;
			return;
			IL_0ab5:
			rect = customFields.chatTextRect.rect;
			customFields.previousChatTextHeight = ((Rect)(ref rect)).height;
			goto IL_0ae1;
		}

		[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.7";
				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<RectTransform>(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<TextMeshProUGUI>() : null);
			}
			if ((Object)(object)f.chatTextRect == (Object)null && (Object)(object)f.chatText != (Object)null)
			{
				((Component)f.chatText).TryGetComponent<RectTransform>(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<RectTransform>(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<RectTransform>();
					val.AddComponent<CanvasGroup>();
					((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<CanvasGroup>();
					((Component)f.hudBottomLeftCorner).GetComponent<CanvasGroup>().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<CanvasGroup>();
			}
		}

		[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 + "<color=#7069ff>[" + ((TMP_Text)HUDManager.Instance.clockNumber).text.Replace("\n", "") + "] </color>";
			}
			if (!(messageContext != null))
			{
				goto IL_010c;
			}
			if (messageContext.senderDead)
			{
				text2 += "<color=#878787>";
				if (Plugin.TagMessageStatus)
				{
					text2 += "*DEAD* ";
				}
			}
			else
			{
				if (!messageContext.walkie)
				{
					goto IL_010c;
				}
				text2 += "<color=#00AA00>";
				if (Plugin.TagMessageStatus)
				{
					text2 += "*WALKIE* ";
				}
			}
			goto IL_011e;
			IL_011e:
			messageContext = null;
			return text2;
			IL_010c:
			text2 = text2 + "<color=" + text + ">";
			goto IL_011e;
		}

		public static string GetChatMessageNameClosingTag()
		{
			return "</color>: <color=#FFFF00>";
		}

		public static bool _HelperMessageSentByLocalPlayer(HUDManager instance, string chatMessage, int playerId)
		{
			if ((int)Traverse.Create((object)instance).Field("__rpc_exec_stage").GetValue() == 2 && playerId >= 0 && playerId < StartOfRound.Instance.allPlayerScripts.Length && IsLocalPlayer(StartOfRound.Instance.allPlayerScripts[playerId]))
			{
				return true;
			}
			return false;
		}

		[HarmonyPatch(typeof(HUDManager), "AddPlayerChatMessageClientRpc")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> transpiler_AddPlayerChatMessageClientRpc(IEnumerable<CodeInstruction> 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<CodeInstruction> transpiler_CanHearMessageOverride(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
		{
			bool deadCheckFound = false;
			bool distanceCheckFound = false;
			using IEnumerator<CodeInstruction> 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<CodeInstruction> transpiler_AddChatMessage(IEnumerable<CodeInstruction> 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 "<color=#FF0000>":
						yield return new CodeInstruction(OpCodes.Call, (object)MethodInfo_GetChatMessageNameOpeningTag);
						continue;
					case "</color>: <color=#FFFF00>'":
						yield return new CodeInstruction(OpCodes.Call, (object)MethodInfo_GetChatMessageNameClosingTag);
						continue;
					case "'</color>":
						yield return new CodeInstruction(OpCodes.Ldstr, (object)"</color>");
						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<CodeInstruction> transpiler_GeneralOverrides(IEnumerable<CodeInstruction> 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<CodeInstruction> transpiler_SubmitChat_performed(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
		{
			bool distanceCheckFound = false;
			using IEnumerator<CodeInstruction> 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.7";
	}
}
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
	{
	}
}