Decompiled source of WhoIsTalking v1.0.1

WhoIsTalking.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("WhoIsTalking")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("WhoIsTalking")]
[assembly: AssemblyTitle("WhoIsTalking")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[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 WhoIsTalkingMod
{
	[BepInPlugin("WhoIsTalking", "WhoIsTalking", "1.0.1")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "WhoIsTalking";

		public const string Name = "WhoIsTalking";

		public const string Version = "1.0.1";

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> ShowSelf;

		internal static ConfigEntry<bool> ShowDeadWhileAlive;

		internal static ConfigEntry<int> MaxRows;

		internal static ConfigEntry<float> FadeSeconds;

		internal static ConfigEntry<float> Scale;

		internal static ConfigEntry<float> OffsetX;

		internal static ConfigEntry<float> OffsetY;

		private void Awake()
		{
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			MigrateOldConfig("markj.whoistalking");
			ShowSelf = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowYourself", true, "Show your own name when you talk.");
			ShowDeadWhileAlive = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowDeadPlayersWhileAlive", false, "Dead players can only be heard by other dead players. Leave this off so the list doesn't show talkers you can't hear.");
			MaxRows = ((BaseUnityPlugin)this).Config.Bind<int>("Layout", "MaxNames", 8, "Most names shown at once.");
			FadeSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Layout", "FadeSeconds", 0.6f, "How long a name stays after someone stops talking.");
			Scale = ((BaseUnityPlugin)this).Config.Bind<float>("Layout", "Scale", 1f, "Size of the list. 1 = normal.");
			OffsetX = ((BaseUnityPlugin)this).Config.Bind<float>("Layout", "OffsetFromRight", 24f, "Gap from the right edge of the screen (pixels at 1080p).");
			OffsetY = ((BaseUnityPlugin)this).Config.Bind<float>("Layout", "OffsetFromBottom", 140f, "Gap from the bottom edge of the screen (pixels at 1080p).");
			new Harmony("WhoIsTalking").PatchAll(typeof(Patches));
			Log.LogInfo((object)"WhoIsTalking 1.0.1 loaded.");
		}

		private void MigrateOldConfig(string oldId)
		{
			try
			{
				string text = Path.Combine(Paths.ConfigPath, oldId + ".cfg");
				if (File.Exists(text))
				{
					if (!File.Exists(((BaseUnityPlugin)this).Config.ConfigFilePath))
					{
						File.Copy(text, ((BaseUnityPlugin)this).Config.ConfigFilePath);
						((BaseUnityPlugin)this).Config.Reload();
						((BaseUnityPlugin)this).Logger.LogInfo((object)("Moved settings from " + oldId + ".cfg"));
					}
					File.Delete(text);
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Couldn't move old settings from " + oldId + ".cfg: " + ex.Message));
			}
		}
	}
	[HarmonyPatch]
	internal static class Patches
	{
		private static bool _loggedError;

		[HarmonyPatch(typeof(PlayerControllerB), "Update")]
		[HarmonyPostfix]
		private static void PlayerUpdate()
		{
			try
			{
				VoiceHud.Tick();
			}
			catch (Exception ex)
			{
				if (!_loggedError)
				{
					_loggedError = true;
					Plugin.Log.LogError((object)("Voice list update failed: " + ex));
				}
			}
		}
	}
	internal static class VoiceHud
	{
		private class Row
		{
			public RectTransform Rt;

			public CanvasGroup Group;

			public Image Dot;

			public Image Ring;

			public TextMeshProUGUI Tmp;

			public Text Legacy;

			public float LastSpoke = -999f;

			public float StartedSpeaking;

			public bool WasSpeaking;

			public float SmoothAmp;
		}

		private const float RowHeight = 34f;

		private const float RowWidth = 260f;

		private const float RowGap = 6f;

		private static int _lastFrame = -1;

		private static GameObject _canvasGo;

		private static RectTransform _root;

		private static TMP_FontAsset _font;

		private static Sprite _circle;

		private static Sprite _panel;

		private static readonly Dictionary<PlayerControllerB, Row> Rows = new Dictionary<PlayerControllerB, Row>();

		private static bool _loggedVoiceMissing;

		private static readonly Dictionary<(Type, string), MemberInfo> Members = new Dictionary<(Type, string), MemberInfo>();

		public static void Tick()
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_0638: 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_066b: Unknown result type (might be due to invalid IL or missing references)
			//IL_067f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0686: Unknown result type (might be due to invalid IL or missing references)
			//IL_06b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_036c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0356: Unknown result type (might be due to invalid IL or missing references)
			//IL_0371: 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_03c2: Unknown result type (might be due to invalid IL or missing references)
			if (Time.frameCount == _lastFrame)
			{
				return;
			}
			_lastFrame = Time.frameCount;
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance == (Object)null || instance.allPlayerScripts == null)
			{
				if ((Object)(object)_canvasGo != (Object)null)
				{
					_canvasGo.SetActive(false);
				}
				return;
			}
			EnsureCanvas();
			if (!_canvasGo.activeSelf)
			{
				_canvasGo.SetActive(true);
			}
			((Transform)_root).localScale = Vector3.one * Mathf.Clamp(Plugin.Scale.Value, 0.3f, 3f);
			_root.anchoredPosition = new Vector2(0f - Plugin.OffsetX.Value, Plugin.OffsetY.Value);
			PlayerControllerB val = FindLocal(instance);
			object obj = Get(instance, "voiceChatModule");
			object obj2 = null;
			if (obj != null)
			{
				string text = Get(obj, "LocalPlayerName") as string;
				if (!string.IsNullOrEmpty(text))
				{
					obj2 = Call(obj, "FindPlayer", text);
				}
			}
			float now = Time.unscaledTime;
			bool flag = (Object)(object)val != (Object)null && !val.isPlayerDead;
			PlayerControllerB[] allPlayerScripts = instance.allPlayerScripts;
			bool flag3 = default(bool);
			foreach (PlayerControllerB val2 in allPlayerScripts)
			{
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				bool num = val2.isPlayerControlled || val2.isPlayerDead;
				bool flag2 = (Object)(object)val2 == (Object)(object)val;
				if (!num || (flag2 && !Plugin.ShowSelf.Value) || (val2.isPlayerDead && flag && !Plugin.ShowDeadWhileAlive.Value && !flag2))
				{
					if (Rows.TryGetValue(val2, out var value))
					{
						value.LastSpoke = -999f;
					}
					continue;
				}
				object obj3 = (flag2 ? (obj2 ?? Get(val2, "voicePlayerState")) : Get(val2, "voicePlayerState"));
				if (obj3 == null)
				{
					if (!_loggedVoiceMissing && !flag2 && val2.isPlayerControlled && instance.connectedPlayersAmount > 0)
					{
						_loggedVoiceMissing = true;
						Plugin.Log.LogInfo((object)("No voice data yet for " + val2.playerUsername + " (normal for a few seconds after they join)."));
					}
					continue;
				}
				object obj4 = Get(obj3, "IsSpeaking");
				int num2;
				if (obj4 is bool)
				{
					flag3 = (bool)obj4;
					num2 = 1;
				}
				else
				{
					num2 = 0;
				}
				bool flag4 = (byte)((uint)num2 & (flag3 ? 1u : 0u)) != 0;
				float num3 = ((Get(obj3, "Amplitude") is float num4) ? num4 : 0f);
				if (!Rows.TryGetValue(val2, out var value2) || (Object)(object)value2.Rt == (Object)null)
				{
					value2 = CreateRow();
					Rows[val2] = value2;
				}
				if (flag4)
				{
					if (!value2.WasSpeaking)
					{
						value2.StartedSpeaking = now;
					}
					value2.LastSpoke = now;
				}
				value2.WasSpeaking = flag4;
				value2.SmoothAmp = Mathf.Lerp(value2.SmoothAmp, flag4 ? num3 : 0f, 1f - Mathf.Exp((0f - Time.unscaledDeltaTime) * 18f));
				string text2 = val2.playerUsername + (val2.isPlayerDead ? "  (dead)" : "");
				Color color = (Color)(val2.isPlayerDead ? new Color(0.7f, 0.7f, 0.7f) : Color.white);
				if ((Object)(object)value2.Tmp != (Object)null)
				{
					((TMP_Text)value2.Tmp).text = text2;
					((Graphic)value2.Tmp).color = color;
				}
				if ((Object)(object)value2.Legacy != (Object)null)
				{
					value2.Legacy.text = text2;
					((Graphic)value2.Legacy).color = color;
				}
			}
			foreach (PlayerControllerB item in Rows.Keys.Where((PlayerControllerB k) => (Object)(object)k == (Object)null).ToList())
			{
				if ((Object)(object)Rows[item].Rt != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)Rows[item].Rt).gameObject);
				}
				Rows.Remove(item);
			}
			float fade = Mathf.Max(0.05f, Plugin.FadeSeconds.Value);
			List<Row> list = (from kv in (from kv in Rows
					where (Object)(object)kv.Value.Rt != (Object)null && now - kv.Value.LastSpoke < fade
					orderby kv.Value.StartedSpeaking descending
					select kv).Take(Mathf.Max(1, Plugin.MaxRows.Value))
				select kv.Value).ToList();
			foreach (Row value3 in Rows.Values)
			{
				if ((Object)(object)value3.Rt != (Object)null && !list.Contains(value3) && ((Component)value3.Rt).gameObject.activeSelf)
				{
					((Component)value3.Rt).gameObject.SetActive(false);
				}
			}
			for (int num5 = 0; num5 < list.Count; num5++)
			{
				Row row = list[num5];
				if (!((Component)row.Rt).gameObject.activeSelf)
				{
					((Component)row.Rt).gameObject.SetActive(true);
				}
				row.Rt.anchoredPosition = new Vector2(0f, (float)num5 * 40f);
				bool wasSpeaking = row.WasSpeaking;
				row.Group.alpha = (wasSpeaking ? 1f : Mathf.Clamp01(1f - (now - row.LastSpoke) / fade));
				float num6 = Mathf.Clamp01(row.SmoothAmp * 10f);
				((Transform)((Graphic)row.Dot).rectTransform).localScale = Vector3.one * (0.75f + num6 * 0.45f);
				((Graphic)row.Dot).color = Color.Lerp(new Color(0.2f, 0.75f, 0.3f), new Color(0.45f, 1f, 0.5f), num6);
				((Graphic)row.Ring).color = new Color(0.45f, 1f, 0.5f, 0.15f + num6 * 0.6f);
			}
		}

		private static PlayerControllerB FindLocal(StartOfRound sor)
		{
			PlayerControllerB[] allPlayerScripts = sor.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if ((Object)(object)val != (Object)null && ((NetworkBehaviour)val).IsOwner && val.isPlayerControlled)
				{
					return val;
				}
			}
			if ((Object)(object)sor.localPlayerController != (Object)null)
			{
				return sor.localPlayerController;
			}
			if (!((Object)(object)GameNetworkManager.Instance != (Object)null))
			{
				return null;
			}
			return GameNetworkManager.Instance.localPlayerController;
		}

		private static void EnsureCanvas()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Expected O, but got Unknown
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_canvasGo != (Object)null))
			{
				_canvasGo = new GameObject("WhoIsTalkingCanvas");
				Object.DontDestroyOnLoad((Object)(object)_canvasGo);
				Canvas obj = _canvasGo.AddComponent<Canvas>();
				obj.renderMode = (RenderMode)0;
				obj.sortingOrder = 60;
				CanvasScaler obj2 = _canvasGo.AddComponent<CanvasScaler>();
				obj2.uiScaleMode = (ScaleMode)1;
				obj2.referenceResolution = new Vector2(1920f, 1080f);
				obj2.matchWidthOrHeight = 1f;
				GameObject val = new GameObject("List", new Type[1] { typeof(RectTransform) });
				val.transform.SetParent(_canvasGo.transform, false);
				_root = (RectTransform)val.transform;
				RectTransform root = _root;
				RectTransform root2 = _root;
				Vector2 val2 = default(Vector2);
				((Vector2)(ref val2))..ctor(1f, 0f);
				root2.anchorMax = val2;
				root.anchorMin = val2;
				_root.pivot = new Vector2(1f, 0f);
				_root.sizeDelta = new Vector2(260f, 34f);
				Rows.Clear();
			}
		}

		private static Row CreateRow()
		{
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Expected O, but got Unknown
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Expected O, but got Unknown
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Expected O, but got Unknown
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_font == (Object)null && (Object)(object)HUDManager.Instance != (Object)null)
			{
				_font = (from t in ((Component)HUDManager.Instance).GetComponentsInChildren<TextMeshProUGUI>(true)
					select ((TMP_Text)t).font).FirstOrDefault((Func<TMP_FontAsset, bool>)((TMP_FontAsset f) => (Object)(object)f != (Object)null));
			}
			if ((Object)(object)_font == (Object)null)
			{
				_font = (from t in Object.FindObjectsOfType<TextMeshProUGUI>()
					select ((TMP_Text)t).font).FirstOrDefault((Func<TMP_FontAsset, bool>)((TMP_FontAsset f) => (Object)(object)f != (Object)null));
			}
			GameObject val = new GameObject("Speaker", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent((Transform)(object)_root, false);
			RectTransform val2 = (RectTransform)val.transform;
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(1f, 0f);
			val2.anchorMax = val3;
			val2.anchorMin = val3;
			val2.pivot = new Vector2(1f, 0f);
			val2.sizeDelta = new Vector2(260f, 34f);
			CanvasGroup val4 = val.AddComponent<CanvasGroup>();
			val4.blocksRaycasts = false;
			val4.interactable = false;
			Image obj = val.AddComponent<Image>();
			obj.sprite = PanelSprite();
			obj.type = (Type)1;
			((Graphic)obj).color = new Color(0f, 0f, 0f, 0.55f);
			((Graphic)obj).raycastTarget = false;
			Image ring = MakeCircle(val2, "Ring", 26f);
			Image dot = MakeCircle(val2, "Dot", 16f);
			GameObject val5 = new GameObject("Name", new Type[1] { typeof(RectTransform) });
			val5.transform.SetParent((Transform)(object)val2, false);
			RectTransform val6 = (RectTransform)val5.transform;
			val6.anchorMin = new Vector2(0f, 0f);
			val6.anchorMax = new Vector2(1f, 1f);
			val6.offsetMin = new Vector2(12f, 0f);
			val6.offsetMax = new Vector2(-40f, 0f);
			Row row = new Row
			{
				Rt = val2,
				Group = val4,
				Dot = dot,
				Ring = ring
			};
			if ((Object)(object)_font != (Object)null)
			{
				row.Tmp = val5.AddComponent<TextMeshProUGUI>();
				((TMP_Text)row.Tmp).font = _font;
				((TMP_Text)row.Tmp).fontSize = 18f;
				((TMP_Text)row.Tmp).alignment = (TextAlignmentOptions)4100;
				((TMP_Text)row.Tmp).overflowMode = (TextOverflowModes)1;
				((Graphic)row.Tmp).raycastTarget = false;
			}
			else
			{
				row.Legacy = val5.AddComponent<Text>();
				row.Legacy.font = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
				row.Legacy.fontSize = 18;
				row.Legacy.alignment = (TextAnchor)5;
				((Graphic)row.Legacy).raycastTarget = false;
			}
			val.SetActive(false);
			return row;
		}

		private static Image MakeCircle(RectTransform parent, string name, float size)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val.transform.SetParent((Transform)(object)parent, false);
			RectTransform val2 = (RectTransform)val.transform;
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(1f, 0.5f);
			val2.anchorMax = val3;
			val2.anchorMin = val3;
			val2.pivot = new Vector2(0.5f, 0.5f);
			val2.anchoredPosition = new Vector2(-20f, 0f);
			val2.sizeDelta = new Vector2(size, size);
			Image obj = val.AddComponent<Image>();
			obj.sprite = CircleSprite();
			((Graphic)obj).raycastTarget = false;
			return obj;
		}

		private static Sprite CircleSprite()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_circle != (Object)null)
			{
				return _circle;
			}
			Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false)
			{
				filterMode = (FilterMode)1,
				wrapMode = (TextureWrapMode)1
			};
			Color32[] array = (Color32[])(object)new Color32[4096];
			float num = 32f;
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					float num2 = Vector2.Distance(new Vector2((float)j + 0.5f, (float)i + 0.5f), new Vector2(num, num));
					byte b = (byte)(Mathf.Clamp01(num - num2) * 255f);
					array[i * 64 + j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, b);
				}
			}
			val.SetPixels32(array);
			val.Apply();
			_circle = Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 100f);
			return _circle;
		}

		private static Sprite PanelSprite()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_panel != (Object)null)
			{
				return _panel;
			}
			Texture2D val = new Texture2D(32, 32, (TextureFormat)4, false)
			{
				filterMode = (FilterMode)1,
				wrapMode = (TextureWrapMode)1
			};
			Color32[] array = (Color32[])(object)new Color32[1024];
			for (int i = 0; i < 32; i++)
			{
				for (int j = 0; j < 32; j++)
				{
					float num = Mathf.Clamp((float)j + 0.5f, 10f, 22f);
					float num2 = Mathf.Clamp((float)i + 0.5f, 10f, 22f);
					float num3 = Vector2.Distance(new Vector2((float)j + 0.5f, (float)i + 0.5f), new Vector2(num, num2));
					byte b = (byte)(Mathf.Clamp01(10f - num3) * 255f);
					array[i * 32 + j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, b);
				}
			}
			val.SetPixels32(array);
			val.Apply();
			_panel = Sprite.Create(val, new Rect(0f, 0f, 32f, 32f), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, new Vector4(11f, 11f, 11f, 11f));
			return _panel;
		}

		private static object Get(object obj, string name)
		{
			if (obj == null)
			{
				return null;
			}
			(Type, string) key = (obj.GetType(), name);
			if (!Members.TryGetValue(key, out var value))
			{
				value = (MemberInfo)(((object)AccessTools.Property(obj.GetType(), name)) ?? ((object)AccessTools.Field(obj.GetType(), name)));
				Members[key] = value;
				if (value == null)
				{
					Plugin.Log.LogWarning((object)("Voice chat member not found: " + obj.GetType().Name + "." + name));
				}
			}
			try
			{
				if (value is PropertyInfo propertyInfo)
				{
					return propertyInfo.GetValue(obj);
				}
				if (value is FieldInfo fieldInfo)
				{
					return fieldInfo.GetValue(obj);
				}
			}
			catch
			{
			}
			return null;
		}

		private static object Call(object obj, string name, params object[] args)
		{
			try
			{
				return AccessTools.Method(obj.GetType(), name, args.Select((object a) => a.GetType()).ToArray(), (Type[])null)?.Invoke(obj, args);
			}
			catch
			{
				return null;
			}
		}
	}
}